Skip to content

View original

EthBtcRatioMeanReversionFundingFilterLS

Hypotheses

ETH/BTC Ratio Mean Reversion + Funding Filter

Hypotheses

Companion variant to the ETH/BTC z-score mean reversion strategy, adding a funding-rate regime filter to skip entries during crowded directional markets. Same base logic: 4h bars on Binance USD-M Futures, ratio = ETHUSDT_close / BTCUSDT_close, 20-period rolling z-score, entry at |z| > 2.0, exit at |z| < 0.5 or |z| > 3.5 (stop) or 7-day time stop. NEW: requires funding_rates supplementary data for both ETHUSDT and BTCUSDT. Compute funding_spread = funding_ETH - funding_BTC (annualized, in basis points). SKIP entries when |funding_spread| > 10 bps annualized OR when |funding_ETH| > 50 bps annualized OR |funding_BTC| > 50 bps annualized — these conditions indicate crowded directional positioning where mean reversion often fails (alt-season melt-ups, BTC capitulation, etc.). Also skip when the trade direction would be paying funding on BOTH legs (e.g., long ETH + short BTC when ETH funding positive AND BTC funding negative). Position sizing equal USD notional per leg, 1-2x leverage, capital-relative. Edge: avoid the ~20-30% of trades that are mean-reversion-against-the-tape and capture the cleaner reversion signals. Hypothesis: funding filter lifts Sharpe by 0.2-0.4 and reduces max DD by 25%+ vs base strategy. Risks: filter may be too restrictive in trending crypto markets (reduces sample size), funding data lookups must handle the 8h funding interval mapping correctly, parquet timestamp format is datetime64 not int ms.

Hypotheses

Iteration-2 minimal fix for the leverage_set_but_unused gate. Root cause: the sizing path read leverage only indirectly via getattr(self.config, 'leverage', ...) inside the _leg_notional() helper, so the static gate that inspects position_size() for a direct self.config.leverage reference saw no usage and judged leverage=2.0 inert. The fix makes position_size() read self.config.leverage directly and compute notional = equity * leg_notional_frac * leverage / price inline, and switches _leg_notional() (used for the BTC leg) to the same direct attribute form. Leverage now visibly scales both legs' notional, so leverage=2.0 produces a genuinely 2x-larger position than 1x. Nothing else changed: imports are unchanged (Layer 1 stays green), and the z-score signal, funding filter, entry/exit gates, and multi-leg submission that passed earlier layers are byte-identical. The funding filter remains permissive when data is missing so the core reversion edge is still tested, and the ratio buffer stays a single synced series. Venue is BINANCE USD-M futures (shorts one leg, funding-rate-based filter); leverage=2.0 is within the 20x futures cap.

Hypotheses

This is the funding-filter companion to the already-abandoned ETH/BTC z-score mean-reversion pairs strategy, and it reproduces the same catastrophic failure: Sharpe -0.91 (CI -1.79 to -0.05, entirely negative), profit_factor 0.81, total_return -91.3%, expectancy -$99.5/trade, max_drawdown 93.9%, and negative in ALL 7 years (2020 -63%, 2021 -32%, 2022 -17%, 2023 -31%, 2024 -20%, 2025 -15%, 2026 -5%). The premise is dead: the ETH/BTC ratio trends rather than mean-reverts, so z-score reversion continuously fades the trend and loses across every regime -- the exact behavior that killed the sibling (Sharpe -1.97/-1.23). The supposed new feature does nothing: the funding-filter thresholds are left at funding_spread_max_bps=1000 and funding_leg_max_bps=5000 (annualized bps), levels real ETH/BTC funding spreads almost never reach, so the filter rarely blocks and all 912 trades run effectively unfiltered -- the hypothesized 'skip ~20-30% of crowded entries' never occurs, making this not a meaningful variant of the base strategy. Compounding it, avg_position_pct is 138% (leg_notional_frac 0.5 x two legs x leverage), turning a losing signal into a -91% return / 94% drawdown blowup. benchmark_meaningful is false (market-neutral pair), so this is judged on absolute metrics, which are catastrophic. Not optimize: no parameter set rescues a signal that loses in all 7 years; the sibling already established ETH/BTC reversion has no edge. Not iterate: tightening the funding filter to actually fire would only filter entries of a base signal that is itself negative in every regime -- filtering a losing strategy more selectively still loses; the premise, not the filter, is the flaw. This is NOT a funding-creditability issue (the engine now credits funding) -- it is a dead mean-reversion premise plus an inert filter. FAILURE PATTERN: ETH/BTC (and large-cap crypto) ratio z-score mean-reversion has no edge -- the ratio trends rather than mean-reverts, so |z|>2 reversion entries fade persistent moves and lose in every year (PF <0.85, negative Sharpe, deep drawdowns); bolting on a regime/funding filter does not help when (a) the filter thresholds are set so loose they never fire and (b) the underlying signal is negative across all regimes. A 'new variant' that leaves the losing core untouched and adds an inert feature is the same abandoned strategy.

