DARKPOOL ALGO
Guides/Enhanced ORB Strategy
Free Optimization Guide

Enhanced ORB Strategy Optimization Guide

Exact Start / Step / End values for the NinjaTrader 8 Strategy Analyzer (Optimize tab), the order to optimize them in, and how to avoid curve-fitting.

HOW THE SYSTEM WORKS

  • Builds an Opening Range from OrStartTime to OrEndTime, marking the high and low of that window.
  • Trades a separate, independently configurable window from TradeStartTime to TradeEndTime. No trade can occur until the OR period has closed AND the trade window is open.
  • Entries fire on a closed-bar cross: long on CrossAbove(Close, OR High), short on CrossBelow(Close, OR Low). The signal is evaluated against the bar's close, not an intrabar wick.
  • Two optional entry filters (minimum breakout size, volume vs. 20-period average) sit in front of every signal.
  • Two independent stop-loss modes (fixed-tick, OR-level) plus a profit target, breakeven, and trailing stop handle exits.

This strategy is fully deterministic: pure price/volume/time logic, no machine learning, no trained model, and no randomness anywhere in the code. The same settings on the same data produce the identical result every single run. A single backtest is trustworthy as-is - there is no reproducibility check to perform and no non-determinism warning needed anywhere in this guide.

UNITS: TICKS

All *Ticks inputs (StopLossTicks, TargetTicks, etc.) are in ticks, the instrument's own minimum price increment (e.g. 0.25 on ES = 1 tick). NinjaTrader has no 4-digit/5-digit broker ambiguity - a tick is a tick for the instrument you're testing. Just confirm your chart's instrument and TickSize before typing the ranges below; scale them up for wider-ranging instruments (e.g. NQ, CL) and down for tighter ones.

STRATEGY ANALYZER SETUP

  • Use real historical tick or minute data for the instrument/session you intend to trade. Garbage data = garbage results.
  • Period: 1-2+ years of the instrument's regular session. Hold back the most recent ~25-30% for out-of-sample validation, or use the Strategy Analyzer's Walk-Forward Optimization feature to automate the split.
  • Optimizer: NinjaTrader 8 Strategy Analyzer, Optimize tab. Use the Genetic optimization method once a table's grid gets large; use Exhaustive/Brute Force for small grids (e.g. a single bool).
  • Fitness/sort: Profit Factor or a custom criterion that weighs drawdown - don't sort by Net Profit alone (see READING RESULTS).
  • Bools optimize as Start 0, Step 1, End 1 (tests both false/off and true/on).

TIME PARAMETERS (set/test manually, do NOT numeric grid-sweep)

OrStartTime / OrEndTime : the Opening Range window TradeStartTime / TradeEndTime : the trade window (must start at or after OrEndTime)

These are DateTime/time-of-day properties, not plain integers - the Strategy Analyzer's Optimize tab does not sweep DateTime inputs in a useful way. Instead, test a handful of sensible combinations by hand, e.g. a 15/30/45-minute OR window measured from the session open, with the trade window starting exactly at OrEndTime and running to your session's usual close. Compare a few full runs and lock the winner before touching anything else.

OPTIMIZATION TABLES (Start / Step / End)

GROUP A: CORE - OR WINDOW + TRADE WINDOW (set first, manually)

Input Default Note
OrStartTime 09:30 session open; test manually, not a sweep
OrEndTime 10:00 try OR windows of 15 / 30 / 45 min from open
TradeStartTime 10:00 keep equal to OrEndTime unless testing a delay
TradeEndTime 15:45 usual pre-close cutoff; test a couple of values

(No Start/Step/End table here - hand-pick a few combinations, run each as a full backtest, and lock the best before moving to Group B.)

GROUP B: STOP LOSS

Input Start Step End Note
UseStopLoss 0 1 1 bool, default true: enables the fixed-tick stop (Pass 1 assumes this is true; see below)
StopLossTicks 20 20 200 fixed-tick stop (default 80)
UseORLevelStops 0 1 1 bool: fixed-tick vs OR-level stop
ORStopBufferTicks 0 2 20 only if UseORLevelStops = true

Run this as TWO SEPARATE optimization passes, not one combined grid: Pass 1 - UseORLevelStops forced FALSE, UseStopLoss forced TRUE: sweep StopLossTicks alone. (Leaving UseStopLoss false here would mean the position has NO stop loss at all, since UseORLevelStops is also false in this pass - don't test that combination unless you deliberately want a no-stop run.) Pass 2 - UseORLevelStops forced TRUE: sweep ORStopBufferTicks alone (StopLossTicks and UseStopLoss are irrelevant to this pass).

The strategy's own entry logic picks the OR-level stop first whenever UseORLevelStops is true (see the code's "IMPORTANT: UseORLevelStops works independently of UseStopLoss" comment) - StopLossTicks is not even read for stop placement in that case, so optimizing both stop inputs in the same grid wastes iterations on a combination that never resolves the way the grid implies. Pick a winner from each pass, then carry forward whichever stop MODE (fixed-tick or OR-level) produced the better, more stable result into Group C.

GROUP C: PROFIT TARGET

Input Start Step End Note
TargetTicks 40 20 300 profit target (default 120)

