Developers
SDK Docs
Official client libraries for the Data Captain US ETF API. Same API key as the REST docs — typed helpers for list, screener, backtest, and portfolio.
Install
npm / yarn / pnpm
npm install datacaptain
# yarn add datacaptain
# pnpm add datacaptainpip
pip install datacaptain
# python -m pip install datacaptainRequires Node.js 18+ (native fetch) or Python 3.9+.
Authentication
Create a key in Dashboard → API Keys. The SDK sends it as the x-api-key header. Default API origin is https://datacaptain.up.railway.app (override with baseUrl / base_url — origin only, no /api suffix).
TypeScript / JavaScript
Package: datacaptain on npm
Quick start
TypeScript
import { DataCaptain, DataCaptainError } from "datacaptain";
const dc = new DataCaptain({
apiKey: process.env.DATACAPTAIN_API_KEY!,
// baseUrl: "https://datacaptain.up.railway.app", // optional
});
try {
const usage = await dc.developer.usage();
const list = await dc.etf.list({ search: "SPY", limit: 10 });
const prices = await dc.prices.batch(["SPY", "QQQ", "VOO"]);
const status = await dc.market.status();
const rankings = await dc.etf.rankings({
category: "return",
period: "1y",
limit: 20,
});
const screen = await dc.etf.screener({
returnMin: 10,
period: "1y",
sort: "return",
});
const heatmap = await dc.etf.heatmap({ basket: "broad", period: "1y" });
const backtest = await dc.backtest.buyAndHold({
symbol: "SPY",
investment: 10_000,
startDate: "2020-01-01",
endDate: "2024-12-31",
});
const compare = await dc.backtest.compare({
symbols: ["SPY", "QQQ", "VOO"],
investment: 10_000,
startDate: "2018-01-01",
endDate: "2024-12-31",
});
const rebalance = await dc.portfolio.rebalance({
holdings: [
{ symbol: "SPY", value: 6000 },
{ symbol: "BND", value: 4000 },
],
target: [
{ symbol: "SPY", weight: 0.6 },
{ symbol: "BND", weight: 0.4 },
],
driftThreshold: 0.02,
});
console.log({ usage, list, prices, status, rankings, screen, heatmap, backtest, compare, rebalance });
} catch (err) {
if (err instanceof DataCaptainError) {
console.error(err.message, err.statusCode, err.code);
}
throw err;
}Namespaces
dc.developer.usage()— plan & daily quotadc.market.status()— US market open/closeddc.prices.batch(symbols)— latest pricesdc.etf.*— list, get, screener, rankings, heatmapdc.backtest.*— buyAndHold, comparedc.portfolio.rebalance()— target weights
Python
Package: datacaptain on PyPI (stdlib HTTP — no extra deps)
Quick start
Python
import os
from datacaptain import DataCaptain, DataCaptainError
dc = DataCaptain(
api_key=os.environ["DATACAPTAIN_API_KEY"],
# base_url="https://datacaptain.up.railway.app", # optional
)
try:
usage = dc.developer_usage()
etfs = dc.etf_list(search="SPY", limit=10)
detail = dc.etf_get("SPY")
screen = dc.etf_screener(
return_min=10,
dividend_yield_min=2,
period="1y",
sort="return",
)
heatmap = dc.etf_heatmap(basket="broad", period="1y")
prices = dc.batch_prices(["SPY", "QQQ", "VOO"])
status = dc.market_status()
bt = dc.backtest_buy_and_hold(
symbol="SPY",
start_date="2020-01-01",
end_date="2024-12-31",
investment=10000,
)
compare = dc.backtest_compare(
symbols=["SPY", "QQQ", "VOO"],
start_date="2018-01-01",
end_date="2024-12-31",
investment=10000,
)
rebalance = dc.portfolio_rebalance(
holdings=[
{"symbol": "VOO", "shares": 63},
{"symbol": "QQQ", "shares": 37},
],
target=[
{"symbol": "VOO", "weight": 60},
{"symbol": "QQQ", "weight": 40},
],
drift_threshold=2,
)
print(usage, etfs["total"], bt.get("totalReturn"))
except DataCaptainError as e:
print(str(e), e.status_code, e.code)Method map
| Capability | TypeScript | Python |
|---|---|---|
| Usage | dc.developer.usage() | dc.developer_usage() |
| Market status | dc.market.status() | dc.market_status() |
| Batch prices | dc.prices.batch([...]) | dc.batch_prices([...]) |
| ETF list | dc.etf.list({...}) | dc.etf_list(...) |
| ETF detail | dc.etf.get('SPY') | dc.etf_get('SPY') |
| Screener | dc.etf.screener({...}) | dc.etf_screener(...) |
| Rankings | dc.etf.rankings({...}) | — (use REST /etf/rankings) |
| Heatmap | dc.etf.heatmap({...}) | dc.etf_heatmap(...) |
| Backtest | dc.backtest.buyAndHold({...}) | dc.backtest_buy_and_hold(...) |
| Compare | dc.backtest.compare({...}) | dc.backtest_compare(...) |
| Rebalance | dc.portfolio.rebalance({...}) | dc.portfolio_rebalance(...) |
Errors
Both SDKs throw DataCaptainError with statusCode / status_code and optional code (plan limits, not found, etc.).