DARKPOOL ALGO
Guides/EnhancedORBIndicator
Free Optimization Guide

EnhancedORBIndicator Optimization Guide

1. What EnhancedORBIndicator Is

EnhancedORBIndicator is a visualization-only companion to the Enhanced ORB Strategy (OpeningRangeBreakoutEnhanced in EnhancedORBStrategy.cs). It draws everything the strategy would act on — or reject — without ever placing an order: the opening range box, the OR high/low lines, a shaded trade window, and a marker at every breakout crossing showing whether that breakout would have passed the strategy's entry filters. Nothing here submits orders, touches Position, or reads account state; it is a pure charting tool that never appears in the Strategies tab, only as an indicator you drop on a chart.

It reuses the existing OpeningRangeIndicator internally for the opening-range high/low calculation, via orIndicator = OpeningRangeIndicator(OrStartTime, OrEndTime); in State.DataLoaded. That means the OR high/low you see on this indicator is computed by the exact same code path the strategy itself uses — one shared source of truth, not a reimplementation that could quietly drift out of sync.

Because the Opening Range group and Entry Filters group use the same parameter names and defaults as Enhanced ORB Strategy, you can copy your strategy instance's settings straight into this indicator and watch, on a chart, exactly which crossings that configuration would have taken and which it would have rejected — before committing to a live or simulated run.

2. Installation

Manual .cs drop (how this indicator ships)

Copy EnhancedORBIndicator.cs into your bin\Custom\Indicators folder, then open the NinjaScript Editor inside NinjaTrader and press F5 to compile. If compilation fails, read the error list at the bottom of the editor.

Warning: Never unzip a NinjaScript export .zip manually into bin\Custom. Exported .zip packages from the NinjaScript editor can bundle unrelated files — including stale copies of NinjaTrader's own stock indicators — alongside the file you actually want. Hand-extracting one of these zips risks silently overwriting live stock indicator files with older versions. Copying only the single .cs file (plus making sure OpeningRangeIndicator.cs is already present in your Indicators folder, since EnhancedORBIndicator calls it internally) is correct and sufficient.

3. Adding It to a Chart

Open a chart, right-click, choose Indicators..., find EnhancedORBIndicator in the list, and add it. It draws as an overlay directly on the price panel (IsOverlay = true, DrawOnPricePanel = true) — the OR box, OR lines, breakout arrows, rejection labels, and trade-window shading all plot on price, alongside your candles.

Warmup — two floors, not one

  • The Opening Range must complete for the current day first. No box, lines, arrows, labels, or shading will appear until the configured OR period (OrStartTime to OrEndTime) has actually finished on the chart's current trading day. Until Times[0][0].TimeOfDay >= OrEndTime.TimeOfDay, the indicator has no OR high/low to draw or evaluate against. This resets every day — each new session starts back in this same "waiting for OR to complete" state (orPeriodComplete is reset whenever Times[0][0].Date changes). This is expected daily warmup behavior, not a bug.
  • A fixed CurrentBar < 20 bar-count floor underneath that. At the very top of OnBarUpdate(), the indicator returns immediately if CurrentBar < 20, regardless of what the OR times are set to. On most intraday charts this floor is irrelevant (the OR period itself typically takes far more than 20 bars to complete), but it's worth knowing it's there as a hard secondary gate.

If you don't see anything on a freshly added chart, first check the clock — if it's before OrEndTime for today, that's exactly what's expected.

4. Parameter Reference

The table below is transcribed directly from the [Display] attributes in EnhancedORBIndicator.cs, so what you see in the NinjaTrader parameters dialog will match this table exactly — names, defaults, groups, and descriptions.

Parameter (display name) Default Group Description
OR Start Time 09:30 1. Opening Range Opening Range start time
OR End Time 10:00 1. Opening Range Opening Range end time
Trade Start Time 10:00 1. Opening Range Time to start considering breakout signals
Trade End Time 15:45 1. Opening Range Time to stop considering breakout signals
Use Minimum Breakout Size true 2. Entry Filters Require minimum breakout distance
Minimum Breakout (Ticks) 5 2. Entry Filters Minimum ticks beyond OR level
Use Volume Filter true 2. Entry Filters Require above-average volume
Volume Multiplier 1.2 2. Entry Filters Multiple of 20-period average volume
Show OR Box true 3. Visual Settings Draw a shaded box for the opening range
OR Box Opacity 20 3. Visual Settings Opacity of the OR box (1-100)
Show OR Lines true 3. Visual Settings Draw horizontal lines at OR high/low
OR Line Width 2 3. Visual Settings Width of OR lines
OR Box Color Orange 3. Visual Settings Color of the opening range box
OR Line Color Orange 3. Visual Settings Color of the opening range lines
Show Breakout Arrows true 3. Visual Settings Draw arrows for breakouts that pass all filters
Show Filter Labels true 3. Visual Settings Draw a gray label explaining why a breakout was rejected
Show Trade Window Shading true 3. Visual Settings Tint the background during the trade window