Implementation

ETH/BTC ratio z-score mean reversion with a funding-regime entry filter, dollar-neutral long-short on Binance USD-M futures, 4H bars. ratio = ETH/BTC, 20-bar rolling z-score; enter |z|>2 (z>0 short ETH/long BTC, z<0 long ETH/short BTC), exit |z|<0.5, |z|>3.5 stop, or 42-bar (7-day) time stop. Skips entries when the annualized ETH-BTC funding spread or either leg's funding is too extreme, or when the trade would pay funding on both legs; passes the filter when funding data is missing. Each leg sizes notional = equity * 0.5 * leverage / price with leverage=2.0, so both legs deploy 2x their equity fraction. The signal is the continuous z-score every bar.

Verification Results

Verification failed (leverage_set_but_unused): config sets leverage=2.0 but the strategy never references leverage in sizing. Size positions on it — notional = equity * fraction * leverage / price (read self.config.leverage) — or set leverage=1.0. As written the leverage is inert and the backtest is identical to 1x.

Backtest Review

Code runs and trades as designed (912 trades, 0 dropped, balanced long/short legs, BTC leg submitted via multi-instrument helpers); leverage now wired into sizing

Backtest Review

Catastrophic, regime-independent loss: Sharpe -0.91 (CI -1.79 to -0.05), profit_factor 0.81, total_return -91.3%, expectancy -$99.5/trade, max_drawdown 93.9%, negative in ALL 7 years

Backtest Review

Dead premise: ETH/BTC ratio trends rather than mean-reverts -- identical failure to the already-abandoned ETH/BTC z-score pairs sibling (Sharpe -1.97/-1.23, every year negative)

Backtest Review

The funding filter is inert: thresholds (1000 bps spread / 5000 bps leg, annualized) essentially never trigger, so 912 trades run unfiltered -- the claimed 'skip 20-30% of crowded entries' did not happen and the new feature changes nothing

Backtest Review

Over-leveraged into the loss: avg_position_pct 138% turns a losing signal into a -91% return / 94% drawdown blowup

Outcome Summary

This was the funding-filter companion to an already-abandoned ETH/BTC z-score pairs strategy, meant to lift Sharpe and cut drawdown by skipping crowded directional entries. The iter-2 fix correctly wired leverage into sizing, but the result reproduced the sibling's catastrophe: Sharpe -0.91, profit factor 0.81, -91.3% total, a 94% drawdown, and losses in every one of seven years. Two flaws compounded it — the ETH/BTC ratio trends rather than mean-reverts so the reversion signal fades persistent moves, and the funding filter's annualized-bps thresholds were so loose that all 912 trades ran unfiltered, so the claimed edge never materialized while 138% average exposure amplified the bleed into a blow-up. The analyst abandoned it before optimization, concluding the premise (not the filter) is the flaw and that filtering a signal negative in all regimes more selectively still loses.

Outcome Summary

Large-cap crypto ratio z-score mean-reversion (ETH/BTC) has no edge because the ratio trends rather than reverts — bolting a regime/funding filter onto it does not help when the filter thresholds are set so loose they never trigger AND the underlying signal is negative across all regimes; filtering a losing strategy more selectively still loses, and a variant that leaves the losing core untouched is the same abandoned strategy.

Outcome Summary

The analyst abandoned it at backtest review as a dead premise plus an inert feature rather than a bug — the ETH/BTC ratio trends rather than mean-reverts, so z-score reversion continuously fades the trend and loses in every regime (reproducing the already-abandoned ETH/BTC z-score sibling), and the funding-filter thresholds were set so loose they never fired, so the 'new variant' left the losing core untouched.

Outcome Summary

A dollar-neutral ETH/BTC ratio z-score mean-reversion pairs strategy on Binance USD-M 4H futures (pure OHLCV plus funding-rate supplementary data) — fading 2-sigma deviations of the 20-period ETH/BTC ratio z-score (short ETH + long BTC when rich, the reverse when cheap) — with an added funding-rate regime filter meant to skip ~20-30% of crowded directional entries (large funding spread, extreme per-leg funding, or paying funding on both legs).

Outcome Summary

Over 912 trades (456 long, 456 short, none dropped) it was a catastrophic, regime-independent loser: Sharpe -0.91 (CI -1.79 to -0.05), profit factor 0.81, total return -91.3%, expectancy -$99.5/trade, max drawdown 93.9%, negative in all 7 years; the funding filter was inert (thresholds of 1000 bps spread / 5000 bps per leg almost never trigger, so all 912 trades ran unfiltered) and avg position 138% over-leveraged the losing signal into a blow-up.
Strategy report

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