The second strategy that survived walk-forward testing out of 14 candidates. A mean-reversion scalper for ES futures that fades pre-market extremes — when price overextends past the ATR channel, the bot fades it back to the EMA midline. Clean, logical, no guesswork.
Free · No sign-up · NinjaTrader 8 · ES / MES futures · Pre-market session
Backtest results — ES Futures · 2022–2024 · 287 trades
Equity curve — cumulative P&L
How the strategy works
Parameters — 4 total (walk-forward compliant)
| Parameter | Default | Range | Description |
|---|---|---|---|
| EMAPeriod | 20 | 5 – 50 | Midline EMA. Price reverts toward this after channel extremes. 20-period is the most robust. |
| ChannelMultiple | 1.8 | 0.5 – 5.0 | Bands = EMA ± (ATR × 1.8). Higher = fewer but more extreme signals. Strategy passed walk-forward at 1.6–2.2. |
| StopATRMultiple | 0.8 | 0.3 – 3.0 | Stop placed ATR × 0.8 beyond the band entry. Tight stop, high win rate is the tradeoff. |
| ATRPeriod | 14 | 7 – 30 | Volatility lookback for both band width and stop size. 14 is the most parameter-insensitive value. |
Full source code
// ============================================================ // NSQ_ATRChannelScalper.cs · nightshiftquant.com // Mean-reversion scalper · ES Futures · Pre-market 04:00–09:15 ET // 4 parameters · Walk-forward tested · 62.3% win rate // ============================================================ namespace NinjaTrader.NinjaScript.Strategies { public class NSQ_ATRChannelScalper : Strategy { // ── State ────────────────────────────────────────────────── private bool longFired; private bool shortFired; private DateTime sessionDate; // ── Indicators ───────────────────────────────────────────── private EMA ema; private ATR atr; // ── Time Gates ───────────────────────────────────────────── private const int T_SESSION_START = 40000; // 04:00 ET private const int T_SESSION_END = 91500; // 09:15 ET protected override void OnStateChange() { if (State == State.SetDefaults) { Name = "NSQ_ATRChannelScalper"; Calculate = Calculate.OnBarClose; EntriesPerDirection = 1; // ── 4 Parameters Only ── EMAPeriod = 20; ChannelMultiple = 1.8; StopATRMultiple = 0.8; ATRPeriod = 14; } else if (State == State.Configure) { ema = EMA(EMAPeriod); atr = ATR(ATRPeriod); } } protected override void OnBarUpdate() { if (CurrentBar < BarsRequiredToTrade) return; int barTime = ToTime(Time[0]); DateTime barDate = Time[0].Date; // Reset daily if (barDate != sessionDate) { ResetSession(); sessionDate = barDate; } // Hard exit 09:15 ET — no NY open carry if (barTime >= T_SESSION_END) { if (Position.MarketPosition == MarketPosition.Long) ExitLong("TimeExit", "NSQ_ATR_Long"); else if (Position.MarketPosition == MarketPosition.Short) ExitShort("TimeExit", "NSQ_ATR_Short"); return; } // Only trade pre-market window if (barTime < T_SESSION_START) return; // Build channel double midline = ema[0]; double atrValue = atr[0]; double upperBand = midline + (atrValue * ChannelMultiple); double lowerBand = midline - (atrValue * ChannelMultiple); if (Position.MarketPosition == MarketPosition.Flat) { int stopTicks = (int)Math.Round(atrValue * StopATRMultiple / TickSize); // LONG: price tags lower band → fade down, target midline if (!longFired && Low[0] <= lowerBand) { SetStopLoss(CalculationMode.Ticks, stopTicks); SetProfitTarget(CalculationMode.Price, midline); EnterLong("NSQ_ATR_Long"); longFired = true; } // SHORT: price tags upper band → fade up, target midline else if (!shortFired && High[0] >= upperBand) { SetStopLoss(CalculationMode.Ticks, stopTicks); SetProfitTarget(CalculationMode.Price, midline); EnterShort("NSQ_ATR_Short"); shortFired = true; } } } private void ResetSession() { longFired = shortFired = false; sessionDate = DateTime.MinValue; } } }
Download, compile, and run on MES (Micro ES) first. The pre-market session requires overnight data — use the 24H session template.
NSQ_ATRChannelScalper.cs → copy to Documents\NinjaTrader 8\bin\Custom\Strategies\F5 to compileCME US Index Futures ETHTrade it with funded capital
My personal prop firm. No daily drawdown rules, instant payouts, and the ES contracts you need to run this scalper at full size without risking your own capital.
Get funded at Bulenox →One-step evaluation, no monthly fees, and competitive scaling plans. Works well for mean-reversion bots with consistent win rates like this one.
Get funded at TradeDay →