crypto-trade-bot — Kraken quantitative trading platform
Self-hosted research, backtesting, paper-trading and (gated) execution platform for Kraken Spot.
Mode is offline by default. No live order can be sent unless a trade key is configured, preflight passes, the
feature flag is on and the owner activates live mode in the UI with a second confirmation (Phase 5, not shipped).
text
apps/api Python 3.12 · FastAPI · asyncpg · Redis · numpy/pandas/scipy/statsmodels (package `ktrade`)
apps/web Next.js · TypeScript · Tailwind v4 · TanStack Query · lightweight-charts
migrations plain SQL, applied by `ktrade migrate` (Timescale hypertables if the extension exists)
docs ARCHITECTURE · THREAT-MODEL · RUNBOOK · KRAKEN-API-NOTES · RESEARCH-REPORTS
deploy Prometheus / Grafana provisioningQuick start (local, Apple Silicon)
bash
cp .env.example .env # then set KTRADE_SECRET_KEY and KTRADE_OWNER_PASSWORD_HASH
docker compose up -d db redis # or use Homebrew postgresql@17 + redis
make setup # uv venv + pip install, pnpm install
make migrate && make backfill # schema + first OHLC pull (≤720 bars per pair/interval)
make worker & # pair discovery, OHLC accumulation, WebSocket v2 stream
make api & # http://127.0.0.1:8470/api/docs
make web # http://localhost:8471 (login with the owner password)
make test lint typecheckOwner password: cd apps/api && .venv/bin/ktrade set-owner-password prints a bcrypt hash → KTRADE_OWNER_PASSWORD_HASH.
What works today (Phase 1 + Phase 2)
- Kraken REST client with the documented signature (test vector in
tests/test_kraken_signing.py), monotonic nonce, tiered call counter, retries; WebSocket v2 client (ticker/book/trade/ohlc) with CRC32 book checksum verification and automatic resubscription on mismatch; reconnect with backoff; heartbeat watchdog. - Pair metadata discovery (ordermin/costmin/tick/lot decimals/status/leverage) — capabilities are read from the
exchange, never hard-coded.
XBT→BTCnaming normalised to WS v2 symbols. - Postgres schema: candles (open-time keyed,
closedflag), trades, latest ticker/book, 1-s microstructure samples, data gaps, backtest runs, hash-chained immutable audit log, risk state, paper ledger tables. - Event-driven backtester: decisions at bar close, execution at next open (+ optional latency), maker/taker fees, spread, slippage, square-root impact, participation-capped partial fills, lot rounding, exchange minimums, independent risk gateway on every order. Proven no-lookahead by tests.
- Strategy SDK + plugins: time-series momentum (vol-targeted), MA ensemble, z-score mean reversion with OU half-life + regime filter + cost-aware entries; benchmarks buy&hold / cash / simple momentum / equal-risk.
- Validation: holdout, anchored/rolling walk-forward with embargo, parameter sensitivity maps, block-bootstrap CIs, deflated Sharpe, stress scenarios (fees ×2, spread ×3, slippage, latency, liquidity collapse, outage gap), shuffled-trade Monte Carlo. Full provenance (commit, dataset hash, params, seed, window, costs).
- Web terminal: overview, market explorer (live candles/book/tape), strategy lab, backtest explorer + compare, risk center (limits, kill switch, what-if evaluator, audit), reports, settings (credential status, preflight).
- Observability: structured JSON logs with correlation ids, Prometheus metrics at
/api/metrics, health endpoint.
Known limitations (honest list)
- Kraken REST OHLC returns at most 720 bars per pair/interval; history accumulates from first deployment (1-min: 12 h, 1-h: 30 days, 1-d: ~2 years at first pull). Long backtests on fine intervals need a licensed external dataset (not included). Results on short windows are statistically weak — the UI says so.
- Phases 3–5 are not implemented: cointegration/Kalman, GARCH/HMM regimes, portfolio optimisation, market-making simulation, paper execution loop, live adapter. Pages exist as clearly-labelled placeholders.
- WS v2 allows one OHLC interval per symbol per connection → only 1-min bars are streamed; other intervals come from REST polling (≤ 60 s lag).
- Kraken has no Spot sandbox; the only dry-run is
AddOrder validate=true(used by preflight). - No shorting / margin: strategies are long-only spot.
- Timescale is optional; without the extension plain B-tree indexes are used (fine at this scale).
See docs/RUNBOOK.md for operations and docs/THREAT-MODEL.md for security assumptions.