Skip to content

View original

EthCrossVenuePerpBasisMeanReversionLS4H

Hypotheses

ETH Inter-Exchange Perp Basis Mean-Reversion (Hyperliquid vs Binance, 4H, Long-Short)

Hypotheses

Market-neutral cross-venue basis arbitrage on ETH perpetuals between Hyperliquid (ETHUSD.HYPERLIQUID) and Binance USD-M futures (ETHUSDT.BINANCE). The two venues have different participant mixes (HL is dominated by sophisticated/retail-degen traders; Binance USD-M is the deepest global perp book) and different funding cycles (HL hourly, Binance 8h). This creates transient inter-exchange price spreads of 0.20–0.80% that re-converge within 1–3 four-hour bars as cross-venue arbitrageurs (market makers, basis traders) close the gap. The strategy detects when the percentage spread (HL_close - BIN_close) / BIN_close exceeds a rolling z-score threshold of |z| > 2.0 over a 60-bar lookback, then longs the cheaper venue and shorts the richer venue in equal notional. Position closes when the z-score reverts to |z| < 0.3 or after a 4-bar (16h) time-stop. This is NOT a classical chart pattern, NOT a directional momentum/reversal trade, and NOT funding-carry — it's pure inter-venue mean-reversion driven by a structural arbitrage mechanism. Targets the heavily under-represented HYPERLIQUID venue (4.1% vs 20% quota), cross-venue scope (4.6% vs 15% quota), and long-short direction (9.2% vs ~45% target) simultaneously.

Hypotheses

Iteration-5 fix (leverage_set_but_unused). The gate scans the stored strategy code for a leverage reference (config.leverage / self._lev / .leverage) and rejects when leverage>1 is declared but absent from the code. I wired leverage into the sizing path unambiguously: position_size() now reads `leverage = float(self.config.leverage)` directly and computes `notional = equity * exposure_frac * leverage`, and the mirrored Hyperliquid leg uses that same leverage-scaled notional — so 2x leverage doubles both legs' notional (real margin effect, not inert). This is the smallest change that satisfies the gate while preserving all previously-passing signal logic (spread z-score, entry/exit, atomic two-leg management) and imports. Leverage 2.0 is appropriate here because the position is market-neutral (equal-notional long/short), so 2x per-leg keeps directional risk near zero while making the basis edge economically meaningful.

Hypotheses

Fee-dominated cross-venue basis mean-reversion with a structural, untunable negative edge — not worth optimizing. The ETH Hyperliquid-vs-Binance perp basis is only a few bps to ~0.3%, but a market-neutral round trip pays FOUR taker fills (open+close on both legs), so the ~0.2-0.4% two-venue cost floor exceeds what the spread reverts. The backtest bleeds steadily: Sharpe -9.85, Sortino -13.8, profit_factor 0.908, omega 0.097, expectancy -$103/trade, total_return -24.9%, with every month negative except one and all three years (2024 -7.6%, 2025 -11.3%, 2026 -6.0%) negative; commission is 10.1% of gross ($45.9k + $23.4k impact). The current config already selects the widest dislocations (entry z>2 over 60 bars) and still loses with a 48.4% win rate and avg_win ~ avg_loss, so raising entry_z / lengthening the hold reduces trade count but cannot lift a few-bps basis above the 4-fill cost floor. This is not a code bug (the strategy runs cleanly, market-neutral, beta 0.002) and there is no promoted cross-venue sibling stranded on a dead target — the mechanism itself is fee-floored. FAILURE PATTERN: cross-venue perp-basis mean-reversion on a major (ETH HL vs Binance) is structurally fee-dominated — the tradable inter-exchange spread (single-digit bps) is smaller than the 4-fill two-venue round-trip cost, producing a consistent PF<1 bleed that z-threshold tuning cannot reverse.

Implementation

Market-neutral cross-venue basis mean-reversion on ETH perpetuals between ETHUSDT.BINANCE (primary) and ETHUSD.HYPERLIQUID (extra leg), 4H bars. The percentage spread (HL-BIN)/BIN is z-scored over a 60-bar rolling window; when |z|>2.0 the strategy longs the cheaper venue and shorts the richer venue in equal notional, closing both legs on re-convergence (|z|<0.3) or a 4-bar (16h) time-stop. Per-leg notional = equity * exposure_frac * leverage, so the configured 2x leverage genuinely doubles gross exposure.

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

Strategy is mechanically sound and runs cleanly: 446 market-neutral trades, timestamp-aligned SyncedBuffer, genuinely low beta (0.002) and benchmark correlation (0.03), no liquidation or bug

Backtest Review

Targets under-represented Hyperliquid/cross-venue/long-short buckets as intended

Backtest Review

Consistent structural loss: Sharpe -9.85, Sortino -13.8, profit_factor 0.908, omega 0.097, expectancy -$103/trade, total_return -24.9% — every month negative except one, all three years negative

Backtest Review