Notes on a couple of entries above:

  • Minimum Breakout (Ticks) is range-limited to 1–100 in the source ([Range(1, 100)]).
  • Volume Multiplier is range-limited to 0.1–5.0 ([Range(0.1, 5.0)]).
  • OR Box Opacity is range-limited to 1–100 ([Range(1, 100)]).
  • OR Line Width is range-limited to 1–5 ([Range(1, 5)]).
  • OR Box Color and OR Line Color are the color-picker properties (ORBoxColorSerialized / ORLineColorSerialized in code); both default to Orange.

This is deliberately the same 4 + 4 (Opening Range / Entry Filters) parameter set, with the same names and defaults, as Enhanced ORB Strategy's own Opening Range and Entry Filters groups — that parity is what makes a strategy-configuration preview possible (see Section 6). The indicator's third group, Visual Settings, has no strategy counterpart — it exists purely to control what this indicator draws.

5. How a Signal Forms

Everything below happens inside OnBarUpdate() and its helper EvaluateAndDraw(), on closed bars only (Calculate = Calculate.OnBarClose):

  1. The Opening Range is tracked via the internal OpeningRangeIndicator instance. Every bar, the indicator reads orIndicator.ORHighLine[0] and orIndicator.ORLowLine[0] — the same OR high/low values the strategy itself would compute.

  2. At OrEndTime, the OR box and lines are drawn (once per day, if enabled). The instant Times[0][0].TimeOfDay >= OrEndTime.TimeOfDay becomes true for the first time that day, orPeriodComplete flips to true, and — if ShowORBox is on and both OR levels are valid (> 0) — a shaded rectangle is drawn from the OR start bar to the OR high/low. If ShowORLines is on, two horizontal lines are drawn at the OR high and OR low, extending out to TradeEndTime.

  3. Trade-window background shading appears between TradeStartTime and TradeEndTime (if enabled). On every bar where Times[0][0].TimeOfDay falls inside that window, if ShowTradeWindowShading is on, the bar's background is tinted with a light blue shade (BackBrush = sessionShadeBrush).

  4. A CrossAbove/CrossBelow of the OR high/low is evaluated — but only once the OR period is complete AND the bar is inside the trade window. The indicator checks CrossAbove(Close, orHigh, 1) for a long candidate and CrossBelow(Close, orLow, 1) for a short candidate, but only after confirming orPeriodComplete is true, the bar's time is within [TradeStartTime, TradeEndTime], and both OR levels are valid. Outside the OR-complete/trade-window conditions, the indicator returns early and evaluates nothing.

  5. The crossing is checked against the minimum-breakout-size filter first (if enabled), then the volume filter (if enabled). Inside EvaluateAndDraw(): if UseMinimumBreakoutSize is on, the breakout distance in ticks is measured ((Close[0] - orLevel) / TickSize for longs, mirrored for shorts) and compared against MinimumBreakoutTicks. Only if that filter passes (or is disabled) does the volume filter run: if UseVolumeFilter is on, Volume[0] is compared against SMA(Volume, 20)[0] * VolumeMultiplier. The volume filter is skipped entirely if the breakout-size filter already failed.

  6. If all enabled filters pass, a solid colored arrow is drawn. A long that clears all filters gets a solid Lime up-arrow (Draw.ArrowUp) below the bar's low; a short gets a solid Red down-arrow (Draw.ArrowDown) above the bar's high. This only happens if ShowBreakoutArrows is also on — if it's off, a passed breakout draws nothing at all.

  7. If a filter rejects the breakout, a dimmed gray text label is drawn instead — with the specific rejection reason spelled out. The label uses the exact rejection reason generated in code:

    • Breakout-size rejection: "Breakout too small ({0:0.#} ticks, need {1})" — e.g. "Breakout too small (3.2 ticks, need 5)".
    • Volume rejection: "Low volume ({0:0} vs {1:0} avg required)" — e.g. "Low volume (842 vs 1010 avg required)".

    The full label text is prefixed with "X (long) " or "X (short) " depending on direction, so a real label reads like "X (long) Breakout too small (3.2 ticks, need 5)". This only draws if ShowFilterLabels is on.

