← Back to Portfolio

Algorithmic Trading Research Platform

A Multi-Market Paper Trading System, In Production

A multi-market paper trading system I built and actively run: a BTC perpetual futures engine marked against live Delta Exchange data, and an options paper trading engine for NIFTY / SENSEX / FINNIFTY marked against live Groww prices — each with its own CLI, trade ledger, and VPS-deployed live poller. Backing both is a research lab where I develop and backtest regime classifiers and signal overlays across BTC, ETH, and PAXG before any logic reaches the paper engines. It has been running in production long enough to accumulate a real operational history — live incidents, root-caused and fixed, not just green tests. The repositories are private (they contain live strategy logic), so this page walks through the architecture and engineering history instead of linking out.

System Architecture

Delta Exchange APIlive BTC perp dataGroww APIlive NIFTY / SENSEX / FINNIFTYBTC Perp PaperTrading EngineOptions PaperTrading EngineTrade Ledger · CLI · Live Pollerdeployed on VPS via systemdsatellite SQLite stores — chain / price / regime data, split per service

25

merged PRs

130+

commits

560+

automated tests

3

live production incidents diagnosed & fixed

Sequence Diagrams

A few of the more interesting flows — how a trade actually moves through the system, and how two of the production incidents below unfolded in real time.

Live Trade Signal Flow

PollerMarket Data APIStrategy EngineTrade Ledger+ Notificationspoll latest price (every 5–15s)price tickevaluate(price)check entry / exit gatesrecord trade (open / close)acknotify (Telegram)

Incident: Root-Causing a Stalled WAL Checkpoint

Regime CaptureMain DB (WAL)On-Call (Me)open connection at startuppins WAL read snapshot for connection lifetimePRAGMA wal_checkpoint(PASSIVE)checkpointed frame count frozenEXPLAIN QUERY PLANTEMP B-TREE — 3.1M rows scannedadd composite index + fix connection lifecyclecheckpoint resumes advancing ✓

Incident: Lock Contention → Satellite DB Split

PollerShared DB(later: satellite)Chain Capturewrite price snapshot (every 15s)write option chain snapshot (priority)blocked — "database is locked"satellite DB split shipped (PR #10)write price snapshot → satellite DBwrite option chain snapshotsucceeds immediately ✓

A Few War Stories From the PR History

Traced a live lock-contention incident to a shared database file

A background writer sharing one SQLite file with the priority market-data path could stall it under load. Split the shared store into per-service satellite databases using SQLite's ATTACH + temp views, so every existing query kept working with zero SQL changes — then wrote a test that holds a satellite's write lock open indefinitely and asserts the main database still writes immediately.

Root-caused a stalled checkpoint during live market hours

The write-ahead log kept growing mid-session. The obvious suspect (a long-lived idle connection) was real but wasn't the cause — EXPLAIN QUERY PLAN revealed a single unindexed lookup materializing millions of rows into a temp B-tree on every poll tick, taking over a minute per call. One composite index fixed it, backed by a regression test asserting the query plan itself never regresses.

Rebuilt a backup pipeline that was quietly outgrowing itself

Once continuous options-chain capture went live, a full-copy-every-run backup ballooned the database from megabytes to gigabytes in under two weeks, duplicating nearly the whole file each time. Redesigned it into per-trading-day archives with retention-based pruning — and caught a near-OOM on the 2GB VPS along the way, where a single query was materializing an entire day's data twice in memory, fixed by streaming the export in batches.

Closed the gap between what's in git and what's actually running

After a code-only deploy silently reverted an uncommitted hot-fix, built a branch-based CI/CD protocol with path-filtered tests and manual, main-only deploys. Later caught the same class of bug one layer deeper: a scheduling change had merged and passed CI, but the deploy step only ever synced application code, never the service definitions that controlled when it actually ran — fixed by syncing and reloading those on every deploy too.

Treated every new signal as a hypothesis to falsify, not confirm

Every strategy candidate goes through multi-window backtesting — days through weeks — specifically to catch the overfitting trap where an idea looks great on the sample it was tuned against and falls apart outside it. Several promising ideas were swept, measured, and explicitly rejected in the PR history rather than shipped, with the negative result kept as documented research instead of discarded — the same discipline that governs the honest reporting of what didn't work, not just what did.

← Back to Portfolio