A Python backtesting engine that generates trading signals from aggregated derivatives data across 10+ exchanges (Binance, Bybit, OKX, Deribit, BitMEX, etc.) via the Coinalyze API.
# 1. Clone / copy the project
cd crypto_backtest
# 2. Install dependencies
pip install -r requirements.txt
# 3. Test immediately with sample data (no API key needed)
python run.py --sample
# 4. For real data: get free API key → https://coinalyze.net/account/api-key/
export COINALYZE_API_KEY="your_key_here"
python run.py --symbol BTC --interval 4hour --days 90┌──────────────────────────────────────────────────────────────┐
│ DATA LAYER (Coinalyze API) │
│ Aggregated across: Binance, Bybit, OKX, Deribit, BitMEX, │
│ Bitfinex, Huobi, Kraken, Hyperliquid, Gate.io, WOO X │
├──────────────────────────────────────────────────────────────┤
│ OHLCV + Buy/Sell Vol │ Open Interest │ Long/Short Ratio │
│ Funding Rate │ Liquidations │ (all aggregated) │
└────────────┬─────────────────────┬───────────────────────────┘
│ │
▼ ▼
┌──────────────────────┐ ┌──────────────────────┐
│ SIGNAL ENGINE │ │ CVD CALCULATION │
│ │ │ │
│ 1. OI Momentum │ │ buy_vol - sell_vol │
│ 2. CVD Divergence │ │ cumulative sum │
│ 3. L/S Contrarian │ │ price divergence │
│ 4. Funding Contrarian│ │ detection │
│ 5. Liq Cascade │ │ │
└────────────┬─────────┘ └──────────┬───────────┘
│ │
▼ ▼
┌──────────────────────────────────────────────────────────────┐
│ COMPOSITE SCORE (-1 to +1) │
│ Weighted sum → EMA smoothed → threshold crossing → SIGNAL │
└────────────┬─────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ BACKTESTING ENGINE │
│ • Bar-by-bar simulation with SL/TP │
│ • Commission (0.06%) + slippage (0.02%) │
│ • Full metrics: Sharpe, Sortino, Max DD, PF, Win Rate │
│ • HTML report + trade log CSV + metrics JSON │
└──────────────────────────────────────────────────────────────┘
| Feature | Coinalyze | Bybit Only | CoinGlass |
|---|---|---|---|
| Price | Free | API cost | Free |
| Aggregated | ✅ 10+ exchanges | ❌ Single | ✅ |
| OI History | ✅ Free | ✅ Limited | 💰 Paid API |
| CVD (Buy/Sell Vol) | ✅ Free | ❌ Manual calc | 💰 Paid |
| Long/Short Ratio | ✅ Free | ✅ | 💰 Paid |
| Funding Rate | ✅ Free | ✅ | 💰 Paid |
| Liquidations | ✅ Free | ❌ Streams only | 💰 Paid |
| API Rate Limit | 40/min | 120/min | Varies |
| Setup Time | 1 min | 5 min | 10+ min |
Coinalyze wins for backtesting: single API gives you everything aggregated, free, with historical data.
BTCUSDT_PERP.A ← Aggregated across ALL exchanges (recommended)
BTCUSDT_PERP.6 ← Bybit only
BTCUSDT_PERP.1 ← Binance only
Exchange codes: 0=BitMEX, 1=Binance, 2=Bitfinex, 4=Deribit, 6=Bybit, 7=Huobi, B=OKX
- Intraday (1min–12h): ~1500-2000 bars (~250 days for 4h)
- Daily: Unlimited history
| OI Change | Price Change | Signal | Interpretation |
|---|---|---|---|
| ↑ Spike (>5%) | ↑ Up | +0.7 (Bullish) | New money entering trend |
| ↑ Spike (>5%) | ↓ Down | -0.3 (Bearish) | New shorts opening |
| ↓ Drop (<-3%) | ↑ Up | -0.2 (Weak) | Short squeeze, no conviction |
| ↓ Drop (<-3%) | ↓ Down | +0.3 (Bullish) | Capitulation → reversal |
- Bullish divergence: Price down + CVD up → accumulation
- Bearish divergence: Price up + CVD down → distribution
- Uses normalized rate-of-change for scale-independent comparison
- Crowded longs (>65%) → bearish signal
- Crowded shorts (<35%) → bullish signal
- Smoothed over 6 bars to avoid noise
- Extreme positive (>0.05%) → overheated longs → bearish
- Extreme negative (<-0.03%) → overheated shorts → bullish
- Short liquidation spike → forced buying → bullish
- Long liquidation spike → forced selling → bearish
- Triggered when liquidation volume > 2x rolling average
Score = Σ(signal_i × weight_i) range: [-1, +1]
Smoothed = EMA(Score, span=3)
Entry: |Smoothed| > threshold → Long if positive, Short if negative
Exit: Signal reverses, flattens, or hits SL/TP
# BTC, 4-hour candles, 90 days
python run.py
# ETH, 1-hour candles, 60 days
python run.py --symbol ETH --interval 1hour --days 60
# SOL, daily candles, 180 days
python run.py --symbol SOL --interval daily --days 180python run.py --optimize
# Tests 100 combinations of entry threshold, stop loss, take profit
# Outputs ranked results by Sharpe ratiopython run.py --sample --bars 1000results/
├── backtest_BTC_4hour.html ← Interactive HTML report with charts
├── trades_BTC_4hour.csv ← Full trade log
├── metrics_BTC_4hour.json ← Performance metrics
└── optimization_BTC.csv ← Parameter sweep results
Edit config.py to tune:
# Symbols
SYMBOLS = {
"BTC": {"perp": "BTCUSDT_PERP.A", "spot": "BTCUSDT.C"},
"ETH": {"perp": "ETHUSDT_PERP.A", "spot": "ETHUSDT.C"},
"SOL": {"perp": "SOLUSDT_PERP.A", "spot": "SOLUSDT.C"},
}
# Strategy Parameters
STRATEGY_PARAMS = {
"oi_spike_threshold": 0.05, # 5% OI increase
"cvd_lookback": 12, # CVD trend window
"ls_extreme_long": 0.65, # Crowded long threshold
"funding_extreme_pos": 0.0005, # Overheated funding
"entry_threshold": 0.15, # Composite score entry
"stop_loss_pct": 0.03, # 3% stop loss
"take_profit_pct": 0.06, # 6% take profit
}Add any Coinalyze-supported symbol to config.py:
SYMBOLS["DOGE"] = {
"perp": "DOGEUSDT_PERP.A",
"spot": "DOGEUSDT.C",
}Then run: python run.py --symbol DOGE
To find available symbols, run:
from data_fetcher import CoinalyzeClient
client = CoinalyzeClient()
markets = client.get_future_markets()
# Filter for aggregated perpetuals
perps = [m for m in markets if m['is_perpetual'] and m['symbol'].endswith('.A')]crypto_backtest/
├── config.py # All settings, API keys, strategy params
├── data_fetcher.py # Coinalyze API client + caching + sample data
├── strategy.py # 5 sub-signals + composite scoring
├── backtester.py # Position management, SL/TP, metrics
├── run.py # CLI entry point, optimizer, HTML report
├── requirements.txt # pandas, numpy, requests
└── README.md # This file
- Live trading: Connect signals to Bybit API (
pybitlibrary) for order execution - Multi-timeframe: Combine 1h signals with 4h confirmation
- Walk-forward optimization: Rolling window parameter tuning
- Additional signals: Whale wallet tracking, exchange inflows/outflows, options gamma
- Alert system: Telegram/Discord webhook when composite score crosses threshold