Show Breakout Arrows and Show Filter Labels are independent toggles, confirmed directly in the code. EvaluateAndDraw() branches on passedFilters: the passed-filter branch checks only ShowBreakoutArrows before drawing an arrow (and returns without drawing anything if it's off), while the separate rejected branch checks only ShowFilterLabels before drawing a label. Neither toggle reads or affects the other — turning one off has zero effect on whether the other still draws.

6. Tuning Cookbook

Goal: preview a specific Enhanced ORB Strategy configuration. Change: set every parameter on this indicator — OR Start/End Time, Trade Start/End Time, Use Minimum Breakout Size, Minimum Breakout Ticks, Use Volume Filter, Volume Multiplier — to match your strategy instance's configuration exactly, field for field. Expect: the arrows and labels on the chart now preview precisely what that strategy configuration would do at each breakout — a solid arrow means the strategy would enter there, and a rejection label tells you exactly which filter (and by how much) would have blocked it.

Goal: reduce visual clutter. Change: turn off Show Filter Labels to see only accepted breakouts (arrows only, no rejection text cluttering the chart), or turn off Show Trade Window Shading if you find the background tint distracting. Expect: a visually quieter chart. Turning off Show Filter Labels does not hide arrows (see Section 5's toggle-independence note), and turning off shading has no effect on OR box/lines/arrows/labels — it only removes the background tint.

Goal: see every breakout regardless of filters. Change: turn off both Use Minimum Breakout Size and Use Volume Filter. Expect: every CrossAbove/CrossBelow of the OR high/low inside the trade window now passes EvaluateAndDraw() with passedFilters staying true throughout, so every raw crossing draws as a solid arrow instead of being evaluated against either filter. Useful for seeing the raw, unfiltered breakout frequency before you decide how aggressively to filter it.

Goal: focus purely on the OR levels and window, without any signal markers. Change: turn off Show Breakout Arrows and Show Filter Labels, but leave Show OR Box, Show OR Lines, and Show Trade Window Shading on. Expect: a clean chart showing only the opening range and the trade window — no arrows or text at all, regardless of how many crossings occur or how they'd be filtered.

7. Known Limitations & Honest Caveats

  • The CurrentBar < 20 warmup guard is a fixed floor, not adaptive to your configured OR window. This check is literally the first line of OnBarUpdate(): if (CurrentBar < 20) return;. It does not scale with how long your OR period is configured to run — if you set a very short OR window on a very slow timeframe, this fixed 20-bar floor (not the OR-completion check) could in principle be the more restrictive gate in edge cases, though on typical intraday setups the OR-completion wait in Section 3 will dominate.
  • Parameters are configured independently on the indicator and the strategy — they are not linked. EnhancedORBIndicator and OpeningRangeBreakoutEnhanced (the strategy) are separate NinjaScript objects, each with its own copy of OrStartTime, OrEndTime, TradeStartTime, TradeEndTime, UseMinimumBreakoutSize, MinimumBreakoutTicks, UseVolumeFilter, and VolumeMultiplier. Editing the strategy's settings does nothing to this indicator's settings, and vice versa. If you change your strategy's configuration, you must manually update the indicator's parameters to match if you want the chart preview to stay an accurate reflection of what the strategy would do.
  • This indicator has no concept of an open position. It cannot preview stop-loss, profit-target, breakeven-trigger, or trailing-stop behavior — none of that logic exists in this file at all (no Position access, no SetStopLoss/SetProfitTarget/SetTrailStop calls). It only marks entry-side breakout signals and their filter outcomes. To see how a trade would actually be managed once open — stop placement, breakeven, trailing — you need to run the Enhanced ORB Strategy itself, in simulation or live, through NT8's Strategy Analyzer or a live/sim account.

8. Troubleshooting

I don't see the OR box or lines. Check that Show OR Box / Show OR Lines are actually turned on in the parameters dialog. If they are, confirm OrEndTime has actually been reached yet today on the chart — the box and lines are only drawn once, at the moment the OR period completes for the current day (Section 3). Before that moment each day, there is nothing to draw.

No arrows or labels appear at all. Two independent conditions must both be true before any evaluation happens: the current bar's time must fall inside the Trade Start Time–Trade End Time window, and the OR period must already be complete for the day. If either isn't true yet, OnBarUpdate() returns before ever checking for a crossing — this is normal, not a malfunction. Also double-check Show Breakout Arrows and/or Show Filter Labels aren't both switched off, since a passing or failing breakout will silently draw nothing if its corresponding toggle is off.

The strategy took a trade but the indicator didn't mark it (or vice versa). Since the indicator and strategy are configured completely independently (Section 7), the most common cause is a parameter mismatch — different OR times, different trade window, different filter settings, or a different Minimum Breakout Ticks / Volume Multiplier value between the two instances. Re-check every parameter in Section 4 side-by-side against your strategy's actual settings.

The indicator shows as disabled after I edited the source. Recompile: open the NinjaScript Editor and press F5. NinjaTrader disables any NinjaScript object whose compiled binary is out of sync with its source until a successful recompile completes.

9. Risk Disclaimer

Trading futures and other derivatives involves substantial risk of loss and is not suitable for every investor. EnhancedORBIndicator is an educational and analytical tool, not a signal service or investment advice. Any historical or hypothetical performance referenced in connection with this indicator or its companion strategy does not guarantee future results. Backtested and hypothetical results have inherent limitations and should not be relied upon as an indicator of actual future performance. You are solely responsible for your own trading decisions, risk management, and compliance with applicable rules and regulations.