Skip to content

View original

EthDailyConsecutiveDownDayPullbackLongBullRegime

Hypotheses

ETH Daily Consecutive-Down-Day Pullback Long with 200-SMA Bull Regime Filter

Hypotheses

A long-only single-instrument SHORT-TERM MEAN-REVERSION strategy on ETHUSDT perpetual futures using daily bars and OHLCV-only data, with a 200-SMA bull regime filter. The trigger is STRUCTURALLY NOVEL within the portfolio: it counts CONSECUTIVE DOWN DAYS (a discrete-event count, not a continuous statistic), making it mechanistically orthogonal to every existing strategy. Existing mean-reversion strategies trigger on continuous-statistic extremes: SolFourHourBbOversoldMeanReversionLong on std-dev distance, BnbFourHourRsi2OversoldMeanReversionLong on Wilder-smoothed velocity, BtcFourHourVwapDistanceMeanReversionLong on volume-weighted distance, and the Drawdown Accumulation strategies on % from N-day high. None use a discrete-count event mechanism. The N-down-days-in-a-row pattern was extensively documented by Larry Connors (Short-Term Trading Strategies That Work, 2008) and has remained a robust short-term mean-reversion trigger across asset classes for ~17 years. It captures a different microstructure regime than oscillator extremes: persistent multi-day selling pressure that exhausts as systematic sellers complete their flow, rather than sharp single-bar capitulation (RSI(2)) or position-relative-to-mean (BB). Daily timeframe is chosen because (a) ETH daily futures data path is empirically reliable (proven by EthDailyGoldenCrossMomentumLong already in pipeline), (b) ETH 4H has consistently failed Layer 3 infrastructure (4 iterations), (c) consecutive-down-day patterns are statistically meaningful only at daily resolution — at 4H they become noise. ETH is chosen specifically because (a) ETH is the most underutilized asset in the portfolio (only 1 strategy despite reliable data path), (b) ETH has well-documented short-term pullback-then-resume dynamics in bull regimes (institutional mean-reversion flows are heaviest on ETH due to its derivatives/staking ecosystem), (c) the existing EthDailyGoldenCrossMomentumLong fires on RARE long-term regime events while this fires on FREQUENT short-term pullbacks — truly orthogonal signal timing on the same asset. Only 4 parameters (down-day count threshold, regime SMA period, exit lookback, stop-loss pct), all economically meaningful and stable.

Hypotheses

Implements the Connors N-down-days-in-a-row pullback trigger on ETH daily bars with a 200-SMA regime gate, exactly as specified. Iteration 4 addresses the ONLY reported failure — the Layer 3 300s wall-clock timeout — by replacing the O(n)-per-bar full-buffer rescan (`_clean_series`, which rebuilt a dict and two lists from the entire ~4.7k-bar history every bar, giving O(n^2)) with an incremental O(1)-per-bar dedup buffer that maintains the same keep-last-value-per-timestamp semantics and is memory-bounded to regime_sma + slack. All produced values (closes, highs, SMA, consecutive-down count, exit-high) are identical to the prior version on both clean and duplicate-timestamp data, so the trade-generating entry/exit logic that already passed Layers 1 and 2 (and produced trades in earlier iterations) is fully preserved. No banned imports were added; imports and class structure are unchanged.

Hypotheses

