Skip to content

View translation

BtcDailyBollingerLowerBandBounceLong200Sma

Hypotheses

BTC Daily Bollinger Band Lower-Band Bounce Long-Only with Trend Filter (BINANCE USD-M Futures, Daily, OHLCV-Only)

Hypotheses

A long-only, single-instrument, single-venue, OHLCV-ONLY mean-reversion strategy on BTCUSDT.BINANCE 1D bars. Enter long when close touches or breaks below the lower Bollinger Band (20-period SMA - 2 * 20-period stdev) AND close is above 200-day SMA (uptrend filter). Exit when close reaches the middle band (20-SMA) OR hits stop or time limit. Different from existing RSI oversold (RSI < 30) — Bollinger lower-band uses volatility-adjusted oversold instead of momentum-based. Per factory directive: BTCUSDT.BINANCE 1D bars are always safe. Four parameters total.

Hypotheses

Implements the hypothesis exactly: volatility-adjusted oversold entry via the lower Bollinger Band, gated by a 200-day uptrend filter, exiting on mean-reversion to the middle band. Iteration-3 fix targets ONLY the reported Layer-2 failure: the mean/std helper methods (_mean/_std) triggered a proxy re-binding TypeError ('takes 1 positional argument but 2 were given') under the synthetic-scenario verifier. Those computations are now inlined directly inside calculate_signal, removing every self-called helper so the proxy has nothing to mis-bind. No entry/exit logic, thresholds, imports, or parameters were changed, preserving the Layer-1 pass and the strategy's mean-reversion edge (target = reversion from the 2-sigma band to the 20-SMA, well above round-trip fees).

Hypotheses

Failed every robustness and forward gate on a statistically inadequate sample. Deflated Sharpe=0.0 (vs 0.95) with the optimized Sharpe 4.19 far below the 225-trial expected-max luck bar of 10.19 (is_significant=false), PBO=0.726, walk-forward is_overfitted=true (avg IS 6.27 -> avg OOS -1.005; OOS windows [0.0, 0.0, -3.02], none positive), holdout FAILED (0.0), and sensitivity FAILED with 3 cliffs on the core mechanism parameters (bb_std, bb_period, sma_period). Root cause: the entry (close <= lower Bollinger band AND close > 200-SMA) fires only 22 times in 6.5 years at 8.46% exposure, so the optimizer has no real sample and fits noise — its 'best' config collapses to 5 trades with a 100% win rate and profit_factor 0.0 over 57 days. FAILURE PATTERN: a low-frequency oversold-dip-in-uptrend mean-reversion filter on BTC 1D produces a flattering small-sample base Sharpe (1.58, PF 2.05) that is pure best-of-225 selection noise after deflation — DSR 0.0, uniformly non-positive OOS, zero holdout, and cliffs on all three signal-defining parameters. Not iterable (no tunable region; the signal is too rare to fit), not revisable (BB mean-reversion is not a proven mechanism stranded on a dead target). The PSR=0.9999 / DSR=0.0 split is the diagnostic tell.

Implementation

Long-only, single-instrument, OHLCV-only mean-reversion on BTCUSDT.BINANCE daily bars. Enters long when the close touches or breaks below the lower Bollinger Band (20-SMA minus 2 standard deviations) while the close remains above the 200-day SMA (uptrend filter). Exits when the close reverts to the middle band (20-SMA profit target), an 8% stop-loss triggers, the close breaks below the 200-SMA (trend break), or a 20-bar time stop is hit. Sized to the lesser of 20% of equity notional or a 1.5%-risk / stop-distance budget, no leverage.

Verification Results

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['bb_std', 'risk_pct', 'stop_pct', 'bb_period', 'sma_period', 'min_notional', 'min_stop_pct', 'max_hold_bars', 'per_trade_pct'] Check that __init__ sets all attributes from self.parameters.get(). - steady_uptrend: TypeError: BtcDailyBollingerLowerBandBounceLong200Sma._mean() takes 1 positional argument but 2 were given (bar timestamp: 1735701660000) - steady_downtrend: TypeError: BtcDailyBollingerLowerBandBounceLong200Sma._mean() takes 1 positional argument but 2 were given (bar timestamp: 1735701660000) - flat_ranging: TypeError: BtcDailyBollingerLowerBandBounceLong200Sma._mean() takes 1 positional argument but 2 were given (bar timestamp: 1735701660000) - volatility_spike: TypeError: BtcDailyBollingerLowerBandBounceLong200Sma._mean() takes 1 positional argument but 2 were given (bar timestamp: 1735701660000) - zero_volume: TypeError: BtcDailyBollingerLowerBandBounceLong200Sma._mean() takes 1 positional argument but 2 were given (bar timestamp: 1735701660000) - price_gap: TypeError: BtcDailyBollingerLowerBandBounceLong200Sma._mean() takes 1 positional argument but 2 were given (bar timestamp: 1735701660000)

Backtest Review

Genuine positive edge: expectancy +$434.65/trade, profit_factor 2.05, omega 2.00, Sharpe 1.58, Sortino 2.66

Backtest Review

Trend-ALIGNED, not contrarian: the 200-SMA gate makes this buy-dips-in-uptrend, distinct from the failed pure-reversal class — evidenced by zero trades in the 2022 bear (filter working correctly)

Backtest Review

Trades match the hypothesis exactly: all 22 long, 72.7% win rate, entered on lower-band touches within uptrend

Backtest Review

Low drawdown (5.3%) and clean risk profile; 4 tunable parameters keep the overfitting surface small

Backtest Review

