Skip to content

View translation

AdaRsi2RangingReversionLS2h

Hypotheses

ADA USD-M RSI-2 Short-Term Reversion, Long-Short (Single-Instrument BINANCE Perp, 2h Bars, Fade RSI(2) Oversold/Overbought Extremes Back Toward the Mean ONLY in Ranging Regimes — High Trade Count by Design, Trend-Gated, ATR-Stopped, 3-Parameter)

Hypotheses

A LONG-SHORT, single-instrument short-term mean-reversion on ADAUSDT.BINANCE (USD-M perp, 2h bars) using the documented Connors RSI-2 mechanism — a DIFFERENT, well-established reversion signal from the VWAP-z-score (pending SOL 15m), Asian-session (pending DOGE 30m), and Keltner-overshoot (pending LINK 4h) strategies, on a fresh instrument. Mechanism: compute a fast RSI(2); when it is deeply oversold (< low_thresh, default 10) go LONG, when deeply overbought (> high_thresh, default 90) go SHORT, betting on snap-back toward a short EMA. It is engineered against this session's binding failure modes: (1) TRADE COUNT — the RSI thresholds are set intentionally loose (10/90, not the classic 5/95) so the strategy fires ≳50 times/year, directly answering the two deaths that killed the smart-money-divergence (16 trades/yr) and spot-200SMA (0 trades) siblings at the sandbox measurability floor; (2) FEE VIABILITY — on a high-volatility major at 2h, an RSI(2) extreme reversion captures ~0.6–1.5% moves, multiples of the ~0.10% USD-M round-trip, unlike the fee-dead 15m/1h fades (taker-flow −0.025%); (3) REGIME — a TREND GATE (only fade when a slow EMA-slope filter is flat/ranging) removes the trending regime where RSI fades bleed, the discipline the un-gated AVAX/BNB/XRP fades lacked. It is NOT a basket (single-instrument, 2 fills/round-trip → sidesteps the L12 fee wall), NOT options (no trade-count wall, L23), NOT carry/funding-signal (L13 exhausted), NOT trend (regime-distributed reversion), NOT daily-low-frequency (2h fires often → clears the sandbox trade-count wall), and NOT a rotation duplicate (L24). Pure OHLCV on a deep-history major → no data wall. 3 low parameters (RSI thresholds as one pair, EMA/exit lookback, trend-gate lookback) resist overfit.

Hypotheses

Iteration 7 targets the exact incoherence the gate flagged: a positive mark-to-market Sharpe (0.64) against a -59.29% realized equity curve. That divergence is the fingerprint of asymmetric REALIZED exits — unrealized excursions were fine, but iteration 6's snap-back exit was profit-gated at only 0.4%, so RSI(2) (which recrosses its midline after one counter-bar) cashed virtually every winner at ~+0.4% gross while every loser ran the full 2.2% bracket stop, a ~7:1 loss/win ratio that needs an ~88% win rate to break even. Three coupled edits fix the payoff geometry rather than re-tuning the signal: (1) the bracket is now positive R:R, 3.0% take-profit against a 2.0% stop; (2) min_exit_profit_pct is raised to 1.2% so the discretionary snap-back exit is a real take-profit and can no longer truncate a winner below a loser's stop distance; (3) max_hold_hours goes to 48h (24 bars) so the wider take-profit is reachable before the timeout flattens the trade. Fee drag is cut at the same time by requiring a full 1.0-ATR stretch from the mean at entry (marginal half-ATR fills had nothing to revert to and were pure commission) and trimming risk_per_trade to 0.6% so the risk formula rather than the notional cap sets size. Entry logic, the ranging gate, the continuous 50-RSI(2) signal, imports and class structure are untouched — Layers 1-3 already passed on them. One honest note: this is the last structural asymmetry I can name in the payoff; if the realized equity curve is still negative with a positive-R:R bracket and a 1-ATR stretch filter, the RSI(2) fade on ADA 2h has no edge left to recover and should be abandoned rather than tuned further.

