Streams live trades from Binance through an event-driven pipeline and renders a live candlestick dashboard in the browser, with full history kept in a time-series database.
Binance WS ──► ingestor ──► Redpanda ──► processor ──┬──► TimescaleDB (history)
(trades) (Python) (Kafka API) (aggregates) └──► Redis ──► FastAPI /ws ──► React dashboard
| Concern | Choice | Reasoning |
|---|---|---|
| Event backbone | Redpanda | Kafka-API compatible, single binary, no ZooKeeper. Same client code as Kafka, less to run locally. |
| Storage | TimescaleDB | Trades are time-series. Hypertables and time-bucketing fit better here than a document or search store. |
| Real-time fan-out | Redis pub/sub | Broadcasts candle updates from the processor to every connected WebSocket client, and caches the latest per-symbol state. |
| API / sockets | FastAPI | Async, typed, with WebSocket support built in. |
| Charts | lightweight-charts | TradingView's charting library, built for financial candlesticks. |
| Packaging | uv + pyproject.toml | Fast, reproducible installs; no requirements.txt. |
TimescaleDB is used here instead of Elasticsearch on purpose: OHLCV data is time-series, so a hypertable is a better fit than a search index.
- ingestor (
lm-ingestor) - connects to the Binance combined trade stream, normalizes each event, and publishes to Redpanda keyed by symbol (preserving per-symbol order). - processor (
lm-processor) - consumes trades, builds 1-minute OHLCV candles in memory, batch-writes raw trades to TimescaleDB (viaCOPY), upserts closed candles, and broadcasts live updates over Redis. - api (
lm-api) - FastAPI service exposing REST history/stats plus a/wsWebSocket that fans out live ticks and candle updates. - web - React + Vite dashboard with a live candlestick chart, stats, and a trade tape.
cp .env.example .env
docker compose up --buildThen open the dashboard at http://localhost:8080. API docs at http://localhost:8000/docs.
Run the infrastructure in Docker, the code on your machine:
# 1. Infra only
docker compose up -d redpanda timescaledb redis
# 2. Backend (three terminals, or use a process manager)
uv sync
uv run lm-ingestor
uv run lm-processor
uv run lm-api
# 3. Frontend
cd web
npm install
npm run dev # http://localhost:5173 (proxies /api and /ws to :8000)| Method | Path | Description |
|---|---|---|
| GET | /api/symbols |
Configured symbols |
| GET | /api/candles?symbol=btcusdt&limit=240 |
Historical 1m candles |
| GET | /api/trades?symbol=btcusdt&limit=50 |
Recent raw trades |
| GET | /api/stats |
Latest per-symbol snapshot (from Redis) |
| WS | /ws?symbol=btcusdt |
Live ticks + candle updates (omit symbol for all) |
uv run pytest # pure aggregation logic
uv run ruff check # lintAll settings are environment variables prefixed LM_ (see .env.example).
- TimescaleDB continuous aggregates for multi-interval candles (5m / 1h) for free.
- Compression + retention policies on the trades hypertable.
- Prometheus metrics + Grafana dashboard for pipeline throughput/lag.
- Kubernetes manifests / Helm chart.
MIT