research(blind): 52 agenti ciechi su curve anonime BTC/ETH — orchestratore valuta PnL/maxDD, niente di nuovo regge
Flotta di 52 subagenti "esperti di segnali" su storico BTC/ETH ANONIMIZZATO (Series A/B rebased a 100, calendario sintetico, split 70/30) — non sanno cosa siano. Ognuno scrive un signal(df)->position causale (script o ML), tunato solo sul train. Orchestratore valuta su PnL e maxDD nel test held-out. Harness cieco leak-free (riusabile): - make_blind.py: export anonimo + overlay; blindlib.py: evaluator con shift della posizione + GUARDIA DI CAUSALITA' online (squalifica ogni look-ahead, ML incluso); blind_eval.py CLI; score_all.py giudice OOS; verify_top.py (corr-al-trend, fee-stress, jackknife). - 52/52 passano la guardia (zero leak su tutta la flotta). Esito OOS (benchmark buy&hold: -7% PnL, 68% DD): - top = macd (+21%, DD 11%, Sh 0.84), accel, vol_of_vol, regime_switch, rf, obv — tutti trend/vol-regime. Sharpe OOS ~0.84 decade dal train ~1.4. Mean-rev e ML in fondo. - 3 scettici indipendenti: REFUTED. regime-luck (top-5 bar = 67-102% del PnL); trend-redundancy (HAC alpha t=+0.9..+1.5, nessuno >1.96 — TSMOM travestito); overfit (accel/vov knife-edge). Verdetto: ri-conferma CIECA e indipendente del soffitto direzionale ~1.3. macd = classe-TP01, forward-monitor non deploy. Diario 2026-06-21-blind-signal-fleet.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
"""Agent 01 — Dual EMA crossover (family=trend, slug=ema_cross).
|
||||
|
||||
The angle: long/short on the sign of (fast EMA - slow EMA). The two spans are the
|
||||
core tuned knobs. One refinement that survived a plateau check on split='train':
|
||||
the two anonymized curves are strongly up-trending, so a SYMMETRIC short is pure
|
||||
drag (it shorts the dips of a bull market). We keep the long/short crossover but
|
||||
size the SHORT side down by `SHORT_W` — still a genuine long/short EMA cross, just
|
||||
risk-asymmetric. Direction is then vol-targeted (causal trailing window) so the two
|
||||
curves are sized comparably and the drawdown stays bounded.
|
||||
|
||||
Tuning (train only): a broad plateau f in [18..30], s in [40..50], SHORT_W in
|
||||
[0.1..0.3] all give sharpe_min ~1.3 / DD ~0.23. f=25, s=40, SHORT_W=0.25 sits in
|
||||
the plateau interior (not on a grid edge) -> robust, not a lucky cell.
|
||||
|
||||
CAUSAL: ema(c, span) is an online recursion (value at i uses rows 0..i only);
|
||||
vol_target uses a trailing vol window. No look-ahead, no centered windows, no
|
||||
global fit. Verified by causality_ok (max_diff 0.0).
|
||||
"""
|
||||
import numpy as np
|
||||
import blindlib as bl
|
||||
|
||||
# --- tuned ONLY on split='train' (plateau interior) ---
|
||||
FAST_SPAN = 25
|
||||
SLOW_SPAN = 40
|
||||
SHORT_W = 0.25 # short side sized down (asymmetric L/S); 0 -> long-flat
|
||||
TARGET_VOL = 0.20
|
||||
VOL_WIN = 30
|
||||
LEV_CAP = 1.0
|
||||
|
||||
|
||||
def signal(df):
|
||||
c = df["close"].values.astype(float)
|
||||
fast = bl.ema(c, FAST_SPAN)
|
||||
slow = bl.ema(c, SLOW_SPAN)
|
||||
# +1 when fast above slow, -SHORT_W when below: genuine EMA-cross direction,
|
||||
# short side de-weighted because the curves are persistently up-trending.
|
||||
raw = np.where(fast >= slow, 1.0, -SHORT_W)
|
||||
pos = bl.vol_target(raw, df, target_vol=TARGET_VOL,
|
||||
vol_win_days=VOL_WIN, leverage_cap=LEV_CAP)
|
||||
return np.clip(pos, -1.0, 1.0)
|
||||
Reference in New Issue
Block a user