Hypotheses

backtest_no_trades: metrics unreliable: Incoherent: Sharpe 0.26 disagrees in sign with total_return -59.50% — the Sharpe is computed from the mtm_equity_curve series while the return comes from the equity curve. Judge on the equity curve.

Implementation

Long-short RSI(2) mean-reversion fade on ADAUSDT USD-M perp (2h bars). Goes LONG when RSI(2) < 6 and price is at least 1 ATR BELOW a 50-period EMA, SHORT when RSI(2) > 94 and price is at least 1 ATR ABOVE it, and only while the EMA is flat (|EMA drift over 12 bars| / ATR < 0.6) so the fade is not fighting a trend. Exits are venue-managed brackets (2.0% stop / 3.0% take-profit, OUO-linked, filling intra-bar), plus a 48h max-hold timeout and an RSI(2)-snap-back take-profit that can only fire once the trade is already up 1.2%. Sizing risks 0.6% of equity against the real 2.0% stop distance, capped at 35% of equity notional, no leverage.

Verification Results

If the intent is a longer warm-up, keep the override; otherwise rename to avoid shadowing. No action required for correctness.

Verification Results

min_bars_required() overrides a framework method (static analyzer base_shadow warning). This appears deliberate (the strategy needs slow_ema_period + slope_lookback + buffers of history before signalling), and the base template's dispatch respects the override, so it is functionally correct — but confirm the base uses the overridden value for its warm-up gate rather than its own default.

Verification Results

Consider whether the snap-back exit should be removed or its floor raised toward the bracket TP so the intended 1.5:1 R:R is actually realized; leave the analyst to judge on full-history results.

Verification Results

The discretionary RSI-snap-back take-profit in should_exit() (fires once pnl >= min_exit_profit_pct = 1.2%) coexists with the venue bracket's 3.0% take-profit. It is signal-based (not a duplicated fixed price level, so not a double-exit bug), but it can still realize winners between 1.2% and 3.0%, capping the upside the positive-R:R bracket was designed to capture. This is a design/edge concern, not a defect.

Verification Results

Iteration 7's sandbox is a fee-bleed loss, not a code defect: total_return -29.3%, PF 0.855, Sharpe -0.14, avg_trade_return_pct 0.0077% (near ZERO, far below the ~0.15% USD-M fee floor), commission 10.6% of gross over 689 trades. The developer's own payoff-asymmetry fix did not close the gap: avg_win 495.7 vs avg_loss 594.8 (loss > win) with win_rate only 0.507, so the RSI(2) fade still cashes winners small and lets losers run to the wider stop. The discretionary RSI snap-back exit (gated at min 1.2% profit) can still truncate winners below the 3.0% bracket TP, keeping avg_win depressed relative to the 2.0% stop. Regime attribution shows edge only in the 'calm' tercile (+0.02, Sharpe 0.17); 'normal' -18.1% and 'stressed' -27.8% are firmly negative, and the strategy loses across most stress windows. The developer flagged this as the last nameable structural fix. Analyst should treat a full-history backtest as the decider and weigh abandonment if realized expectancy stays sub-floor — the mechanism (single-name RSI-2 fade, PF<1.15) matches the negative-expectancy pattern that has not survived to promotion.

Analysis

Backtest gate: - metrics unreliable: Incoherent: Sharpe 0.64 disagrees in sign with total_return -59.29% — the Sharpe is computed from the mtm_equity_curve series while the return comes from the equity curve. Judge on the equity curve.

