Skip to content
All strategies

Strategies

Cross-Sectional Vol-Normalized Residual Reversal, Equal-Risk Long/Short (Dispersed Alt Basket, Binance USD-M, Pure OHLCV, Z-Score Rank, 2-Day Rebalance)

Outcome: Abandoned

CrossSectionalVolNormalizedResidualReversalLS

Outcome Summary

This strategy set out to fix raw reversal's high-vol-name domination by ranking a dispersed 12-name Binance USD-M alt basket on vol-normalized residual z-scores and sizing legs equal-risk, deliberately using pure OHLCV to sidestep the data-coverage walls that killed prior ideas. Mechanically it worked as designed — 3,062 dense, balanced trades and true market-neutrality with no sparsity or coverage artifacts. But the edge was decisively negative: -95.2% total return, 95.8% max drawdown, Sharpe -0.43, and losses in every one of the six regime years, with both long and short sleeves bleeding. The analyst abandoned it at the backtest-review gate as an inverted, negative-edge mechanism that no lookback tuning could rescue, noting that flipping to short-horizon cross-sectional momentum — and fixing the non-binding 1.0x gross cap — is the path worth exploring next.

Hypothesis

A MARKET-NEUTRAL cross-sectional SHORT-TERM REVERSAL strategy across a dispersed basket of ~12 liquid Binance USD-M perpetuals, hardened against the specific failure mode of raw reversal. Instead of ranking by raw trailing return (where a single high-volatility name mechanically tops/bottoms the rank and dominates the book), it ranks by VOL-NORMALIZED return — each name's trailing return divided by its own realized volatility (a per-name z-score / 'residual') — and sizes the legs EQUAL-RISK (inverse-volatility),……Show moreShow less

A MARKET-NEUTRAL cross-sectional SHORT-TERM REVERSAL strategy across a dispersed basket of ~12 liquid Binance USD-M perpetuals, hardened against the specific failure mode of raw reversal. Instead of ranking by raw trailing return (where a single high-volatility name mechanically tops/bottoms the rank and dominates the book), it ranks by VOL-NORMALIZED return — each name's trailing return divided by its own realized volatility (a per-name z-score / 'residual') — and sizes the legs EQUAL-RISK (inverse-volatility), so every position contributes the same risk and the signal reflects genuine relative OVER-EXTENSION rather than raw beta. Long the most-negative-z names (oversold relative to their own vol), short the most-positive-z names (overbought relative to their own vol), dollar/beta-neutral. CRITICAL DESIGN CHOICES grounded in this session's accumulated failures: (1) PURE OHLCV — uses NO supplementary data, deliberately and completely avoiding the data-coverage wall that just killed the OI-surge strategy (open_interest has only ~30 days of catalog history), the taker-flow strategy (3.5-year hole), and threatens every OI/taker-gated idea; OHLCV has full multi-year coverage for every basket member, so walk-forward OOS windows are never data-starved. (2) NON-momentum, NON-breakout — directional momentum/breakout is confirmed regime-dead across 14+ abandons; this is REVERSAL, the analyst's repeatedly-recommended chop-regime mechanism. (3) NOT a pairs-RATIO trade — the closed cross-asset ratio-MR family fails because a 2-asset ratio is non-stationary; a broad cross-sectional rank across 12 dispersed names is a fundamentally different, diversified statistical structure (no single non-stationary spread to blow up). (4) Genuine refinement over a raw-return reversal basket — the vol-normalized ranking + equal-risk weighting is the documented fix for raw reversal's high-vol-name domination. (5) NOT cross-venue/HL, NOT COIN-M, NOT drawdown-accumulation, NOT single-symbol RSI. Fires every 2 days across 12 names → dense OOS, immune to event-sparsity. Intentionally minimal: 3 tunables (zscore_lookback, vol_lookback, rebalance_days).

Iteration 2 fixes the Layer-2 synthetic failure: `_bar_ts` was a `@staticmethod def _bar_ts(bar)` but is invoked as `self._bar_ts(bar)`; under the verifier's proxy binding this passed 2 positional args to a 1-arg function (TypeError across all 6 scenarios). Converting it to a normal instance method `def _bar_ts(self, bar)` makes the arity match the call site. This is the smallest possible change — no imports, class structure, signal logic, or sizing were touched, preserving the already-passing Layer-1 static checks and all reversal/equal-risk construction.

Fundamentally negative-edge mechanism, not a tuning problem — no optimization can flip it. The cross-sectional vol-normalized reversal signal loses money in ALL SIX regime years (2021 -64.9%, 2022 -24.2%, 2023 -9.3%, 2024 -16.7%, 2025 -1.6%, 2026 -3.0%), total_return -95.2%, Sharpe -0.43 (CI straddles/negative: [-1.28, 0.24]), profit_factor 0.85, negative expectancy, both long and short sleeves losing. The signal fires densely and balanced (3,062 trades) so this is genuinely the reversal sign being ADVERSE at a……Show moreShow less

