eval repo README with validation results
Browse files
README.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
tags: [ml-intern, crypto, finance, backtesting, evaluation]
|
| 3 |
+
---
|
| 4 |
+
|
| 5 |
+
# crypto-quant-eval
|
| 6 |
+
|
| 7 |
+
[](https://hf.co/chat?mode=ml-intern)
|
| 8 |
+
|
| 9 |
+
Institutional-grade evaluation harness for crypto quant trading strategies.
|
| 10 |
+
The companion dataset lives at [Avi-L/crypto-quant-eval-data](https://huggingface.co/datasets/Avi-L/crypto-quant-eval-data).
|
| 11 |
+
|
| 12 |
+
## What this eval measures
|
| 13 |
+
|
| 14 |
+
A strategy "passes" only if it survives all of:
|
| 15 |
+
|
| 16 |
+
| Check | Where | Rule |
|
| 17 |
+
|---|---|---|
|
| 18 |
+
| No lookahead (purge + embargo) | `crypto_eval/cv.py` | label window `[t, t+h]` must never overlap a test block; embargo >= horizon (8h = one funding interval) enforced |
|
| 19 |
+
| Leakage audit | `crypto_eval/cv.py` | independent per-segment audit of every CPCV fold; run fails loudly on violation |
|
| 20 |
+
| Fee-aware PnL | `crypto_eval/costs.py` | 5 bps taker / 2 bps maker (Binance VIP0), funding accrued at 8h ticks |
|
| 21 |
+
| Slippage | `crypto_eval/costs.py` | square-root impact `k*sqrt(notional/ADV)`, 2 bps floor |
|
| 22 |
+
| Deflated Sharpe (DSR) | `crypto_eval/stats.py` | accept only if DSR > 0.95 |
|
| 23 |
+
| Probability of Backtest Overfitting (PBO) | `crypto_eval/stats.py` | accept only if PBO <= 0.5 |
|
| 24 |
+
| Min Track Record Length | `crypto_eval/stats.py` | how long the track record must be before SR is significant |
|
| 25 |
+
|
| 26 |
+
Splitting uses CPCV (N=6 blocks, K=2 held out → 15 combinations) via
|
| 27 |
+
[`purgedcv`](https://pypi.org/project/purgedcv/) 0.1.11, following
|
| 28 |
+
López de Prado, *Advances in Financial Machine Learning* (Wiley 2018),
|
| 29 |
+
ch. 7 (purged K-fold + embargo) and ch. 11–12 (DSR, PBO, MinBTL).
|
| 30 |
+
|
| 31 |
+
## Quickstart
|
| 32 |
+
|
| 33 |
+
```bash
|
| 34 |
+
pip install -r requirements.txt
|
| 35 |
+
python run_eval.py --data /path/to/curated --symbol BTCUSDT --freq 1h \
|
| 36 |
+
--strategy funding_carry
|
| 37 |
+
```
|
| 38 |
+
|
| 39 |
+
`--data` is a directory containing the dataset repo's parquet files
|
| 40 |
+
(`bars_BTCUSDT_1h.parquet`, `funding_BTCUSDT.parquet`, `manifest.json`).
|
| 41 |
+
Strategies are functions `(bars, funding) -> positions`; add yours to
|
| 42 |
+
`crypto_eval/strategies.py`. Decision-time discipline is enforced
|
| 43 |
+
structurally: a bar starting at `t` closes at `t+freq`, so signals use
|
| 44 |
+
`shift_bars` (last closed bar at `t-1`); the engine and audit catch peeking.
|
| 45 |
+
|
| 46 |
+
## Validation results (2026-10-23)
|
| 47 |
+
|
| 48 |
+
Run on real curated data: BTCUSDT 1h, 59,654 bars (2020-01 → 2026-10),
|
| 49 |
+
5,295 funding ticks, $1M initial capital, CPCV N=6/K=2, horizon=embargo=8h.
|
| 50 |
+
Full JSON in `results/`.
|
| 51 |
+
|
| 52 |
+
| Strategy | Net PnL | Fees | Slippage | Funding | Mean SR (ann.) | PBO | DSR/PSR mean | Verdict |
|
| 53 |
+
|---|---|---|---|---|---|---|---|---|
|
| 54 |
+
| `funding_carry` | **-$69,773** | $2,856 | $95,031 | +$5,940 | -0.93 | 0.214 | 0.141 | **REJECT** |
|
| 55 |
+
| `ma_crossover` | **-$1,522,405** | $29,208 | $1,508,181 | -$3,469 | -4.95 | 0.014 | 0.000 | **REJECT** |
|
| 56 |
+
|
| 57 |
+
Both demo strategies are deliberately naive, and the harness correctly
|
| 58 |
+
rejects them: the carry trade's funding income (+$5.9k) is swamped by
|
| 59 |
+
slippage ($95k), and the MA crossover's $1.5M of turnover cost destroys
|
| 60 |
+
the strategy outright. A gross-return backtest would have flattered both.
|
| 61 |
+
|
| 62 |
+
Note on the DSR column: per-combination values are PSR (n_trials=1 within
|
| 63 |
+
a combination); DSR applies when multiple strategy configurations are
|
| 64 |
+
compared — `eval_trial_set` computes it with the across-trial SR variance.
|
| 65 |
+
|
| 66 |
+
## Validation performed
|
| 67 |
+
|
| 68 |
+
- Synthetic-data smoke: 20k GBM bars, both strategies, numeric DSR/PBO (`synth_gen.py`)
|
| 69 |
+
- Leakage test: `--embargo 0` with horizon 8 raises `ValueError` (guard in `make_cpcv`)
|
| 70 |
+
- Sanity: zero-position strategy produces exactly 0.0 net PnL; any turnover produces strictly positive fees + slippage
|
| 71 |
+
- No-lookahead audit passes on all 15 CPCV combinations, both real and synthetic data
|
| 72 |
+
|
| 73 |
+
## Known gaps
|
| 74 |
+
|
| 75 |
+
- ETH enters via funding only; ETH spot 1m (HaianCao/Binance-Public-OHLCV,
|
| 76 |
+
34.6 GB) was not ingested
|
| 77 |
+
- On-chain metrics are daily (coinmetrics-community), no usable HF on-chain repo exists
|
| 78 |
+
- PBO uses n_splits=8 (70 combos) rather than 16 (12,870) — the latter is
|
| 79 |
+
prohibitively slow on CPU with purge/embargo enabled
|
| 80 |
+
- Cross-venue funding divergence ([Chainticks/funding-divergence](https://huggingface.co/datasets/Chainticks/funding-divergence)) is verified
|
| 81 |
+
as a source but not yet wired into the harness
|
| 82 |
+
|
| 83 |
+
## References
|
| 84 |
+
|
| 85 |
+
- López de Prado, *Advances in Financial Machine Learning*, Wiley 2018 (ch. 7, 11, 12)
|
| 86 |
+
- [`purgedcv`](https://pypi.org/project/purgedcv/) — MIT-licensed implementation of the splitting and statistics used here
|