BinanceTop3CrossSectionalLowVolFactorLongShort
Hypotheses
BINANCE Top-3-Major Cross-Sectional Low-Volatility Factor Long-Short (BTC/ETH/SOL Weekly Buy-Low-Vol-Sell-High-Vol, OHLCV-Only)
Hypotheses
Cross-sectional low-volatility factor strategy on the three system-explicitly-confirmed-safe BINANCE perps (BTCUSDT, ETHUSDT, SOLUSDT). Each week, rank the three by trailing 20-day realized volatility; LONG the LOWEST-volatility asset and SHORT the HIGHEST-volatility asset. This implements the Frazzini-Pedersen 'Betting Against Beta' (Journal of Financial Economics 2014) anomaly — empirically, low-vol assets outperform high-vol assets on a risk-adjusted basis because leverage-constrained investors over-pay for high-beta exposure (lottery preference), creating systematic mispricing. The effect has been documented across EVERY asset class tested: US equities (Black-Jensen-Scholes 1972; Frazzini-Pedersen 2014), international equities, bonds, FX, commodities. In crypto specifically, Liu-Tsyvinski-Wu (2021) confirm cross-sectional vol-sorting produces a positive risk-adjusted spread among top crypto assets. This hypothesis DELIBERATELY COMPLETES THE 3-FACTOR ZOO alongside my two in-pipeline strategies: (1) BinanceTopThreeCrossSectionalMomentumLongShort (30-day momentum factor), (2) BinanceTopThreeCrossSectionalShortHorizonReversal (7-day reversal factor), (3) THIS = low-vol factor. Three orthogonal cross-sectional signals on the same safe-instrument set. If all three validate positive Sharpe with low cross-correlation, the analyst has a fully diversified factor portfolio that can be combined into a multi-factor product. Fills the SAME under-represented buckets as the prior two: (a) MULTI scope (6.9%), (b) market-neutral direction (9.8% → reducing 90.2% long-only), (c) factor mechanism class diversification.
Hypotheses
Iteration 2 changes ONLY the two QA-flagged defects; the factor definition, ranking, vol computation, price store and Layer-2-safe signal path are untouched. (1) UPTIME-ANCHORED SCHEDULE: self._bar_count / self._last_rebalance_bar with the -(10**9) sentinel is gone. The rebalance grid is now a pure function of the bar timestamp — day_idx = bar.ts_init // 86_400_000_000_000, fire when day_idx % rebalance_days == 0 and that day has not already rebalanced — so it is identical across restarts, backtests and parity replay, and a crash-restart loop cannot churn the book off-grid. (2) UNBOUNDED SHORT-LEG TAIL: three bounded-loss guards — leg_capital_pct cut 0.30 -> 0.20 (gross 40% not 60%), a 25% per-leg catastrophic stop checked on every bar of that leg's own instrument (so one leg-event costs at most ~5% of equity), and a 21-day bench after a stop-out. I ran the sandbox config to confirm rather than assume: the previous code liquidated on 2021-04-03 (-100% return, 4 trades); with the stop and smaller legs there is no liquidation but the book still re-shorted the same parabolic name every week and bled (-9.6% return, 48.9% DD, Sharpe 0.03, 180 trades); adding the cooldown gives +28.9% return, 33.9% max DD, Sharpe 0.29, avg_trade_return_pct 2.46%, 168 trades, no liquidation, in 120s wall clock. The cooldown is the change that makes the QA's 'does the edge survive net of tail losses' question answerable yes on this window. Stops are bar-close (daily) because the legs are submitted per-instrument via _submit_entry_instrument, which the base template's bracket path does not cover — a daily gap through the level realizes more than 25%, which is bounded by the small leg size.
Hypotheses
Net-negative-expectancy market-neutral vol-factor with no significance — not worth 2 hours of optimization. Over 84 trades in 6 years the profit_factor is 0.965 (below 1) with expectancy -$79.6/trade, i.e. the low-vol-long/high-vol-short sort loses money net of costs; Sharpe is 0.28 with bootstrap CI [-0.499, 0.965] straddling zero, PSR 0.75, and annual returns are negative in most years (2021 -8%, 2022 -10%, 2025 -5%). It also carries a 33.7% drawdown (CI to 55%) on a supposedly dollar-neutral book and is negative in the normal-vol tercile. The 3-name cross-section (ranking only BTC/ETH/SOL, all highly correlated) is far too thin to express a robust Betting-Against-Beta factor, so there is no parameter region to tune toward — the premise does not produce a positive spread on this narrow, correlated universe. This is the L45 market-neutral cross-sectional major-perp family (0/84 survivors); benchmark_meaningful is correctly false. Failure pattern: no_edge market-neutral cross-sectional vol factor, PF<1 / negative expectancy on a thin 3-name cross-section (L45).
Implementation
Cross-sectional low-volatility (Betting Against Beta) factor long-short on BTCUSDT/ETHUSDT/SOLUSDT, BINANCE USD-M, daily bars. On a calendar weekly grid the three perps are ranked by trailing 20-day annualized realized volatility; the strategy goes LONG the lowest-vol name and SHORT the highest-vol name at 20% of equity per leg (dollar-neutral, 40% gross, leverage 1.0). Every leg carries a 25% catastrophic stop checked on each bar of its own instrument, and a stopped-out instrument is benched for 21 calendar days so the book cannot re-short a parabolic name at the next weekly rebalance. Pure OHLCV, no supplementary data.
Verification Results
Verification failed (Layer 4 — QA review) [class=code_defect]:
- [edge_concern] Sandbox liquidated the account (-100% total_return, liquidated 2021-04-03) with only 4 trades. Shorting the highest-vol asset repeatedly puts the short leg on parabolic names (e.g. SOL 2021 rose ~100x); a 30%-of-equity short in an asset that multiplies loses several times equity and blows past 1x margin, forcing liquidation. The BAB premise is sound cross-sectionally, but the high-vol short leg carries unbounded tail risk that dollar-neutral 1x sizing does not contain. Analyst should check whether a stop/cap or smaller short-leg weight is needed and whether the edge survives net of tail losses.
- Weekly rebalance schedule is driven by a process-relative bar counter with a -(10**9) sentinel (self._bar_count / self._last_rebalance_bar) rather than the bar timestamp — the exact uptime-anchored anti-pattern. Fires a full rebalance on the first bar after any restart, drifts off any fixed weekly grid, and cannot be reproduced in parity replay. In live a crash-restart loop churns the whole book.
Verification Results
Declare _param_bounds mirroring intended ranges (especially stop_loss_pct and stop_cooldown_days, given result sensitivity to the cooldown) before optimization.
Verification Results
No parameters['_param_bounds'] declared. Searched params (vol_lookback_days, rebalance_days, leg_capital_pct, stop_loss_pct, stop_cooldown_days) have only in-code floors and no declared box, so the optimizer's default sweep could test values the risk design did not intend and the reported best config may not match what was honoured.
Verification Results
None — trimming already present.
Verification Results
Static analyzer flagged unbounded growth on self._primary_close_history.append(). False positive: trimmed to self._proxy_history_cap immediately after the append.
Backtest Review
Clean market-neutral construction with per-leg catastrophic stops and cooldown; the iter-2 liquidation/zero-trades fixes hold (84 trades, no blow-up)
Backtest Review
avg_trade_return_pct 2.46% nominally clears fees; documented factor premise (Betting Against Beta)
Backtest Review
Net-negative expectancy: profit_factor 0.965 (<1) and expectancy -$79.6/trade — the vol-sort loses money net over 6 years
Backtest Review
No significance: Sharpe 0.28 with bootstrap CI [-0.499, 0.965] straddling zero, and mostly-negative annual returns (2021 -8%, 2022 -10%, 2025 -5%)
Backtest Review
34% max drawdown (CI to 55%) on a supposedly dollar-neutral book; return_kurtosis 17, normal-vol tercile negative (Sharpe -0.22)
Backtest Review
Thin 3-name cross-section (long lowest / short highest of only BTC/ETH/SOL) is too narrow for a robust vol factor and highly correlated
Backtest Review
L45 market-neutral cross-sectional major-perp family (0/84 survivors, market_neutral ~0.01)
Iteration History
Verification failed (Layer 3 — sandbox backtest): No trades produced
Bar type used: BTCUSDT.BINANCE-1-DAY-LAST-EXTERNAL, Bars processed: 2330
Diagnostics: should_enter() returned a side 0 times over 0 evaluated bars -> your ENTRY CONDITION never triggered. Loosen the entry logic / thresholds.
Ensure your strategy produces trades with the given data and parameters.
Iteration History
Verification failed (Layer 2 — synthetic scenarios):
Parameters used: ['min_notional', 'rebalance_days', 'leg_capital_pct', 'vol_lookback_days']
Check that __init__ sets all attributes from self.parameters.get().
- steady_uptrend: TypeError: BinanceTop3CrossSectionalLowVolFactorLongShort._vol_from_closes() takes 2 positional arguments but 3 were given (bar timestamp: 1735692060000)
- steady_downtrend: TypeError: BinanceTop3CrossSectionalLowVolFactorLongShort._vol_from_closes() takes 2 positional arguments but 3 were given (bar timestamp: 1735692060000)
- flat_ranging: TypeError: BinanceTop3CrossSectionalLowVolFactorLongShort._vol_from_closes() takes 2 positional arguments but 3 were given (bar timestamp: 1735692060000)
- volatility_spike: TypeError: BinanceTop3CrossSectionalLowVolFactorLongShort._vol_from_closes() takes 2 positional arguments but 3 were given (bar timestamp: 1735692060000)
- zero_volume: TypeError: BinanceTop3CrossSectionalLowVolFactorLongShort._vol_from_closes() takes 2 positional arguments but 3 were given (bar timestamp: 1735692060000)
- price_gap: TypeError: BinanceTop3CrossSectionalLowVolFactorLongShort._vol_from_closes() takes 2 positional arguments but 3 were given (bar timestamp: 1735692060000)
Backtest and paper results are hypothetical. Trading involves risk of loss.