LowVolAnomalyLongRotation10MajorsUsdmWeekly
Hypotheses
Low-Volatility Cross-Sectional Rotation, Long-Only (BINANCE USD-M, Weekly Hold the 4 LOWEST-Realized-Volatility Names From a 10-Major Universe — Betting-Against-Beta / Low-Vol Anomaly, a Sort Signal No Deployed Basket Uses, Defensive Tilt, 2-Parameter)
Hypotheses
A LONG-ONLY, weekly-rebalanced cross-sectional rotation over a 10-name deep-history BINANCE USD-M universe (BTCUSDT, ETHUSDT, SOLUSDT, BNBUSDT, AVAXUSDT, LINKUSDT, ADAUSDT, XRPUSDT, DOGEUSDT, LTCUSDT) whose sort signal is REALIZED VOLATILITY — explicitly a signal no promoted basket uses (the deployed cross-sectional winner ranks by relative-strength return; the deployed carry baskets rank by funding), satisfying L24's requirement for a genuinely new input rather than a re-weighting of relative strength. Each week it ranks the universe by trailing realized volatility (std of daily returns over a lookback) and holds the 4 LOWEST-vol names equal-weight. Mechanism/edge = the low-volatility / betting-against-beta anomaly: investors systematically overpay for high-volatility 'lottery' assets (in crypto, the meme/high-beta alts), so the lower-volatility names deliver superior RISK-ADJUSTED returns. Crucially, unlike raw-momentum rotation this tilt is DEFENSIVE — in high-vol/bear regimes the sort concentrates into the steadiest majors (BTC, ETH, LTC) and rotates AWAY from the high-beta alts that crash hardest, which is the same rotate-away-from-the-worst mechanic that let the deployed long-only momentum basket survive 2022 rather than the −60% death of the vol-managed long basket. It reuses the ONE long-only structure proven to survive here (weekly K-of-N rotation → sandbox-certifiable trade count, low turnover so fee-viable), on pure OHLCV with no data wall. It is NOT single-name MR/reversal (the confirmed-dead family), NOT funding carry (mapped/saturated), NOT options (L23), NOT a market-neutral L/S basket (L12 fee wall — this is long-only), NOT trend-following, and NOT a relative-strength rotation duplicate (different sort signal, different risk profile). 2 core parameters (vol lookback, number of held names).
Hypotheses
I profiled the reported Layer-3 timeout rather than guessing, and the diagnostic's assumed cause (per-bar work scaling with history) is not what is happening here. Running this exact config through subprocess_entry completed the FULL history in 149s inside runner.run() with only 141 trades over 2,438 primary bars. cProfile on a 1-year window shows 206 of 209 seconds in ParquetDataCatalog.query -> fsspec glob/find/ls/stat (2.9M info() and 2.6M stat() calls walking the catalog tree); engine plus strategy execution was about 3 seconds, and no strategy function appears in the top 35 by cumulative time. I then timed the catalog directly: one bar type costs 56.9s and three bar types 45.2s, so the cost is per CALL (a full-tree glob) and not per leg. The runner batches the extras into ~2 bars() calls plus a 24s instruments() scan, which is the ~200s I/O floor this run pays before a single bar is processed. That means shrinking the 10-name universe would NOT have fixed the timeout and would only have weakened the hypothesis's cross-sectional breadth, so I kept the universe intact. What I did change are the two real work reducers available in strategy code: (1) on_extra_bar no longer calls _maybe_rebalance() -- the rotation clock is the primary BTC day, so the 9 extra legs were repeating a gated check 9 times per day for nothing, and the rebalance still fires once per primary bar after every leg for that day is recorded; (2) re-equalisation is now drift-gated at 15% of target notional instead of a flat $25 floor, which at roughly $22.5k per sleeve fired an order for nearly every name every week -- this cuts order/fill/position work in the engine and, more importantly for the hypothesis, cuts fee drag on a strategy whose entire viability rests on low turnover. All state remains O(1)-bounded (closes capped at _max_history, no full-history rescan), imports are unchanged, and the signal, ranking, regime gate and sizing are untouched so Layers 1 and 2 stay green. HONEST CAVEAT for the reviewer: these changes trim engine-side work but cannot move the ~200s catalog-glob floor, and the standalone 149s becomes >300s under concurrent sandbox load. The durable fix is operator-side in the catalog query path -- get_file_list_from_data_cls globs the entire data/bar tree per query where a direct path listing (what InstrumentResolver already does with a single stat call) would make it near-instant. If Layer 3 times out again, that is where to look, not in this file.
Hypotheses
Long-crypto-beta cross-sectional basket that fails to beat its own benchmark and whose headline is mostly unrealized — not worth 2 hours of optimization. The +2093% total_return is dominated by un-exited open positions (end_unrealized_pct 623.9), so it is not a realized edge; judged on risk-adjusted metrics it is not significant (Sharpe 0.684 with bootstrap CI [-0.011, 1.173] straddling zero) and its information_ratio versus the equal-weight-basket benchmark is NEGATIVE (-0.24) — the low-vol sort does not add risk-adjusted value over a naive equal-weight basket, it is just long-crypto beta (beta 0.29, benchmark_correlation 0.60). It carries the L36 compounding/leverage-artifact signature (avg_trade_return_pct 12.29% — many multiples of a major's weekly move — return_kurtosis 410, exposure_pct 222.95% exceeding the stated 0.90 gross), a 39.1% max drawdown (CI to 83%) concentrated in the bull years (2021 +347%, 2022 -10%, 2026 -6.8%, yen-carry 2024 -19%). This is the L45 multi-instrument cross-sectional basket family (0/84 survivors) crossed with the L49 long-only basket carried by beta; benchmark_meaningful is true and it loses to that benchmark. Optimization would curve-fit the vol-sort to the bull regimes. Failure pattern: no_edge/risk_reject long-only cross-sectional basket, beta-carried, negative IR vs benchmark (L45/L49/L36).
Implementation
Long-only weekly low-volatility cross-sectional rotation over 10 BINANCE USD-M majors on 1-DAY bars. Every rebalance_days (7) primary days, if BTC is above its 100-day SMA (portfolio-level risk-on gate), the universe is ranked by trailing 30-day realized volatility of daily returns and the 4 LOWEST-vol names are held equal-weight at 90% gross; if BTC is below its regime SMA the book rotates entirely to cash. Names that fall out of the target set are closed first, then surviving winners are re-equalized to the equal-weight target only when their sleeve has drifted more than reequalize_drift_frac (15%) of target notional, keeping turnover and fees proportional to actual drift. Legs whose last bar is more than max_staleness_days old are excluded from that week's ranking. Leverage 1.0, gross under 1x so no margin is consumed.
Verification Results
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-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 Review
Well-formed weekly K-of-N rotation with a regime gate; 141 trades, low fee drag (1.07% of gross); genuinely novel sort signal (realized-vol) vs deployed baskets
Backtest Review
Deep-history 10-major universe, no data wall
Backtest Review
Headline is ~6x open-position unrealized (end_unrealized_pct 623.9 vs total_return 2093%) — not a realized edge
Backtest Review
Not significant: Sharpe 0.684 with CI [-0.011, 1.173] straddling zero; information_ratio vs its equal-weight-basket benchmark is NEGATIVE (-0.24) — does not beat a naive basket
Backtest Review
L36 compounding/leverage artifact signature: avg_trade_return_pct 12.29%, return_kurtosis 410, exposure_pct 222.95% (exceeds stated 0.90 gross)
Backtest Review
Long-crypto beta carried by 2021/2023/2025 bulls (beta 0.29, corr 0.60); max_drawdown 39.1% (CI to 83%); yen-carry 2024 -19% stress
Backtest Review
L45 cross-sectional multi-instrument basket family (0/84) + L49 long-only basket large-DD family
Iteration History
Verification failed (Layer 4 — QA review):
- Catastrophic negative edge -- the low-vol anomaly is inverted on this crypto universe/window. total_return -51.12%, profit_factor 0.190, win_rate 0.231, avg_trade_return_pct -6.68%, max_drawdown 60.69%. Holding the 4 LOWEST-realized-vol majors lost heavily because in crypto a low trailing realized vol frequently flags a name that has been quietly bleeding or ranging before a breakdown -- NOT the defensively 'steady' major the thesis assumes -- so the sort selected into names that then crashed. This is a pure-OHLCV cross-sectional-rank rotation, the L7 zero-survivor family; the developer's own note that a MOMENTUM-rank version survived underlines the problem: momentum-rank holds names with positive drift, low-vol-rank holds stagnant/bleeding names. The defensive premise is falsified here.
- The portfolio does not behave like the stated 90%-gross, 4-leg long-only majors basket -- either a rebalance/exposure bug or non-representative execution. avg_position_pct is 26.3%, beta to the equal-weight majors benchmark is 0.152, and benchmark_correlation is 0.21. A properly-invested long-only basket of 4 majors at 0.90 gross MUST track the majors closely (gross ~90%, beta ~0.9); 26% gross and beta 0.152 indicate it is severely under-invested or churning/frozen. A likely cause is the rebalance-alignment gate: _maybe_rebalance returns unless all(d == current_day for d in self._last_day_index.values()), so ANY single-symbol missing daily bar makes the freshest symbols' current_day never equal the lagging symbol's day, stalling rebalances indefinitely; the reequalize_min_notional dead-band could also leave legs unfilled. If the basket is not actually held at target gross, the -51% result is not even a faithful test of the hypothesis.
- Trade count 26 over 363 days is below the ~100-trade measurability floor (L16) for a general edge conclusion, though the loss magnitude (PF 0.19, -51%) makes the negative direction unambiguous here. Also note the exposure anomaly above means turnover/impact figures may not reflect a correctly-sized book.
Iteration History
Verification failed (Layer 4 — QA review):
- The low-vol sort still has negative edge after the defensive trend gate. total_return -19.60%, profit_factor 0.532, win_rate 0.317, avg_trade_return_pct -2.14%, Sharpe -0.79, max_drawdown 30.8%, with fat-tail losses (skew -2.44, kurtosis 31.8, largest_loss -$4,232). Even after excluding low-vol names below their SMA, the names that qualified still underperformed. The trend gate reduced the loss (v1 -51% -> v2 -19.6%) mainly by parking the book in cash, not by producing positive edge. Two iterations, both net-negative -- the low-volatility anomaly (an equities result) does not transfer to this crypto universe/window; low trailing realized vol keeps flagging names that then underperform. This is the pure-OHLCV cross-sectional-rank rotation L7 zero-survivor family.
- The book is still far below the design gross, so the sandbox again is not a faithful test of the 4-name 90%-gross basket. The developer states it 'now holds the intended ~90% gross', but the sandbox shows avg_position_pct 22.77% and beta 0.045 to the equal-weight majors benchmark -- i.e. ~1 name held on average, mostly cash. The stall-bug fix is real, but the added defensive trend gate now excludes most names in this down window, so the strategy holds a highly concentrated ~1-name book rather than the diversified 4-name basket the hypothesis describes. Whether one calls this 'working as designed' (defensive) or under-investment, the run does not test the stated 4-name low-vol basket, and the concentrated book it did hold lost -19.6%.
- 41 trades over 363 days is below the ~100-trade measurability floor (L16) for a general edge conclusion, though PF 0.532 / -19.6% makes the negative direction unambiguous. The concentrated, mostly-cash book also means turnover/impact figures do not reflect a fully-invested basket.
Backtest and paper results are hypothetical. Trading involves risk of loss.