Failed deflated Sharpe and every forward gate on optimization attempt 1. DSR=0.0017 (vs 0.95) with the optimized Sharpe 0.442 FAR below the 225-trial expected-max luck bar of 5.5377 (is_significant=false, sharpe_ci_low=-2.866 straddling 0, PBO=0.6918 >0.5) — after multiple-testing correction the selected best-of-225 config is statistically indistinguishable from best-of-N noise; probabilistic_sharpe 0.60 vs DSR 0.0017 is the textbook PSR-vs-DSR selection-inflation trap. The walk-forward is is_overfitted=TRUE: avg IS Sharpe 3.499 collapses to avg OOS 0.383 with OOS windows [1.15, 0.0, 0.0] — two of three OOS windows produce NO trades. Decisively, the untouched time-ordered HOLDOUT FAILED and is ZERO (holdout_sharpe 0.0, ratio 0.0). Sensitivity FAILED with 2 cliff parameters (regime_sma, down_day_count): down_day_count 3->4 flips Sharpe 1.64->-0.68 and regime_sma 200->240 goes negative. The optimized full-sample refit is flat (total_return 2.4%, Sharpe 0.44, PF 1.12, negative 2022 -3.5% and 2025 -1.8% years, only 18 trades). Not iterate: the base 43-trade sample is too thin to survive per-window walk-forward (empty OOS windows) and best-of-225 selection, the binding failures are structural (zero holdout, below-luck-bar Sharpe, PBO 0.69, 2 cliffs), and a second sweep re-overfits noise. Not revise_hypothesis: ETH daily is a valid, data-rich target and this is overfitting to noise on a fine instrument, not a proven mechanism stranded on a dead one. FAILURE PATTERN: a Connors-style consecutive-down-day pullback long on single-asset ETH daily produces an attractive but thin-sample base backtest (Sharpe 1.64 on 43 trades) that does NOT survive optimization — the low daily trade frequency leaves two of three walk-forward OOS windows empty (is_overfitted, IS 3.50 -> OOS 0.38), the holdout goes to zero, the best-of-225 Sharpe (0.44) cannot clear a 5.54 luck bar (DSR 0.0017, PBO 0.69), and the parameter surface has 2 cliffs. A promotable-looking base Sharpe and a clean pre-optimization review measure consistency, not significance or forward-generalization.

Implementation

Long-only ETHUSDT daily perpetual-futures mean-reversion. Counts CONSECUTIVE DOWN DAYS (discrete-event trigger); on a streak >= down_day_count while price is above a 200-SMA bull-regime filter, buys the exhausted multi-day pullback. Exits on momentum resume (close above the prior exit_lookback-bar high), regime break (close below SMA), or an 8% hard stop. OHLCV-only, leverage 1.0, capital-relative risk sizing.

Verification Results

Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit. This almost always means per-bar work that scales with history — e.g. rescanning the full funding/supplementary series, or rebuilding a list and calling min()/sorted() inside calculate_signal()/on_bar() on every bar. Precompute sorted timestamp arrays ONCE in __init__ and use bisect, or cache lookups keyed by timestamp, so per-bar cost is O(log n) not O(n).

Backtest Review

43 long trades over 2021–2025, well-distributed across years (2021 +11.4%, 2024 +6.3%, 2025 +9.7%; only 2023 negative at -2.7%) — not a single-window artifact

Backtest Review

Trades match the hypothesis: long-only (0 shorts), enters after multi-day pullbacks in a bull regime, ~4.5-day holds — mechanism is correctly implemented

Backtest Review

Healthy, fee-viable metrics: Sharpe 1.64, Sortino 2.44, profit_factor 1.89, win_rate 74%, max_drawdown 8.08%, expectancy +$620/trade, commission only 2.17% of gross

Backtest Review

Low exposure (11.5%) with positive alpha (0.0215) and near-zero beta — a genuine timing overlay, orthogonal to buy-hold

Backtest Review

Trade sample (43) is on the lower side — optimizer must guard against overfitting/cliff on down_day_count and exit_lookback

Backtest Review

High tail_ratio (61.8) and kurtosis (22) indicate a few outlier days carry part of the edge — verify robustness in walk-forward

Backtest Review

Negative information_ratio (-0.72) vs ETH buy-hold, though expected for a low-exposure pullback timer and not the right benchmark for this strategy type

Analysis

Base backtest looked promotable (Sharpe 1.64, PF 1.89, 43 well-distributed trades) and the mechanism is correctly implemented (long-only, discrete down-day count, genuine 200-SMA regime gate)

Analysis

Low beta (0.01) and positive base alpha (0.0215) — a genuine low-exposure timing overlay, not a closet long

Analysis

Failed deflated Sharpe: DSR=0.0017 vs 0.95, is_significant=false, PBO=0.6918, sharpe_ci_low=-2.866; optimized Sharpe 0.442 far below the 225-trial expected-max luck bar of 5.538

Analysis

Walk-forward is_overfitted=TRUE: avg IS 3.499 collapses to avg OOS 0.383 with OOS windows [1.15, 0.0, 0.0] — two of three OOS windows produce zero trades

Analysis

Holdout FAILED and is zero (holdout_sharpe 0.0, ratio 0.0) — no forward edge on untouched data

Analysis

Sensitivity FAILED with 2 cliff parameters (regime_sma, down_day_count): down_day_count 3->4 flips Sharpe to -0.68, regime_sma 200->240 goes negative

Analysis

Optimized full-sample refit is flat: total_return 2.4%, Sharpe 0.44, PF 1.12, with negative 2022 (-3.5%) and 2025 (-1.8%) years on only 18 trades

