A high-performance, low-latency crypto paper trading and backtesting platform built in C++ with kdb+/q
CryptoHedgeLab is engineered for quant developers and algorithmic traders who need deterministic, microsecond-level strategy execution with real-time hedging via futures and options. It ingests live market data from Binance, evaluates pre-compiled strategies, applies hedging logic, and stores every tick in kdb+/q for high-fidelity backtesting β all without a single line of interpreted code in the hot path.
- Project Philosophy
- Core Features
- System Architecture
- Tech Stack
- Project Structure
- Market Data Ingestion
- Strategy Engine
- Hedging Engine
- Paper Trading Engine
- Backtesting Engine
- Performance Metrics
- Latency Monitoring
- Data Storage β kdb+/q
- Getting Free Market Data
- Installation
- Configuration
- Running the Platform
- Performance Goals
- Roadmap
- Author
CryptoHedgeLab is built on one belief: if you can't measure it, you can't trust it.
Most retail and semi-professional trading platforms abstract away the details that matter most in high-frequency environments β memory allocation patterns, lock contention, tick-to-decision latency, and the true cost of hedging. This platform is designed to expose all of those details and give you full control over them.
| Principle | What It Means in Practice |
|---|---|
| β Pre-compiled strategy execution | Zero overhead strategy evaluation in the hot path |
| β Fully deterministic logic | Same inputs always produce the same outputs |
| β Microsecond latency tracking | Every pipeline stage is timestamped and measured |
| β Real hedging instruments | Futures and options hedging, not just PnL math |
| β Lock-free architecture | No mutex contention in the critical path |
| β Rigorous performance measurement | Sharpe, drawdown, PnL tracked across every backtest run |
- Connects directly to Binance WebSocket streams for Spot, Futures, and Options
- Processes trade events and full order book depth updates in real time
- Reconstructs an in-memory order book with full bid/ask ladder at every tick
- Zero-copy data flow through the pipeline wherever possible
- Lock-free single-producer/single-consumer queues between all pipeline stages
- Pre-allocated memory pools β zero heap allocation in the hot path
- Cache-line-aligned data structures to minimize false sharing
- Deterministic execution order with no GC pauses
- Strategies are authored via the UI and compiled down to native C++ logic
- No runtime parsing, no scripting overhead, no interpreter
- Supports price signals, order book imbalance, volume triggers, and EMA-based conditions
- Each strategy run is fully reproducible given the same tick data
- Primary hedging via futures: fast, liquid, low-latency delta neutralization
- Secondary hedging via options: tail-risk protection and volatility-aware overlays
- Configurable hedge ratios per strategy run
- Hedged vs. unhedged PnL comparison built into the backtester
- Full simulated matching engine with realistic order handling
- Supports market orders, limit orders, partial fills, and configurable slippage
- Runs on live Binance data with zero risk of real capital exposure
- Replay historical tick data directly from kdb+/q at configurable speed multipliers
- Deterministic execution ensures backtest = forward test (given same data)
- Outputs full performance report: PnL curve, Sharpe ratio, max drawdown, win rate
- Timestamps every stage of the pipeline: tick arrival β decision β order β fill
- Real-time latency dashboard in the frontend
- Historical latency percentile tracking (p50, p95, p99)
The platform is structured as a linear, staged pipeline. Each stage communicates with the next via lock-free queues, ensuring no blocking between data ingestion and order execution.
βββββββββββββββββββββββββββββββββββββββββββ
β Frontend (Strategy Builder + β
β Latency Dashboard + PnL UI) β
ββββββββββββββββββββββ¬βββββββββββββββββββββ
β
ββββββββββββΌβββββββββββ
β Strategy Compiler β
β (UI β C++ DSL) β
ββββββββββββ¬βββββββββββ
β
ββββββββββββΌβββββββββββ
β C++ Execution Core β
ββββββββββββ¬βββββββββββ
β
βββββββββββββββββΌββββββββββββββββ
β Binance WebSocket Feeds β
β (Spot + Futures + Options) β
βββββββββββββββββ¬ββββββββββββββββ
β
ββββββββββββΌβββββββββββ
β Order Book Recon β
β (in-memory ladder) β
ββββββββββββ¬βββββββββββ
β
ββββββββββββΌβββββββββββ
β Strategy Engine β
β (compiled C++ logic)β
ββββββββββββ¬βββββββββββ
β
ββββββββββββΌβββββββββββ
β Hedge Engine β
β (Futures + Options) β
ββββββββββββ¬βββββββββββ
β
ββββββββββββΌβββββββββββ
β Risk Controls β
ββββββββββββ¬βββββββββββ
β
ββββββββββββΌβββββββββββ
β Execution Engine β
ββββββββββββ¬βββββββββββ
β
βββββββββββββββββΌββββββββββββββββ
β Paper Trading / Exchange Sim β
βββββββββββββββββ¬ββββββββββββββββ
β
ββββββββββββΌβββββββββββ
β kdb+/q Storage β
ββββββββββββ¬βββββββββββ
β
ββββββββββββΌβββββββββββ
β Backtesting Engine β
β + Replay Engine β
βββββββββββββββββββββββ
| Layer | Technology | Why |
|---|---|---|
| Core Engine | C++ 17/20 | Deterministic, compiled, zero-overhead abstractions |
| Networking | Boost.Beast / uWebSockets | Async WebSocket handling with minimal latency |
| JSON Parsing | simdjson | SIMD-accelerated parsing, fastest available |
| Concurrency | Lock-free queues (SPSC) | No mutex contention in the hot path |
| Database | kdb+/q | Column-store built for time-series, industry standard in HFT |
| Frontend | React + React Flow | Interactive strategy builder and live dashboards |
| Build System | CMake | Cross-platform, fine-grained compilation control |
cryptohedgelab/
β
βββ core/
β βββ feed_handler/ # Binance WebSocket connection + stream parsing
β β βββ spot_feed.cpp
β β βββ futures_feed.cpp
β β βββ options_feed.cpp
β β
β βββ order_book/ # In-memory order book reconstruction
β β βββ book.hpp
β β βββ book.cpp
β β
β βββ strategy_engine/ # Compiled strategy execution
β β βββ strategy_base.hpp
β β βββ compiled/ # Generated C++ strategies live here
β β
β βββ hedge_engine/ # Futures and options hedging logic
β β βββ futures_hedge.cpp
β β βββ options_hedge.cpp
β β
β βββ risk_engine/ # Position limits, drawdown guards
β β βββ risk_controls.cpp
β β
β βββ execution_engine/ # Order routing to exchange simulator
β β βββ executor.cpp
β β
β βββ exchange_simulator/ # Paper trading matching engine
β βββ matcher.cpp
β βββ slippage_model.cpp
β
βββ kdb/
β βββ schema.q # Table definitions
β βββ ingestion.q # Real-time data write handlers
β βββ queries.q # Backtest queries and analytics
β
βββ frontend/
β βββ strategy_builder/ # Visual drag-and-drop strategy composer
β βββ latency_dashboard/ # Real-time latency chart by pipeline stage
β βββ pnl_dashboard/ # Live PnL curve, Sharpe, drawdown display
β βββ components/ # Shared UI components
β
βββ backtester/
β βββ replay_engine/ # Tick-level historical replay from kdb+
β
βββ config/
β βββ settings.json # Strategy params, hedge ratios, risk limits
β
βββ README.md
CryptoHedgeLab consumes multi-instrument WebSocket streams from Binance. All streams are public and require no API key for market data consumption.
| Stream | Fields |
|---|---|
btcusdt@trade |
price, quantity, timestamp, buyer/maker flag |
btcusdt@depth |
bid/ask price levels, quantities, update ID |
| Stream | Fields |
|---|---|
btcusdt@trade |
price, quantity, timestamp |
btcusdt@depth |
bid/ask ladder |
btcusdt@markPrice |
mark price, funding rate, next funding time |
Futures are the primary hedging instrument due to their liquidity, tight spreads, and low-latency execution characteristics.
| Field | Description |
|---|---|
| strike | Strike price of the option contract |
| expiry | Expiration date |
| option price | Current mid-market price |
| implied vol | Used for volatility-aware hedge sizing |
Options are used as a secondary, event-driven hedge for tail-risk scenarios where a large adverse move is detected.
Strategies are authored visually in the frontend Strategy Builder β a drag-and-drop node editor built with React Flow. The UI generates a DSL (domain-specific language) representation which is then compiled into native C++ before execution. There is no interpretation at runtime.
Supported signal types:
- Price relative to moving averages (EMA, SMA)
- Order book imbalance (bid size vs ask size ratio)
- Volume spike detection
- Spread thresholds
- Custom threshold conditions
UI Node Graph
β
DSL Representation (JSON)
β
Strategy Compiler (C++ codegen)
β
Compiled .so / static strategy object
β
Loaded into Strategy Engine at startup
When order book imbalance exceeds 0.6 and price is below the 10-period EMA, the strategy emits a buy signal. When imbalance drops below 0.4 and price is above the EMA, it emits a sell. Both conditions are evaluated in compiled native code with no runtime overhead.
Futures hedging is applied in real time as the strategy accumulates a spot position. When a long spot position is open and a hedge signal is active, the engine shorts an equivalent notional in perpetual futures scaled by the configured hedge ratio. Short spot positions are hedged with a long futures leg. The hedge ratio is configurable between 0.0 (no hedge) and 1.0 (full delta neutral).
Why futures first:
- Deep liquidity on Binance USDT-M perpetuals
- No expiry management (perpetual contracts)
- Funding rate tracked and factored into PnL
- Sub-millisecond order placement latency in simulation
Options are used when the risk engine detects a high-volatility environment or a large adverse position has formed. A protective put is purchased at a configurable OTM strike (e.g. 5% out of the money) with the nearest weekly expiry. Quantity is sized proportionally to the open spot position. Options premium paid is tracked separately in PnL attribution.
Hedge comparison in backtester:
Every backtest run outputs a side-by-side comparison:
| Metric | Unhedged | Futures Hedged | Options Hedged |
|---|---|---|---|
| Total PnL | β | β | β |
| Sharpe Ratio | β | β | β |
| Max Drawdown | β | β | β |
| Volatility | β | β | β |
(Values populated per backtest run β see Performance Metrics section)
The exchange simulator replicates the core matching logic of a real exchange without any network round-trips or real capital exposure.
| Order Type | Behavior |
|---|---|
| Market Order | Filled immediately at best available price |
| Limit Order | Queued and filled when price crosses the limit |
| Partial Fill | Large orders may fill across multiple price levels |
Slippage is modeled as a function of order size relative to available liquidity at each price level. Larger orders that consume multiple book levels incur proportionally higher slippage. The slippage factor is configurable in settings.json and can be calibrated against historical Binance order book data.
The backtester replays historical tick data stored in kdb+/q at configurable speed multipliers. Execution is fully deterministic β given the same data, the same strategy will always produce the same fills.
./replay_engine --symbol BTCUSDT --speed 10x --start 2024-01-01 --end 2024-03-31Each run produces:
- PnL curve β cumulative profit and loss over the backtest window, plotted tick-by-tick
- Sharpe ratio β annualized risk-adjusted return
- Maximum drawdown β largest peak-to-trough decline
- Win rate β percentage of trades that closed profitable
- Average trade duration β time in position per trade
- Hedge effectiveness β how much the hedge reduced realized drawdown vs unhedged
All results are written back to kdb+/q and visualized in the frontend PnL dashboard.
Performance metrics are computed automatically at the end of every backtest run and tracked in real time during paper trading sessions.
- Cumulative PnL curve tracked at tick resolution, stored in kdb+ and visualized in the frontend
- Entry and exit points overlaid on the price series
- PnL reported before and after hedge costs (funding rates, options premium) for full attribution
- Hedged vs unhedged equity curves displayed side by side
- Annualized Sharpe ratio computed separately for hedged and unhedged runs
- Annualized on a 365-day basis since crypto markets trade continuously
- A Sharpe above 1.5 is the minimum threshold for a strategy to be considered viable
- Maximum drawdown tracked over the full backtest window, reported in both percentage and absolute USDT
- Drawdown guard in the risk engine halts paper trading if the live drawdown breaches a configurable limit (default: 5%)
- Calmar ratio (annualized return divided by max drawdown) reported alongside Sharpe
- Win rate β percentage of trades that closed in profit
- Profit factor β ratio of gross profit to gross loss
- Average win vs average loss β risk-reward per trade
- Total trade count and average hold time per position
- Turnover β total volume traded relative to starting capital
- Futures funding costs broken out separately from trading PnL
- Options premium spent on protective puts tracked per backtest run
- Net PnL reported after all costs, so strategy viability is never overstated
Every stage of the pipeline is instrumented with high-resolution timestamps. The frontend latency dashboard displays live readings and historical percentile distributions.
| Stage | Description |
|---|---|
| Tick Received | Timestamp when WebSocket message arrives at feed handler |
| Book Updated | Time to reconstruct order book after depth event |
| Strategy Decision | Time to evaluate strategy logic and emit signal |
| Order Sent | Time to pass order to exchange simulator |
| Fill Confirmed | Time to receive fill acknowledgement |
Tick β Book Update : 1.2 Β΅s
Book β Strategy Decision: 3.1 Β΅s
Decision β Order Sent : 4.8 Β΅s
Order β Fill : 2.5 Β΅s
ββββββββββββββββββββββββββββββββββ
End-to-End : 11.6 Β΅s
| Stage | p50 | p95 | p99 |
|---|---|---|---|
| Tick β Decision | 3.1 Β΅s | 5.4 Β΅s | 9.2 Β΅s |
| Decision β Fill | 7.1 Β΅s | 11.3 Β΅s | 18.6 Β΅s |
| End-to-End | 11.6 Β΅s | 19.4 Β΅s | 28.1 Β΅s |
All market data, fills, positions, and latency measurements are persisted to kdb+/q, a columnar time-series database purpose-built for high-frequency financial data.
Not everything coming off the wire needs to be persisted. Storage is kept lean and purposeful:
- β Trades (tick data, short-term only) β every individual trade event from Binance, kept for a rolling window to feed the backtester and signal computation. Older data is expired or archived to keep query performance tight.
- β Best bid/ask (not full depth) β only the top-of-book is stored, not the full 20-level ladder. Full depth is maintained in memory for live strategy evaluation but writing every depth update to disk is unnecessary and expensive at tick frequency.
- β Executed fills β every simulated order fill with side, price, quantity, and slippage, forming the authoritative trade log.
- β Positions β periodic snapshots of spot, futures, and options positions for risk monitoring and replay.
- β PnL snapshots β cumulative realized and unrealized PnL, both hedged and unhedged, at regular intervals for the equity curve.
- β Latency measurements β tick-to-decision and decision-to-fill timings for every event, used to build percentile distributions in the dashboard.
- β Futures mark price + funding rate β needed for accurate PnL attribution on futures hedge legs.
- β Options fills β strike, expiry, premium paid, and position size when a protective put is exercised.
- β Full order book depth history β not stored. Too voluminous, and the in-memory book is sufficient for live use. Historical depth replay can be sourced externally if needed.
- β Raw WebSocket frames β not stored. Parsed and forwarded only.
trade:([]
time: `timestamp$();
sym: `symbol$();
price: `float$();
size: `int$()
)futures:([]
time: `timestamp$();
sym: `symbol$();
price: `float$();
size: `int$();
markPrice: `float$();
fundingRate: `float$()
)options:([]
time: `timestamp$();
sym: `symbol$();
strike: `float$();
expiry: `date$();
price: `float$();
iv: `float$()
)book:([]
time: `timestamp$();
sym: `symbol$();
bid: `float$();
ask: `float$();
bidSize: `int$();
askSize: `int$()
)fills:([]
time: `timestamp$();
sym: `symbol$();
side: `symbol$();
price: `float$();
qty: `int$();
slippage: `float$()
)positions:([]
time: `timestamp$();
sym: `symbol$();
spot: `float$();
futures: `float$();
options: `float$()
)pnl:([]
time: `timestamp$();
sym: `symbol$();
realizedPnl: `float$();
unrealizedPnl: `float$();
hedgedPnl: `float$();
unhedgedPnl: `float$();
drawdown: `float$()
)latency:([]
time: `timestamp$();
tickToDecision: `long$();
decisionToFill: `long$();
endToEnd: `long$()
)CryptoHedgeLab is designed to run entirely on free, publicly available Binance data.
| Data | Source | Notes |
|---|---|---|
| Spot trades + order book | Binance WebSocket | Public stream, no auth needed |
| Futures trades + order book | Binance Futures WebSocket | Includes mark price + funding rate |
| Options quotes | Binance Options WebSocket | Available on USDT-settled options |
Visit data.binance.vision for bulk historical downloads:
| Data | Availability | Notes |
|---|---|---|
| Spot trade ticks | β Full history | Daily/monthly CSVs per symbol |
| Futures trade ticks | β Full history | Same format as spot |
| Klines (OHLCV) | β Full history | 1s to 1M intervals |
| Order book snapshots | Snapshots, not full depth stream history | |
| Options history | Sparse data, especially pre-2023 |
Full order book replay (every depth update tick) is the hardest data to get for free. The Binance data portal provides periodic snapshots, not a continuous stream of depth events. For production-grade order book backtesting, consider:
- Tardis.dev β normalized full depth data, ~$20β50 for targeted datasets
- Building your own recorder β run the feed handler in record mode to accumulate your own tick database in kdb+
For most strategy research purposes, trade-tick level data from the Binance data portal is sufficient to get meaningful backtest results.
- C++17/20 compatible compiler (GCC 11+ or Clang 14+)
- CMake 3.20+
- Boost 1.80+ (Beast, Asio)
- kdb+/q installed (free 32-bit version available from kx.com)
- Node.js 18+ and npm (for frontend)
# Start kdb+ on port 5000 and load the schema
q kdb/schema.q -p 5000All runtime parameters are set in config/settings.json:
{
"feed": {
"symbol": "BTCUSDT",
"streams": ["spot", "futures", "options"],
"orderbook_depth": 20
},
"strategy": {
"name": "imbalance_ema_v1",
"ema_period": 10,
"imbalance_threshold": 0.6
},
"hedge": {
"mode": "futures",
"ratio": 0.8,
"options_otm_factor": 0.95,
"tail_risk_threshold": 0.05
},
"risk": {
"max_position_usdt": 10000,
"max_drawdown_pct": 5.0,
"halt_on_drawdown": true
},
"paper_trading": {
"initial_capital_usdt": 100000,
"slippage_factor": 0.0002
},
"kdb": {
"host": "localhost",
"port": 5000
}
}# Start the execution engine with live Binance data
./build/cryptohedgelab --config config/settings.json --mode paper# Replay historical tick data from kdb+ at 10x speed
./build/replay_engine \
--symbol BTCUSDT \
--start 2024-01-01 \
--end 2024-03-31 \
--speed 10x \
--hedge futurescd frontend
npm run dev
# Open http://localhost:3000The dashboard provides:
- Strategy Builder β visual node editor to compose and compile strategies
- Latency Dashboard β real-time pipeline latency by stage, with p50/p95/p99 percentiles
- PnL Dashboard β live cumulative PnL curve, Sharpe, max drawdown counter
- Backtest Viewer β replay results with hedged vs unhedged comparison
| Metric | Target | Notes |
|---|---|---|
| Tick Processing | < 5 Β΅s | Feed handler to order book update |
| Strategy Execution | < 2 Β΅s | Signal evaluation only |
| End-to-End Latency | < 20 Β΅s | Tick arrival to fill confirmation |
| Backtest Throughput | > 1M ticks/sec | kdb+ replay speed |
| Sharpe Threshold | > 1.5 | Minimum acceptable for strategy viability |
| Max Drawdown Limit | < 5% | Enforced by risk engine in paper trading |
- Multi-symbol strategy support (portfolio-level hedging)
- Options Greeks computation (delta, gamma, vega) for smarter hedge sizing
- Transaction cost model calibrated against real Binance fee tiers
- Walk-forward optimization in the backtester
- Cross-exchange feed ingestion (OKX, Bybit)
- REST API for external strategy submission
- Persistent latency anomaly alerting
Isha Patro Software Engineer | Quant Developer
Built with a focus on HFT-style system design β where performance, correctness, and timing are not optional.
CryptoHedgeLab is a paper trading and research platform. It does not place real orders or manage real capital.