Iteration History

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['exit_rsi', 'atr_period', 'low_thresh', 'rsi_period', 'high_thresh', 'min_notional', 'atr_stop_mult', 'gate_lookback', 'max_hold_hours', 'risk_per_trade', 'slow_ema_period', 'max_notional_frac', 'max_trend_slope_pct'] Check that __init__ sets all attributes from self.parameters.get(). - steady_uptrend: TypeError: AdaRsi2RangingReversionLS2h._ema() takes 2 positional arguments but 3 were given (bar timestamp: 1735692240000) - steady_downtrend: TypeError: AdaRsi2RangingReversionLS2h._ema() takes 2 positional arguments but 3 were given (bar timestamp: 1735692240000) - flat_ranging: TypeError: AdaRsi2RangingReversionLS2h._ema() takes 2 positional arguments but 3 were given (bar timestamp: 1735692240000) - volatility_spike: TypeError: AdaRsi2RangingReversionLS2h._ema() takes 2 positional arguments but 3 were given (bar timestamp: 1735692240000) - zero_volume: TypeError: AdaRsi2RangingReversionLS2h._ema() takes 2 positional arguments but 3 were given (bar timestamp: 1735692240000) - price_gap: TypeError: AdaRsi2RangingReversionLS2h._ema() takes 2 positional arguments but 3 were given (bar timestamp: 1735692240000)

Iteration History

Verification failed (Layer 4 — QA review): - Measurably negative edge with catastrophic loss profile. On 447 trades (metrics_reliable=true): total_return -50.28%, profit_factor 0.713, avg_trade_return_pct -0.058% (below the 0.15% futures floor and negative), max_drawdown 57.48%. Despite a 61.7% win rate the reward/risk is badly inverted -- avg_loss $1,025 is ~2.3x avg_win $453 -- the classic RSI-fade failure where occasional trend-continuation losses dwarf the many small reversion wins. The ranging EMA-slope gate did not prevent this. This is the L7 'RSI-oversold-with-trend-filter' mechanism class, which has zero survivors across the record; pure-OHLCV RSI reversion on a fresh instrument does not change that. (Note: the Sharpe 0.40 headline contradicts the -50% return / PF 0.71 and is a lumpy per-bar artifact, not a real positive edge.) - Risk-control failure: realized per-trade loss far exceeds the sizing budget. position_size targets risk_per_trade=2% via size = risk_budget/(atr_stop_mult*ATR), so a stop-out should cost ~2% of equity (~$2k). The sandbox shows largest_loss -$11,114 (~11% of equity, ~5.5x the budget) and max_drawdown 57.5%. Root cause: the ATR stop is evaluated ONLY on bar close in should_exit via get_position_pnl_pct, so on a 2h bar an adverse intrabar move runs well past the stop level before the market exit fires -- the stop does not contain the loss it is sized around. A strategy nominally risking 2%/trade that takes 11% single-trade hits and a 57% drawdown has an unsafe risk model (L15). - Extreme turnover and impact: turnover 305 over 336 days with total_impact_usd $17,917 on ~$100k -- a fade at this frequency (447 trades) is very cost-sensitive, and even a small genuine edge would be eroded by fees + impact. This compounds the negative-edge finding.

Iteration History

Verification failed (Layer 4 — QA review): - Still no net edge on a measurable sample after the pivot. On 119 trades (metrics_reliable=true): total_return -11.56%, profit_factor 0.675, avg_trade_return_pct -0.050% (negative, below the 0.15% futures floor and the ~0.10% round-trip), win_rate 0.563 with a still-inverted reward/risk (avg_loss $685 ~= 1.9x avg_win $359). The mechanism has now been tried in BOTH orientations and lost both: counter-trend ranging fade (iter-1/2, down to -50%) and trend-aligned pullback (iter-3, -11.6%). RSI(2) on ADA 2h has no fee-clearing edge in either direction. - The code no longer implements the stated hypothesis, and the new form is the L7 zero-survivor class. The hypothesis specifies a COUNTER-TREND fade gated to RANGING regimes ('Fade RSI(2) Oversold/Overbought Extremes ... ONLY in Ranging Regimes ... only fade when a slow trend filter is flat/ranging'). Iter-3 REMOVED the ranging gate and replaced it with a trend-DIRECTION gate: buy oversold only when price > slow EMA (uptrend), short overbought only when price < slow EMA (downtrend). That is a trend-aligned pullback, not the hypothesis's ranging fade -- and it is now literally 'RSI-oversold-with-trend-filter', the exact mechanism class L7 names as having zero survivors. So the pivot both diverges from the hypothesis it is filed under and lands in a known-dead class. - Turnover/impact remains high (turnover 67, total_impact_usd $3,839 on ~$100k) for a strategy with no net edge, and the direction split is regime-skewed (76 short vs 43 long over a down-window), so the result partly reflects ADA's directional drift rather than a symmetric reversion edge.

