← All projects

NinjaTrader 8 Order-Flow Imbalance Scalper

Unmanaged NinjaScript strategy that classifies every trade print, scores order-flow imbalance with rolling Z-scores and scalps with layered protection logic.

Client
Futures scalper
Year
2026
Category
Trading Systems
Stack
  • NinjaTrader 8
  • C#
  • NinjaScript
  • Tick Replay

The problem

The spec called for a scalper that reacts to order-flow imbalance as it happens, not at bar close. It also had to be safe enough to leave running: every fill protected, hard daily limits, and no surprises on restart.

What I built

  • Tick-level signal: OnMarketData() caches the best bid and ask and processes every last-trade print. Signals are evaluated intrabar on each trade.
  • Aggressor classification: prints at or above the ask count as buys and at or below the bid as sells. The fallback is the uptick/downtick rule, then the last known direction.
  • OFI statistics: delta, imbalance percent, and a rolling mean, standard deviation and Z-score. The lookback is either per bar or a rolling tick window.
  • Entry filters: Z-score and imbalance thresholds per side, minimum volume, maximum spread and an optional fast/slow trend filter.
  • Unmanaged orders: market or limit entries with an entry timeout. A stop is submitted on every fill, and an optional target is OCO-linked to it.
  • Trade management: breakeven, an optional trailing stop, optional reversal, one trade at a time and cooldown bars.
  • Risk limits: an HHmmss trading window that can cross midnight, exit on session close, max trades, max consecutive losses, daily loss and profit locks, max hold time and max bars in trade.
  • Operating modes: log-only mode (signals without orders), wait-until-flat on start, and strategy-only or account-wide flatten on shutdown. A small OFI status block and signal markers are drawn on the chart.

Details

  • Missing-protection watchdog: after a short grace period, if a position has no working stop (or a required target is missing), the strategy locks trading and flattens.
  • Stops only tighten: stop moves are tracked as pending changes, so a stop is never loosened or modified twice in flight.
  • Backtest parity: the logic lives in OnMarketData(), so historical tests run with Tick Replay. The recommended flow is tick charts, then Sim or Market Replay, then live.