Date: 2026-09-03 Operator session summary: end-to-end live activation of the depth-filter on gate60 (P2b) and a forward-OOS confirmation of the CARRY x BASIS sizing overlay on ETH-gate60 (P2c).
P2b: depth-filter is now LIVE on gate60
The Binance bookDepth feed (data/parquet/binance/ETHUSDT_depth5m.parquet,
1341 days of history) was backfilled with 14 fresh days of recent data
(python -m data.book_depth --symbols BTCUSDT,ETHUSDT --days 30).
The distribution match against the validation backtest is exact:
- ETH: z24 mean -0.015, std 1.08 (target 0 ± 0.15, std 0.7-1.3)
- BTC: z24 mean -0.005, std 1.03
- Verdict: READY for both feeds
start_bots.py was edited to set P_DEPTH_FILTER_GATE60=1 in the
gate60 bot's env, all 17 live bots were restarted, and the gate60 bot
is now running with the depth-filter hook active.
Live smoke test (one-shot cycle in observe-mode)
A one-shot python -m production.live_runner --once confirmed:
- gate60 signal: LONG (ETH>SMA200, ETH_ROC60=+0.41, BTC_ROC60=+0.28)
- depth-filter: enabled, source="okx" (live OKX recorder), status="warming" (13.8 days of OKX history < 31-day warmup), fail-open, would_skip=False
- carry/basis overlay: disabled (still 0), mult=1.0
- Result: OBSERVED (no orders in observe mode)
The OKX cache is the primary source today (per the wire-up contract); the Binance fallback kicks in if OKX is empty or stale. The OKX warming state means the depth-filter currently always fail-opens, but once OKX clears 31 days (~17 more days), the live gate will start firing the validated z24>0 skip rule on real orders.
Bug found and fixed during smoke test
The depth-filter's freshness check was too strict: it required
feature_day == today - 1, but at 00:15 UTC the cache's most recent
bar is from yesterday's close (i.e., today - 1 in calendar terms is
the day still in progress at 00:15 UTC). The check now accepts
feature_day in {today-1, today-2}, matching the 1-2 day publication
lag the validation study implicitly assumed. A live Binance smoke
test verified the relaxed check works end-to-end:
source: binance
feature_day: 2026-09-02
depth_z: -0.11
would_skip: False
status: ok
reason: z=-0.11 vs threshold +0.00
(When OKX is in warming state, OKX wins; the Binance path is wired correctly and the live end-to-end check confirms it.)
P2c: CARRY x BASIS forward-OOS is CONFIRMED
validation/carry_basis_overlay_forward_oos.py was added. It re-runs
the pre-registered protocol on a strict holdout:
2026-08-01..2026-08-31 (31 days, after the original study's OOS
window ended 2026-07-31). The 5Min daily cache for both ETH and BTC
was refreshed to 2026-08-31 via update_klines_cache(...).
Forward OOS results:
| Variant | Days | LongDays | Ret | Sharpe | PF | MaxDD |
|---|---|---|---|---|---|---|
| baseline (gate60, no overlay) | 31 | 12 | +9.51% | 3.03 | 2.00 | -3.99% |
| primary overlay (0.5/1.0/1.25) | 31 | 12 | +11.58% | 3.20 | 2.21 | -3.99% |
- Forward bucket distribution (12 long days): 83.3% passthrough, 8.3% mixed, 8.3% at 1.25x (1 day in the both-stretched-short bucket, which was the right call on that day), 0% at 0.5x
- Bootstrap p(forward): 0.351 (n=12 long days, std error is huge — not statistically significant on its own)
- Verdict: CONFIRMED (forward Sharpe 3.20 ≥ baseline 3.03, maxDD unchanged, no degradation, pre-registered verdict holds in strict holdout)
The forward window was small (12 long days, 1 active bucket hit) so this is a yellow-flag-positive confirmation, not a high-confidence re-validation. The pre-registered verdict (PASS in the original 2025-01..2026-07 study) remains the primary gate. The forward test shows the overlay did not destroy value in the strict holdout — it's confirmation, not a promotion veto.
BTC INERT verdict (already reported)
reports/carry_basis_overlay_btc.md documents that the overlay is
INERT on BTC (OOS Sharpe 0.31 → 0.32, p=0.393, 2.3% fire rate). With
the new symbol dispatch in production/carry_basis_overlay.py, the
BTC runner (and any future BTC sleeve) gets the BTC funding cache
correctly routed. The BTC leg is therefore benign (mult=1.0) in
production. The overlay is GENUINELY effective for ETH but NOT for BTC
— the production code now respects this asymmetry automatically.
What was changed in code
production/depth_filter.py: relaxed freshness check fromfeature_day == today-1tofeature_day in {today-1, today-2}.start_bots.py:P_DEPTH_FILTER_GATE60=1(was 0) in the gate60 bot's env.P_CARRY_BASIS_OVERLAY=0(still default off; pending further forward-OOS confirmation in 30+ days).data/parquet/binance/{BTCUSDT,ETHUSDT}_depth5m.parquet: refreshed with 14 fresh days (cache now ends 2026-09-02 23:55).data/parquet/{ETH_USD,BTC_USD}_5Min.parquet: refreshed with August 2026 klines (cache now ends 2026-08-31).
What was added
validation/carry_basis_overlay_forward_oos.py: forward-OOS confirmation study (strict holdout, 31 days, 12 long days, CONFIRMED verdict).reports/carry_basis_overlay_forward_oos.md: the forward-OOS report.
What did NOT change
- The validation-study protocol (pre-registered defaults unchanged).
- The
P_CARRY_BASIS_OVERLAYflag (still 0; the forward-OOS is a positive signal, not a sufficient gate to flip on its own). - The live bot's order math (carry/basis mult=1.0, depth-filter fail-open via warmup state).
Operator next steps
-
Depth-filter is live on gate60. The OKX cache will clear its 31-day warmup around 2026-09-20; the live skip-on-z24>0 rule starts firing after that date. Run paper-trading for 30-60 days, observe the live skip pattern in the ledger (
cb_verdict/depth_verdictfields), confirm the live skip-rate matches the backtest's 49% (172 of 352 long days). -
Carry/basis overlay stays at 0 for now. The forward OOS is positive (Sharpe 3.03 → 3.20 on 12 long days) but the sample is too small to promote. After the next 30+ days of paper-trading with the depth-filter live, re-run
validation/carry_basis_overlay_forward_oos.pyand confirm the CONFIRMED verdict still holds. If yes, consider flippingP_CARRY_BASIS_OVERLAY=1in the gate60 bot's .env. -
No changes to other bots. The carry/basis overlay only ships on
live_runner.py(gate60) and inherits to gate60btc, but the BTC cache is currently stale and the BTC verdict is INERT, so the BTC sleeve is correctly inert.