Fee-dominated: a cross-venue basis round trip pays 4 taker fills (open+close on both Binance and HL legs); commission is 10.1% of gross ($45.9k commission + $23.4k impact), and the few-bps ETH HL-Binance basis cannot clear that cost floor

Backtest Review

Top-spread selection already fails: at entry_z>2 the win rate is 48.4% with avg_win ~ avg_loss — the widest dislocations do not reliably converge profitably, so raising the threshold cannot manufacture edge

Backtest Review

No code bug and no promoted cross-venue sibling — the negative edge is intrinsic to the mechanism, not a fixable implementation error

Analysis

The strategy bleeds because it trades a spread smaller than its own round-trip cost. Two required changes before this is worth optimizing: (1) Add a HARD cost-aware entry gate: only enter when the RAW percentage spread |(HL-BIN)/BIN| at signal time exceeds a floor that clears the two-leg round-trip cost (BINANCE ~0.10% + HYPERLIQUID ~0.09% ≈ 0.20% round-trip; require the spread to be at least ~2x that, e.g. > 0.40%). A z-score of 2.0 on a spread whose absolute magnitude is only a few bps is untradeable — gate on absolute spread size, not just z. (2) Instrument/verify the spread is REAL, not a bar-misalignment artifact: log the distribution of the raw entry spread. If entries are firing at |spread| of only 0.05-0.15% (a few bps to ~15bps), the hypothesized 0.20-0.80% premium does not exist on this pair and the signal is timing noise between venues — in that case the mechanism cannot work on ETH HL-vs-Binance regardless of z-thresholds, and it should be reframed onto a venue pair with a genuinely wider, slower-converging basis (or abandoned). Also reduce churn: the 4-bar time-stop forces exits that pay fees without waiting for convergence. Re-backtest; if the cost-gated version still shows profit_factor < 1.0, the premise is dead and this should not proceed to the 2-hour optimization.

Outcome Summary

This strategy targeted the under-represented Hyperliquid, cross-venue, and long-short buckets with a market-neutral ETH basis trade between Hyperliquid and Binance, fading z-score dislocations wider than 2.0 for re-convergence. Mechanically it worked flawlessly — 446 clean market-neutral trades, near-zero beta, no bugs — but it lost money every month but one and in all three years, posting Sharpe -9.85 and total return -24.9% as commissions ate 10.1% of gross. The analyst's backtest review flagged the loss as intrinsic: a four-fill two-venue round trip costs 0.2–0.4%, more than the few-bps ETH basis ever reverts, so widening the entry threshold only cuts trades without creating edge. It was abandoned at the pre-optimization gate after 5 iterations as a structurally fee-dominated mechanism not worth optimizing.

Outcome Summary

Cross-venue perp-basis mean-reversion on a liquid major is fee-floored: a four-fill, two-venue round trip costs more than the single-digit-bps spread reverts, and raising the z-threshold cannot manufacture edge the mechanism structurally lacks.

Outcome Summary

The analyst's pre-optimization backtest review returned an 'abandon' verdict, judging the negative edge structural rather than a code bug — a two-venue round trip pays four taker fills, a ~0.2–0.4% cost floor that exceeds the few-bps ETH inter-exchange spread, so it was killed before the 3-phase optimization.

Outcome Summary

A market-neutral, long-short basis arbitrage that z-scored the ETH perp price spread between Hyperliquid and Binance USD-M and, when |z| > 2.0, longed the cheaper venue and shorted the richer one expecting the 0.2–0.8% dislocation to re-converge within 1–3 four-hour bars.

Outcome Summary

It ran cleanly and market-neutral (beta 0.002, benchmark correlation 0.03) across 446 trades but bled steadily: total return -24.9%, Sharpe -9.85, Sortino -13.8, profit factor 0.908, expectancy -$103/trade, 48.4% win rate with avg_win ≈ avg_loss, and commission at 10.1% of gross ($45.9k fees + $23.4k impact).

Iteration History

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['exit_z', 'entry_z', 'lookback', 'min_notional', 'exposure_frac', 'time_stop_bars'] Check that __init__ sets all attributes from self.parameters.get(). - steady_uptrend: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000) - steady_downtrend: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000) - flat_ranging: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000) - volatility_spike: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000) - zero_volume: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000) - price_gap: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000)

Iteration History

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['exit_z', 'entry_z', 'lookback', 'min_notional', 'exposure_frac', 'time_stop_bars'] Check that __init__ sets all attributes from self.parameters.get(). - steady_uptrend: TypeError: EthCrossVenuePerpBasisMeanReversionLS4H._ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000) - steady_downtrend: TypeError: EthCrossVenuePerpBasisMeanReversionLS4H._ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000) - flat_ranging: TypeError: EthCrossVenuePerpBasisMeanReversionLS4H._ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000) - volatility_spike: TypeError: EthCrossVenuePerpBasisMeanReversionLS4H._ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000) - zero_volume: TypeError: EthCrossVenuePerpBasisMeanReversionLS4H._ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000) - price_gap: TypeError: EthCrossVenuePerpBasisMeanReversionLS4H._ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000)
Strategy report

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