Analysis

43-trade base sample is too thin to survive per-window walk-forward and multiple-testing correction

Outcome Summary

This was a structurally novel entry for the portfolio — a Connors-style consecutive-down-day count (a discrete event, unlike the book's oscillator/std-dev mean-reversion siblings) on the under-utilized ETH daily path, deliberately re-targeted away from ETH 4H after four prior infrastructure failures there. After several iterations fixing verification issues (duplicate-timestamp dedup, a Layer-2 staticmethod TypeError, and an O(n²) dedup that blew the 300s wall-clock), its base backtest passed review with a promising Sharpe 1.64 across 43 trades. But optimization exposed it as overfit to a thin sample: the best-of-225 config's Sharpe of 0.44 couldn't clear a 5.54 luck bar (DSR 0.0017, PBO 0.69), two of three walk-forward OOS windows had no trades, the holdout was zero, and the surface had two cliffs. The analyst abandoned it on the first optimization attempt as a structural no-significance/overfit failure rather than iterate on noise; it never reached risk review, paper, or live.

Outcome Summary

A low-frequency daily trigger that yields only ~43 base trades is too thin to survive per-window walk-forward and best-of-N selection — the trade count leaves OOS windows empty and the holdout at zero — so an attractive base Sharpe on a clean pre-optimization review measures consistency, not significance or forward-generalization.

Outcome Summary

It cleared backtest review ('optimize') on the strong base numbers, but the post-optimization analyst voted 'abandon' on the first optimization attempt after it failed every forward gate: deflated Sharpe 0.0017 with the optimized Sharpe 0.442 far below the 225-trial expected-max luck bar of 5.538, PBO 0.6918, is_overfitted=true, a zero holdout (ratio 0.0), and 2 sensitivity cliffs (down_day_count 3→4 flips Sharpe to -0.68, regime_sma 200→240 goes negative).

Outcome Summary

A long-only, single-instrument short-term mean-reversion strategy on ETHUSDT daily futures that uses a Connors-style discrete-event trigger — buy after N consecutive down days — but only when price is above its 200-day SMA (bull regime filter), exiting on momentum resume, regime break, or a hard stop.

Outcome Summary

The base backtest looked promotable — Sharpe 1.64, Sortino 2.44, profit factor 1.89, 74% win rate, 8.08% max drawdown over 43 well-distributed long trades with positive alpha (0.0215) and near-zero beta — but optimization collapsed: the optimized full-sample refit was flat (Sharpe 0.44, total_return 2.4%, PF 1.12, 18 trades), the walk-forward was overfit (avg IS 3.50 → avg OOS 0.38 with two of three OOS windows producing zero trades), and the holdout went to zero.

Iteration History

Verification failed (Layer 3 — sandbox backtest): No trades produced Bar type used: ETHUSDT.BINANCE-1-DAY-LAST-EXTERNAL, Bars processed: 4712 Diagnostics: should_enter() returned a side 0 times over 2267 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: ['risk_pct', 'regime_sma', 'min_notional', 'exit_lookback', 'stop_loss_pct', 'down_day_count', 'size_precision', 'max_notional_frac'] Check that __init__ sets all attributes from self.parameters.get(). - steady_uptrend: TypeError: EthDailyConsecutiveDownDayPullbackLongBullRegime._bar_ts_of() takes 1 positional argument but 2 were given (bar timestamp: 1735701720000) - steady_downtrend: TypeError: EthDailyConsecutiveDownDayPullbackLongBullRegime._bar_ts_of() takes 1 positional argument but 2 were given (bar timestamp: 1735701720000) - flat_ranging: TypeError: EthDailyConsecutiveDownDayPullbackLongBullRegime._bar_ts_of() takes 1 positional argument but 2 were given (bar timestamp: 1735701720000) - volatility_spike: TypeError: EthDailyConsecutiveDownDayPullbackLongBullRegime._bar_ts_of() takes 1 positional argument but 2 were given (bar timestamp: 1735701720000) - zero_volume: TypeError: EthDailyConsecutiveDownDayPullbackLongBullRegime._bar_ts_of() takes 1 positional argument but 2 were given (bar timestamp: 1735701720000) - price_gap: TypeError: EthDailyConsecutiveDownDayPullbackLongBullRegime._bar_ts_of() takes 1 positional argument but 2 were given (bar timestamp: 1735701720000)
Strategy report

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