Positive in 4 of 5 traded years (2020/2023/2024/2025), only 2021 slightly negative (-3.3%)

Backtest Review

Thin sample: 22 trades over 6.5 years (~3.4/yr) means the 3-window walk-forward sees ~7 trades/window — overfitting/deflation risk downstream

Backtest Review

sharpe_ci_low -0.85 straddles zero and probabilistic_sharpe 0.92 (<0.95) — significance is marginal before any multiple-testing penalty

Backtest Review

Very low exposure (8.5%) — capital mostly idle; edge is real but small in absolute terms (CAGR 1.8%)

Backtest Review

avg_win ($1167) < avg_loss ($1517) — dependent on maintaining the high 72% hit rate; return_kurtosis 20 shows some fat-tail dependence

Analysis

Clean, minimal implementation (4 core params), correct long-only single-instrument OHLCV design with low impact cost and huge capacity

Analysis

Attractive-looking base headline (Sharpe 1.58, win rate 72.7%, profit factor 2.05) — but on a statistically meaningless sample

Analysis

Failed deflated Sharpe: DSR=0.0 (vs 0.95), is_significant=false, optimized Sharpe 4.19 far below the 225-trial expected-max luck bar of 10.19

Analysis

PBO 0.726 (>0.5): parameter selection more likely than not overfit

Analysis

Walk-forward is_overfitted=true: avg IS 6.27 -> avg OOS -1.005, OOS windows [0.0, 0.0, -3.02] with zero positive windows

Analysis

Holdout FAILED: holdout_sharpe 0.0, ratio 0

Analysis

Sensitivity FAILED with 3 cliffs on the core mechanism params (bb_std, bb_period, sma_period)

Analysis

No statistical base: 22 trades / 8.46% exposure in the base run; optimized config degenerates to 5 trades, 100% win rate, profit_factor 0.0 — the optimizer is fitting noise

Analysis

base sharpe_ci_low -0.85 (CI through 0) even before multiple-testing correction

Analysis

far too few for meaningful optimization

Analysis

Do NOT abandon -- the strategy works as designed and the mechanism (Bollinger lower-band mean-reversion in an uptrend) is sound, but 22 trades over 6.5 years is far too few to optimize: a 3-window walk-forward leaves ~7 trades per OOS window and the optimizer will fit noise. The flashy metrics (Sharpe 1.52, PF 1.99) are a small-sample artifact (tail_ratio 39.9, kurtosis 20.2, sharpe_ci_low -0.91, one regime entirely missing). RAISE TRADE COUNT toward ~60+ over the full period before optimization, by loosening the doubly-restrictive entry: (1) widen the entry band -- bb_std 2.0 -> 1.5 (more frequent touches), or enter when close is within ~0.5% of the lower band rather than strictly <= lower; (2) loosen the trend gate -- the strict 'close > SMA200' halves opportunities and blanked all of 2022; try sma_period 100, or allow entries within a small tolerance (close > SMA200 * 0.97), so the sample spans bear regimes too; (3) keep it long-only and OHLCV-only (premise is fine). Resubmit once total_trades is comfortably above the ~62 walk-forward floor with a still-coherent mean-reversion logic. If after densification the per-trade edge collapses (avg_trade_return thin, PF drifts toward 1.0), that will be the signal to abandon -- but give it this one density pass first.

Outcome Summary

This strategy translated a classic Bollinger lower-band bounce into a long-only, trend-filtered dip-buyer on BTCUSDT daily futures, and its first backtest was appealing: a 72.7% win rate, profit factor 2.05, Sharpe 1.58, and a low 5.3% drawdown earned an 'optimize' verdict at the review gate. But the edge rested on only 22 trades over 6.5 years at 8.5% exposure, and the 3-phase optimization dismantled it — deflated Sharpe 0.0, PBO 0.726, an overfit walk-forward that went from 6.27 in-sample to −1.005 out-of-sample, a failed holdout, and cliffs on all three signal-defining parameters. The analyst abandoned it after three iterations (the earlier ones fixing a Layer-2 verification error), concluding the signal was simply too rare to fit and not iterable. The PSR 0.9999 / DSR 0.0 split was called out as the diagnostic tell that the base result was pure selection noise.

Outcome Summary

A flattering small-sample base Sharpe (here from just 22 trades at 8.5% exposure) is a warning sign, not an edge — a signal that fires too rarely gives the optimizer no real sample to fit, so an attractive PSR paired with a deflated Sharpe of 0.0 exposes the result as best-of-225 selection noise.

Outcome Summary

The analyst issued an 'abandon' verdict after optimization because the strategy failed every robustness and forward gate: deflated Sharpe 0.0 (vs 0.95), PBO 0.726, walk-forward flagged overfit (IS 6.27 → OOS −1.005 with no positive windows), holdout failed (0.0), and sensitivity showed 3 cliffs on the core signal parameters (bb_std, bb_period, sma_period).

Outcome Summary

A long-only BTCUSDT daily futures mean-reversion strategy that bought when price touched or broke below the lower Bollinger Band (20-SMA − 2σ) while still above the 200-day SMA, exiting at the middle band, a stop, a trend break, or a time limit — a volatility-adjusted buy-the-dip-in-uptrend edge.

Outcome Summary

The base backtest looked strong — 22 long trades, 72.7% win rate, expectancy +$434.65/trade, profit factor 2.05, Sharpe 1.58, and only 5.3% max drawdown — but exposure was just 8.5% (CAGR 1.8%) and the sample was thin; under optimization it collapsed, with the 'best' config degenerating to 5 trades and average out-of-sample Sharpe of −1.005.
Strategy report

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