Fundamentally negative-edge mechanism, not a tuning problem — no optimization can flip it. The cross-sectional vol-normalized reversal signal loses money in ALL SIX regime years (2021 -64.9%, 2022 -24.2%, 2023 -9.3%, 2024 -16.7%, 2025 -1.6%, 2026 -3.0%), total_return -95.2%, Sharpe -0.43 (CI straddles/negative: [-1.28, 0.24]), profit_factor 0.85, negative expectancy, both long and short sleeves losing. The signal fires densely and balanced (3,062 trades) so this is genuinely the reversal sign being ADVERSE at a 5-day horizon on this alt basket, not a data or sparsity artifact. Two of the three tunables are lookback windows; tuning them cannot rescue an edge that is negative across every regime, and Sharpe is scale-invariant so the separate exposure bug (exposure_pct 600% despite gross_cap=1.0 and leverage=1.0 — the 'hard-capped 1.0x gross' construction is not actually netting/capping positions) only amplifies loss magnitude, not sign. Not worth 2 hours of optimization. NOTE for Research Lead: the mechanism appears inverted — short-horizon cross-sectional MOMENTUM (long recent relative winners, short losers) may carry the positive sign here; if that reframing is pursued, also fix the gross-exposure netting so the 1.0x cap actually binds.

Implementation

Market-neutral cross-sectional short-term reversal across a 12-name dispersed basket of liquid Binance USD-M perpetuals, pure OHLCV. Ranks names by vol-normalized residual z-score (trailing return / own realized vol), longs the most-negative-z (oversold) and shorts the most-positive-z (overbought), sizing each sleeve equal-risk (inverse-vol) with equal long/short gross budgets and a 1.0x gross cap. Rebalances every 2 days.

Verification Results

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['assets', 'gross_cap', 'vol_floor', 'resize_frac', 'min_notional', 'num_per_side', 'vol_lookback', 'qty_precision', 'rebalance_days', 'zscore_lookback', 'default_qty_precision'] Check that __init__ sets all attributes from self.parameters.get(). - steady_uptrend: TypeError: CrossSectionalVolNormalizedResidualReversalLS._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735690860000) - steady_downtrend: TypeError:……Show moreShow less

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['assets', 'gross_cap', 'vol_floor', 'resize_frac', 'min_notional', 'num_per_side', 'vol_lookback', 'qty_precision', 'rebalance_days', 'zscore_lookback', 'default_qty_precision'] Check that __init__ sets all attributes from self.parameters.get(). - steady_uptrend: TypeError: CrossSectionalVolNormalizedResidualReversalLS._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735690860000) - steady_downtrend: TypeError: CrossSectionalVolNormalizedResidualReversalLS._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735690860000) - flat_ranging: TypeError: CrossSectionalVolNormalizedResidualReversalLS._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735690860000) - volatility_spike: TypeError: CrossSectionalVolNormalizedResidualReversalLS._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735690860000) - zero_volume: TypeError: CrossSectionalVolNormalizedResidualReversalLS._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735690860000) - price_gap: TypeError: CrossSectionalVolNormalizedResidualReversalLS._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735690860000)

Backtest Review

Sharpe
-0.43
Total return
-95.16%
Max drawdown
95.81%
Trades
3062
Win rate
53.8%
Profit factor
0.85

Signal is functional and dense: 3,062 trades, balanced 1,604 long / 1,458 short, market-neutral (beta 0.002, benchmark_corr 0.004) — no data-coverage or event-sparsity wall as designed

Pure-OHLCV construction gives full multi-year coverage (2020-09 to 2026-06)

Catastrophic and consistent losses: total_return -95.2%, max_drawdown 95.8%, negative in EVERY regime year (2021 -64.9% ... 2026 -3.0%)

Negative-edge mechanism, not a tuning issue: Sharpe -0.43 (CI [-1.28, 0.24]), Sortino -0.47, profit_factor 0.85, negative expectancy, avg_win $284 < avg_loss $388 — the short-horizon cross-sectional reversal sign is adverse on this alt basket

Both sleeves lose despite win rates >0.5 (wins systematically smaller than losses)

Exposure blowup: exposure_pct 600% vs gross_cap=1.0 / leverage=1.0 — the 'hard-capped 1.0x gross' construction is not actually capping; but Sharpe is scale-invariant so this only amplifies magnitude, it does not create the negative edge

Extreme tails (kurtosis 444, skew 10, single +64% day 2021-01-29) confirm the neutral construction is not controlling risk

Outcome Summary

At a 5-day horizon on this alt basket the cross-sectional reversal sign is inverted — short-horizon cross-sectional momentum (long recent relative winners, short losers) may carry the positive edge, and the exposure-netting bug (600% exposure despite a nominal 1.0x gross cap) should be fixed so the cap actually binds.

The analyst issued an 'abandon' verdict at the pre-optimization backtest-review gate, judging the reversal sign to be fundamentally adverse (negative across all six regime years, both sleeves losing) rather than a tuning problem, so it never reached optimization, deeper analysis, or risk review.

A market-neutral cross-sectional short-term reversal strategy that ranked ~12 dispersed Binance USD-M alt perpetuals by vol-normalized residual z-score (trailing return divided by own realized volatility), going long the most-oversold and short the most-overbought names with equal-risk inverse-vol sizing, using pure OHLCV to avoid data-coverage limits.

Over 2020-09 to 2026-06 it fired densely and balanced (3,062 trades: 1,604 long / 1,458 short) and was genuinely market-neutral (beta 0.002, benchmark correlation 0.004), but posted total_return -95.2%, max_drawdown 95.8%, Sharpe -0.43 (CI [-1.28, 0.24]), profit factor 0.85, and negative expectancy (-$26/trade), with wins ($284) systematically smaller than losses ($388) and losses in every regime year.

Backtest and paper results are hypothetical. Trading involves risk of loss.