VolTargetedLongCashBasket10MajorsSpotWeekly
Hypotheses
Crypto-Majors PORTFOLIO-VOLATILITY-TARGETED Long/Cash Basket, Long-Only (BINANCE_SPOT, 10 Equal-Weight Deep Majors, Weekly: Invested Gross = target_vol / realized_vol — Exposure COLLAPSES Toward Cash as Volatility Spikes (Crashes Cluster with Vol), a FAST Drawdown Defense the Slow Momentum Cash-Exit Lacked — UNLEVERED So No Liquidation, 2-Parameter)
Hypotheses
A LONG-ONLY, diversified, DRAWDOWN-DEFENDED spot basket built from the autopsy of this session's failures: the slow monthly momentum cash-defense STILL hit 76.78% drawdown because it reacted too late, and every leveraged single-name/pairs trade LIQUIDATED at -100% from over-sizing. The fix applied here is portfolio-level VOLATILITY TARGETING (the Moreira-Muir vol-managed mechanism), which de-risks on a signal that moves FAST at crash onset — realized volatility — rather than a lagging price/momentum trend. Each week the invested gross fraction = target_vol / realized_vol (capped at 100%, floored at 0): when the equal-weight 10-major basket (BTC, ETH, SOL, BNB, XRP, ADA, AVAX, LINK, DOGE, LTC) is calm, it is near fully invested; when volatility spikes — which in crypto clusters tightly with drawdowns and crashes — exposure automatically collapses toward USDT within days, capping the tail far better than the slow cash-exit that failed. It trades on the SPOT CASH account (no leverage, no margin → liquidation is mathematically impossible) and holds a DIVERSIFIED equal-weight book (max ~10% per name → no single-name blowup). The signal — realized volatility as an exposure scaler — is a mechanism NO deployed basket uses (they use per-name momentum rank and per-name funding), satisfying L24's new-signal requirement, and it is NOT a rank/rotation sort (equal-weight all names → not the L12/L24 duplicate), NOT the dead per-name inverse-vol-WEIGHTED leveraged momentum basket (this scales TOTAL gross to CASH and never levers), NOT carry/options/liquidation-feed/single-name-reversion. Pure OHLCV, data-safe; 2 core parameters (target volatility, realized-vol lookback).
Hypotheses
The reported failure was Layer 1 CONFIG only — instrument_id and bar_type arrived as None, so the strategy itself was never evaluated. The fix is the config: BTCUSDT.BINANCE_SPOT primary with 1-DAY bars plus the nine other majors as extras, all of which I verified exist in the catalog as BINANCE_SPOT 1-DAY series, on the CASH venue with leverage 1.0 (the sizing path never multiplies by leverage, so requesting more would be inert). Two small code fixes ride along, both targeted and both consistent with rules I am held to. First, the rebalance cadence was firing on self._bar_count % rebalance_days — a process-relative counter, which is the uptime-anchored anti-pattern: the grid's phase depended on when the process started, a restart shifted every future rebalance date, and a backtest could not be reproduced by a paper replay. It is now a pure function of the bar's timestamp (epoch day index divisible by rebalance_days, at most once per day). The vol-lookback warmup still counts bars, which is correct — that is a data-sufficiency check, not a schedule. Second, _closes_for walked each leg's entire buffered history (up to 500 bars) converting every close, once per name for the vol estimate and again per name in the rebalance — roughly 15k Cython conversions per bar across ten names, which is exactly what timed out an earlier Layer-3 run of this strategy. Both callers now slice only the tail they need (vol_lookback + 1 closes for the vol estimate, the last bar only for the rebalance price), leaving the arithmetic identical. The vol-targeting mechanism, the equal-weight construction, the long-only netting deltas and the churn band are otherwise unchanged.
Hypotheses
Degenerate backtest whose stated mechanism never operated and whose premise fails — not worth 2 hours of optimization, and already iterated 3x. The metrics are self-contradictory and untrustworthy: total_trades 10 with avg_holding_period 2,161 days (i.e. it bought 10 legs once and held them the whole 6 years = buy-and-hold), yet trades_count 9,110 and commission 17.88% of gross, and the ENTIRE reported return is a single +142.9% print on the last bar (daily_returns and annual_returns each carry one 2026-09-03 entry) — a broken equity curve, so Sharpe 0.56 / Calmar 176 / PF 90.6 are accounting artifacts, not edge. The vol-targeting rebalance that is the whole hypothesis effectively never fired, so the dynamic drawdown defense was never actually tested; and where the numbers are legible it demonstrably fails — max_drawdown 39% (CI to 61%) with double-digit losses in every 2022 stress window (LUNA -15%, FTX -13%, rate-shock -22.5%). information_ratio is -0.93 versus its own equal-weight-basket benchmark, so the overlay subtracts risk-adjusted value and the result is just long crypto beta (benchmark_correlation 0.58); sharpe_ci_low -0.08 straddles zero. This is the L45/L49 long-only basket family reduced to buy-and-hold with a failed vol overlay. Failure pattern: no_edge/risk_reject long-only basket, beta-carried with negative IR vs benchmark, broken/ineffective vol-target implementation and degenerate equity curve (L45/L49).
Implementation
Long-only, unlevered, portfolio-volatility-targeted equal-weight spot basket of ten crypto majors (BTC, ETH, SOL, BNB, XRP, ADA, AVAX, LINK, DOGE, LTC on BINANCE_SPOT, 1-DAY bars). Each rebalance the invested gross fraction is set to target_vol / realized_vol, capped at 100% and floored at 0, where realized vol is the annualized volatility of the equal-weight basket's daily returns estimated as the max of a 10-day window and a 3-day fast window so a fresh cluster of turbulent days cuts exposure within days rather than after the full lookback. Each name receives gross/10 of equity, so the book is near fully invested when calm and collapses toward USDT when volatility spikes (which in crypto clusters with crashes). Rebalancing happens on a calendar grid derived from the bar's own timestamp, with a small churn band to avoid micro-trades. Cash account with leverage 1.0 means shorting and liquidation are both impossible, and equal weighting caps single-name exposure near 10%.
Verification Results
Verification failed (Layer 1 — config): config.instrument_id and config.bar_type are REQUIRED (got instrument_id=None, bar_type=None). Set both to the hypothesis's instrument, e.g. instrument_id='BTCUSDT.BINANCE', bar_type='BTCUSDT.BINANCE-4-HOUR-LAST-EXTERNAL'.
Verification Results
Consider returning without trading on a non-positive equity read rather than assuming $100k. Not required for correctness.
Verification Results
_rebalance falls back to equity=100_000.0 when get_account_equity() returns <=0. Harmless in backtest and useful for the verification proxy, but a silent hardcoded equity fallback could size off a fictional balance if the equity read ever fails unexpectedly.
Verification Results
None — guards already present.
Verification Results
Static analyzer flagged division by ann_vol, n, price. All guarded: ann_vol<=0 returns max_invested; n=max(1,len(basket)); price<=0 closes/skips the leg before the divide.
Backtest Review
Safe by construction (spot CASH, unlevered, long-only, equal-weight — no liquidation, no single-name blowup)
Backtest Review
Deep multi-year universe, pure OHLCV, no data walls
Backtest Review
Degenerate/untrustworthy metrics: total_trades 10 with avg_holding_period 2,161 days (buy-and-hold), yet trades_count 9,110 and commission 17.88% of gross; the entire return is a single +142.9% print on the last bar (2026-09-03) — the equity curve is broken, so Sharpe/Calmar/PF are artifacts
Backtest Review
The vol-targeting rebalance effectively never operated (10 net positions over 6 years), so the hypothesized dynamic drawdown defense was not actually tested
Backtest Review
Where legible, the defense FAILED: max_drawdown 39% (CI to 61%), double-digit losses in every 2022 stress window despite the vol gate
Backtest Review
Negative information_ratio (-0.93) vs its equal-weight-basket benchmark — the overlay subtracts risk-adjusted value; it's long crypto beta (benchmark_correlation 0.58); sharpe_ci_low -0.08 straddles zero
Backtest Review
L45/L49 long-only basket family, reduced here to buy-and-hold with a broken vol overlay
Iteration History
Verification failed (Layer 4 — QA review):
- The position-quantity read is almost certainly broken, disabling the entire de-risking mechanism. In _rebalance the code does `q = float(cur.quantity)` inside a try/except that falls back to `q = 0.0`. Everywhere else in this codebase a position size is read as `float(pos.quantity.as_double())` (the beta-neutral, breadth, and capitulation siblings all use .as_double()); `float(Quantity)` is not the supported accessor and, if it raises, the except silently sets cur_qty = 0.0 on EVERY rebalance. With cur_qty stuck at 0, delta = target_qty - 0 is always positive, so the code always takes the BUY branch and NEVER computes a de-risking SELL. The book can only add/hold and can never collapse toward cash when volatility spikes — the strategy's whole reason to exist.
- The hypothesis's sole promise — a FAST vol-targeted drawdown defense that caps the tail — did NOT happen: max_drawdown 42.88% (near the 50% hard-abandon, comparable to the siblings it was meant to beat), total_return -34.86%, Sharpe -1.31, PF 0.0, win_rate 0.0. The behavior is buy-and-hold, not weekly de-risking: turnover 0.65, avg_holding_period 322 days (positions never effectively reduced), and self-inconsistent metrics (avg_trade_return_pct +46.83% while avg_trade_pnl_usd -$3,522, all 10 legs losers). A functioning vol-target book would show higher turnover and a much smaller drawdown if exposure actually collapsed on the vol spike. The mechanism is not executing as coded.
- Even once execution is fixed, the defense may be too laggy: a 20-day realized-vol estimate + weekly rebalance + a 1%-of-equity churn band means exposure only steps down after a sustained vol rise and only when a per-leg delta exceeds ~$1k, so a fast single-week crash is largely un-hedged. The hypothesis claims de-risking 'within days'; a 20-day lookback cannot react within days.
Iteration History
Verification failed (Layer 4 — QA review):
- The strategy's DEFINING mechanism -- invested gross collapsing toward cash on a volatility spike as a FAST drawdown defense -- is not demonstrated and appears non-functional. This is iteration 3; iter-2 was rejected because the de-risking SELL branch never fired (buy-and-hold, ~322-day holds, DD 42.88%). iter-3's stated fix was to correct the current-quantity read (_long_qty/signed_qty) so target_qty < cur_qty produces a de-risking SELL. But the sandbox shows the behavior is essentially UNCHANGED: max_drawdown 43.49% (vs 42.88% when the branch was admittedly broken), avg_holding_period 341 days across ALL 10 legs, total_trades 10 (each name opened once and closed once at the window end), and turnover FELL 0.65 -> 0.56. A working 2-day vol-target rebalance should RAISE turnover and materially reduce the tail vs buy-and-hold; instead turnover dropped and drawdown is flat. The iter-3 fix cannot be confirmed to have changed behavior -- the book is still acting as a static long basket.
- Code-defect signature in the sandbox: win_rate=0.0, profit_factor=0.0, avg_win=0.0 with metrics_reliable=true over a 363-day window -- every one of the 10 positions closed at a loss and there is not a single winning trade. For an equal-weight basket of 10 majors held ~a full year this is the exit/rebalance-logic signature (positions are effectively marked at the window end because the intended mid-stream de-risking never re-shapes them), not a routine edge shortfall. Combined with the unchanged drawdown above, it indicates the rebalance loop is not exercising the risk-reduction path the hypothesis requires.
- target_vol=0.50 (50% annualized) is a high vol budget relative to crypto-major realized vol (~60-90% annualized), so gross typically sits ~0.6-0.85 -- the book stays MAJORITY long crypto through a downturn, and because realized vol LAGS the first crash day, even a correctly-firing vol-target de-risks only after part of the drawdown has already occurred. This structurally limits the 'FAST tail defense' the hypothesis promises. Even once the mechanism is confirmed to fire, a 43% drawdown is likely with this budget.
- Class-level survival risk (informational): this is a pure-OHLCV, long-only equal-weight crypto-major basket whose P&L is dominated by crypto beta. That class has a very poor survival record in this factory; the vol-target overlay is the only differentiator, so it MUST measurably work to justify the strategy. As shown above, it currently does not.
Iteration History
sandbox_timeout: Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit on a ~20000-bar window (2400 days of BTCUSDT.BINANCE_SPOT-1-DAY-LAST-EXTERNAL). This almost always means per-bar work that scales with history — e.g. rescanning the full funding/supplementary series, or rebuilding a list and calling min()/sorted() inside calculate_signal()/on_bar() on every bar. Precompute sorted timestamp arrays ONCE in __init__ and use bisect, or cache lookups keyed by timestamp, so per-bar cost is O(log n) not O(n).
Backtest and paper results are hypothetical. Trading involves risk of loss.