Iteration History

Verification failed (Layer 4 — QA review) [class=hypothesis_mismatch]: - [edge_concern] Even setting the mismatch aside, the sandbox is fee-marginal-to-negative: avg_trade_return_pct 0.134% is below the 0.15% futures viability floor, PF 0.86, total_return -20.6% over 531 trades, and avg_loss (764) is ~2x avg_win (379). Trade count (~185/yr projected, 531 in sandbox) is healthy, so the strategy is measurable — but the RSI(2) snap-back edge does not clear costs as configured. The analyst should verify per-trade edge vs the ~0.10% round-trip after the gate is corrected, since changing the regime gate materially changes which trades are taken. - [critical] The hypothesis's single defining, repeatedly-stated core mechanic is a COUNTER-TREND fade restricted to RANGING regimes: the title says 'Fade RSI(2) Oversold/Overbought Extremes Back Toward the Mean ONLY in Ranging Regimes', and the description frames the regime gate as 'only fade when a slow EMA-slope filter is flat/ranging' to 'remove the trending regime where RSI fades bleed' — explicitly the discipline the un-gated AVAX/BNB/XRP siblings lacked. The code implements the OPPOSITE gate: should_enter takes uptrend = self._price > self._slow_ema and then buys oversold ONLY in an uptrend and shorts overbought ONLY in a downtrend (a trend-ALIGNED pullback). The docstring openly states this 'replaces the earlier counter-trend ranging fade'. Consequences: (a) the strategy never trades in the ranging regime the hypothesis targets and instead trades within trends, which is a materially different edge/trade set; (b) the gate uses EMA LEVEL (price vs EMA), not the EMA-SLOPE flat/ranging filter the hypothesis names. The specific core mechanic named by the hypothesis is not implemented; a different, coherent strategy is. Per the checklist this is a critical hypothesis mismatch. (line 150) — fix: Either (a) implement the hypothesis as written: compute an EMA-slope / range filter and enter the RSI(2) fade (buy oversold, sell overbought) ONLY when the slope is flat/ranging, independent of trend direction; or (b) if the trend-aligned pullback is genuinely the intended strategy after prior iterations, update the hypothesis text (title, description, name 'RangingReversion') so the stated mechanism matches the code. Do not ship code whose gate contradicts the hypothesis's headline mechanic. - [warning] RSI thresholds are 10/90 as the hypothesis states, and the mechanism is pure OHLCV with point-in-time-safe data (no supplementary reads, so no look-ahead). Sizing is capital-relative via get_account_equity() with a 1% ATR-risk budget and a 0.5x notional cap — no hardcoded lot. Subscription flags are consistent (only on_bar used). API usage (positions_open, avg_px_open, ts_opened) is correct. These are fine; noting only that avg_trade_return_pct 0.134% sits under the 0.15% futures floor — advisory, carried in edge_concern. (line 39) — fix: No code change required for this item; performance is judged downstream.

Iteration History

Backtest gate: - metrics unreliable: Incoherent: Sharpe 0.26 disagrees in sign with total_return -59.50% — the Sharpe is computed from the mtm_equity_curve series while the return comes from the equity curve. Judge on the equity curve.
Strategy report

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