Sources
Built-in historical data sources: venue REST, mock walk, CSV upload — contracts, config, and fallbacks.
This page
Sources
Abstract
A source loads a finite window of OHLCV bars for the chart and engine. Sources live in src/sources/catalog.ts and register into the unified registry via ensureSourcesRegistered().
Conceptual model
Rendering…
Built-in catalog
| id | Name | Network | Notes |
|---|---|---|---|
binance-rest | Binance REST | yes | Public klines; synthetic walk fallback only when fallback: true (default off) |
okx-rest | OKX REST | yes | Candles; symbol BTCUSDT → BTC-USDT; max 300 bars |
bybit-rest | Bybit REST | yes | Spot v5 klines; newest-first reversed |
coinbase-rest | Coinbase REST | yes | Exchange candles; USDT pair rewritten to USD product |
kraken-rest | Kraken REST | yes | Public OHLC; pairs with kraken-ws |
mexc-rest | MEXC REST | yes | Public spot klines (api.mexc.com); 1h → 60m; pairs with mexc-ws |
mock-walk | Mock Walk | no | Offline random walk; optional Mulberry-like seed |
csv-upload | CSV / JSON Upload | no | Reads last upload from upload-store |
UI order is BUILTIN_SOURCES array order (Binance first).
Interface surface
Every source implements SourcePlugin (contracts):
fetchHistorical({
symbol,
interval,
limit?,
startTime?, // unix seconds (optional)
endTime?, // unix seconds (optional) — walk-back pagination
signal?, // AbortSignal for background jobs
config?,
}): Promise<Bar[]>
One-shot Load vs Data Source Manager
| Path | Behavior |
|---|---|
src/data/load-symbol.ts | Single fetchHistorical (limit from Settings historyBars) → chart |
| Data Source Manager | Multi-page walk-back with endTime only per page, then validate + gap-fill, durable IDB cache |
Do not pass startTime + endTime together when paginating on Binance-style venues: they return the first N bars from startTime, which can falsely complete a multi-year job in one page.
Config highlights
binance-rest
| Key | Default | Meaning |
|---|---|---|
baseUrl | https://api.binance.com | Override for mirrors/proxies |
limit | 500 | 50–1000 |
fallback | false | On network error, synthesizeWalk (demo only) |
When Settings → Data has a Binance key in the session vault, Load uses signed REST (higher weight) and falls back to the Worker /api/market/binance/signed/klines on CORS failure. Keys are never written to disk.
mock-walk
| Key | Default | Meaning |
|---|---|---|
seed | 0 | 0 = non-deterministic; non-zero = deterministic PRNG |
startPrice | 100 | Walk origin |
limit | 500 | Bar count |
csv-upload
- No schema fields. User must Upload a CSV (
time,open,high,low,close[,volume]) or JSON array first; otherwise throws a clear error.
Internals
| Path | Role |
|---|---|
src/sources/catalog.ts | Definitions + register/list/get + sourcePageLimit |
src/sources/upload-store.ts | In-memory last upload for csv-upload |
src/data/load-symbol.ts | One-shot Load pipeline |
src/data/data-source-manager.ts | Background backfill + validate + gaps |
src/data/bars-cache.ts | IDB OHLCV cache for manager |
src/data/bars-gaps.ts | Coverage / gap detection |
src/data/parse-bars.ts | CSV/JSON normalization |
Interval → venue codes
Helpers map AXIS intervals (1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M) to OKX bar, Bybit interval codes, Coinbase granularity seconds. Unmapped intervals fall back to daily-ish defaults — check venue docs if you add exotic TFs. Some venues omit a subset (MEXC has no 3m/2h/6h/8h/12h/3d; Kraken has no 3m/2h).
Dynamic registration
registerDynamicSource(plugin) // from catalog / loader
unregisterDynamicSource(id)
listDynamicSourceIds()
Loader path: kind === 'source' + fetchHistorical required.
Invariants & edge cases
- Time unit — always seconds unix (Binance ms ÷ 1000).
- Binance fallback — offline demos “work” but are not real prices; disable
fallbackfor strict desk research. - CORS — browser → public venue APIs must allow CORS; corporate proxies may require a Worker
/api/proxy(not shipped as a general proxy today — plan carefully). - Newest-first venues (OKX, Bybit, Coinbase) — catalog reverses/sorts ascending by
timefor the chart.
Worked example
// Minimal custom source (ES module for loader)
export default {
id: 'static-two',
name: 'Two Bars',
kind: 'source',
async fetchHistorical() {
return [
{ time: 1_700_000_000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 },
{ time: 1_700_000_060, open: 1.5, high: 2, low: 1, close: 1.2, volume: 12 },
];
},
};
Failure modes
| Error / symptom | Fix |
|---|---|
No uploaded file… | Use Upload before selecting csv-upload |
| Empty chart + Binance down | Expected synthetic walk if fallback on |
OKX code !== '0' | Symbol format / region block |
| CORS blocked | Proxy or different source |
See also
- Streams
- Contracts
- Plugin examples (CoinGecko)