Files
PythagorasGoal/scripts/research/blind/agents/agent_19_voltarget_lo.py
T
Adriano Dal Pastro 1afb1014c9 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>
2026-06-21 07:05:04 +00:00

59 lines
3.4 KiB
Python

"""Agent 19 — Vol-targeted long-only / risk-parity single asset
(family=vol, slug=voltarget_lo).
The angle (assigned): NO direction call. Hold the asset LONG at all times, but size
the position by INVERSE realized volatility so the book runs at a roughly constant
target volatility: exposure[i] = clip( target_vol / realized_vol[i] , 0, cap ).
Why this anticipates anything at all, despite never predicting direction: realized
vol is PERSISTENT (today's vol forecasts tomorrow's vol far better than today's return
forecasts tomorrow's return). The big declines on these two curves are also the high-
vol regimes — a crash is a vol spike. So scaling exposure DOWN when trailing vol is
high mechanically pulls the book light right when the worst legs happen, and levers UP
in the calm grind higher. The result on a structurally up-trending curve is a long-only
book with most of buy&hold's upside but a much smaller drawdown (the risk-parity / "vol
control" effect), at modest turnover (the weight only drifts with the vol forecast).
CAUSAL: realized_vol[i] uses returns over a trailing window ending at i (rows <= i);
the position is then shifted by the evaluator (held during bar i+1). No direction is
derived from any future bar; no global fit. Verified by causality_ok (max_diff 0.0).
Tuning (split='train' only, combined A&B). The free knobs are the trailing vol window,
the target vol, and the leverage cap.
* CAP is the single most important choice. Because both curves trend up hard, a high
cap just re-levers into buy&hold and brings the drawdown right back. cap=1.0 (never
more than fully invested) is what preserves the risk-parity de-risking benefit; with
a vol-driven weight that almost always sits below 1.0 this is the whole point.
* VOL_WIN is the vol-forecast horizon. A SLOW window (~120d) gives a stabler vol
estimate, less whipsaw, lower turnover and the BEST risk-adjusted result here:
sharpe_min climbs from ~0.85 (30d) to ~0.97 (120d) and the plateau (110..200d) is
flat at sharpe 0.91..0.99 / DD ~0.42-0.44 -> 120 is a robust interior pick.
* TARGET_VOL is a pure DD/PnL dial: it scales exposure up and down but (for a long-
only inverse-vol book) leaves the Sharpe essentially flat (0.971 across 0.24..0.32).
So it is chosen for the DD/PnL trade-off, not the Sharpe.
Chosen cell, interior on every axis:
TARGET_VOL = 0.28 # DD/PnL dial; Sharpe flat across 0.24..0.32 -> balanced cell
VOL_WIN_D = 120 # slow, stable vol forecast; plateau 110..200d
LEV_CAP = 1.0 # never lever past fully-invested -> keeps the DD-cut benefit
-> train combined: pnl_mean ~2.93, maxdd_worst ~0.43, sharpe_min ~0.97.
This is a DEFENSIVE long-only book, NOT alpha. Its honest value is the drawdown: ~0.43
vs ~0.77-0.79 buy&hold at comparable PnL. Because it never shorts, its Sharpe ceiling
(~1.0) is set by the absence of any direction call -> it can avoid sizing into the big
declines but cannot profit from them. That is the inherent limit of this angle.
"""
import numpy as np
import blindlib as bl
TARGET_VOL = 0.28
VOL_WIN_D = 120
LEV_CAP = 1.0
def signal(df):
# direction = always long (+1), NO direction call. Sizing is pure inverse-vol.
direction = np.ones(len(df))
pos = bl.vol_target(direction, df, target_vol=TARGET_VOL,
vol_win_days=VOL_WIN_D, leverage_cap=LEV_CAP)
# long-only risk-parity: clip to [0, cap] (no shorts by construction)
return np.clip(np.nan_to_num(pos, nan=0.0), 0.0, LEV_CAP)