Optimize Group B and Group C TOGETHER (in whichever stop-mode pass you're running) - stop distance and target distance interact directly through the risk:reward ratio and win rate, so sweeping TargetTicks against a single fixed StopLossTicks (or ORStopBufferTicks) value will miss the real edge. Run the full StopLossTicks x TargetTicks grid (or ORStopBufferTicks x TargetTicks grid) for each stop-mode pass.

GROUP D: BREAKEVEN (default ON)

Input Start Step End Note
BreakEvenTriggerTicks 20 10 100 default 40
BreakEvenOffsetTicks 0 5 30 default 10

(UseBreakEven defaults to true in this strategy. See GROUP E below for why you should not enable Group E at the same time.)

GROUP E: TRAILING STOP (optional, OFF by default)

Input Start Step End Note
TrailingStopTriggerTicks 20 10 150 default 60
TrailingStopOffsetTicks 10 10 100 default 30

CRITICAL: Never enable UseBreakEven and UseTrailingStop together, and never optimize Group D and Group E in the same pass. With the defaults, breakeven's trigger (40 ticks) is LOWER than trailing's trigger (60 ticks), so breakeven fires first and moves the stop via SetStopLoss() while the trailing-stop logic is independently placing its own initial protective stop order every bar until ITS trigger is reached - two stop-management paths acting on the same position before trailing ever activates. The strategy's own code has an explicit comment warning about this conflict. Also note: whenever UseTrailingStop is true, the entry-time stop selection (fixed-tick or OR-level, Group B) is skipped entirely - the trailing-stop system manages its own initial stop using StopLossTicks regardless of UseORLevelStops. If you want the OR-level stop mode from Group B, keep UseTrailingStop off. Pick ONE of Group D or Group E, never both.

GROUP F: TRADE MANAGEMENT

Input Start Step End Note
MaxTradesPerDay 1 1 3 default 1
RequireClosedCandleBreakout 0 1 1 bool, default true

GROUP G: ENTRY FILTERS (one at a time)

Input Start Step End Note
UseMinimumBreakoutSize 0 1 1 bool, default true
MinimumBreakoutTicks 2 2 20 only if filter on (default 5)
UseVolumeFilter 0 1 1 bool, default true
VolumeMultiplier 0.8 0.2 2.0 only if filter on (default 1.2)

SET, DON'T OPTIMIZE

ContractQty : your own position-size choice, not an edge parameter. Set it to what you'll actually trade live; optimizing it only rescales P&L, it doesn't change the edge.

DO NOT TOUCH (purely cosmetic, no effect on trading logic)

ShowORBox, ORBoxOpacity, ShowORLines, ORLineWidth, ORBoxColorSerialized / ORBoxColorSerializable, ORLineColorSerialized / ORLineColorSerializable.

PHASES (order; lock each before the next)

  1. Pick the OR window and trade window (Group A) - manual, a few sensible combinations (e.g. 15/30/45-minute OR windows from the session open). Lock it before proceeding.
  2. Optimize Group B + C TOGETHER, run as two separate stop-mode passes (fixed-tick StopLossTicks x TargetTicks, then OR-level ORStopBufferTicks x TargetTicks). Compare the two passes and lock whichever stop mode + target combination wins.
  3. Group F (trade management / frequency) - MaxTradesPerDay, RequireClosedCandleBreakout.
  4. Group G (entry filters) - one filter at a time: first UseMinimumBreakoutSize/MinimumBreakoutTicks alone, then UseVolumeFilter/VolumeMultiplier alone, keeping the other at its locked/default state while you test each.
  5. Choose ONE of Group D (breakeven) or Group E (trailing stop) as a final optional overlay on top of the already-locked settings from steps 1-4. Never enable both. Optimize it last, against the locked OR window, trade window, stop mode, target, trade management, and filters.

READING RESULTS / VALIDATION

  • Don't sort by Net Profit alone. In the Strategy Analyzer's optimization results grid, weigh:
    • Profit Factor > 1.2 (>1.5 is strong)
    • Max Drawdown - can you stomach it live?
    • Sharpe Ratio - rewards smoother, more consistent equity
    • Total trades - 100+ over the test period is ideal; under 30 is noise, don't trust it
  • CLUSTER TEST: the best row should be surrounded by other good rows in the grid. If its neighbors are losers, it's a curve-fit - discard it and pick from a broad, stable plateau of good results instead of an isolated spike.
  • OUT-OF-SAMPLE VALIDATION: use the Strategy Analyzer's Walk-Forward Optimization feature, or do it manually - optimize on an older slice of data, then run the locked winner UNCHANGED on a held-out, more recent slice. Keep the setting only if it holds up with similar character on the unseen data; if it collapses, it was curve-fit - go back and pick a broader, coarser setting from the cluster.
  • Repeat per instrument and per session, since OR window, filters, and stop/target behavior are all session- and instrument-dependent.

QUICK-START CHECKLIST

  • OR window and trade window chosen and fixed (Group A, manual)
  • Stop mode chosen: fixed-tick XOR OR-level stop (never both)
  • Group B/C (stop + target) locked from a stable cluster, per stop-mode pass
  • Group F (trade management) tuned
  • Group G entry filters tuned ONE AT A TIME
  • Only ONE of breakeven (Group D) or trailing stop (Group E) enabled, if either - never both together
  • Picked from a STABLE CLUSTER, not an isolated spike
  • Healthy trade count (100+ ideal), acceptable Max Drawdown, Profit Factor > 1.2, reasonable Sharpe Ratio
  • Validated with Walk-Forward Optimization / out-of-sample data - it held up unchanged
  • Repeated per instrument / session
  • Demo-confirmed before going live