Opening range breakout managed Strategy
A single-file example that freezes a daily opening range, checks close breakouts, and attaches fixed managed protection.
using System;
using System.ComponentModel.DataAnnotations;
using NinjaTrader.Cbi;
using NinjaTrader.NinjaScript;
namespace NinjaTrader.NinjaScript.Strategies
{
public class OpeningRangeBreakoutStrategy : Strategy
{
private DateTime rangeDate = DateTime.MinValue;
private double rangeHigh;
private double rangeLow;
private bool rangeReady;
[NinjaScriptProperty]
[Range(0, 235959)]
[Display(Name = "Range start", GroupName = "Session", Order = 0)]
public int RangeStart { get; set; }
[NinjaScriptProperty]
[Range(0, 235959)]
[Display(Name = "Range end", GroupName = "Session", Order = 1)]
public int RangeEnd { get; set; }
[NinjaScriptProperty]
[Range(1, 200)]
[Display(Name = "Stop ticks", GroupName = "Risk", Order = 2)]
public int StopTicks { get; set; }
[NinjaScriptProperty]
[Range(1, 400)]
[Display(Name = "Target ticks", GroupName = "Risk", Order = 3)]
public int TargetTicks { get; set; }
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Name = "OpeningRangeBreakoutStrategy";
Calculate = Calculate.OnBarClose;
BarsRequiredToTrade = 20;
RangeStart = 93000;
RangeEnd = 100000;
StopTicks = 12;
TargetTicks = 24;
}
else if (State == State.Configure)
{
SetStopLoss("LongEntry", CalculationMode.Ticks, StopTicks, false);
SetProfitTarget("LongEntry", CalculationMode.Ticks, TargetTicks);
SetStopLoss("ShortEntry", CalculationMode.Ticks, StopTicks, false);
SetProfitTarget("ShortEntry", CalculationMode.Ticks, TargetTicks);
}
}
protected override void OnBarUpdate()
{
if (CurrentBar < BarsRequiredToTrade)
return;
if (rangeDate != Time[0].Date)
{
rangeDate = Time[0].Date;
rangeHigh = double.MinValue;
rangeLow = double.MaxValue;
rangeReady = false;
}
int currentTime = Time[0].Hour * 10000
+ Time[0].Minute * 100
+ Time[0].Second;
if (currentTime >= RangeStart && currentTime <= RangeEnd)
{
rangeHigh = Math.Max(rangeHigh, High[0]);
rangeLow = Math.Min(rangeLow, Low[0]);
return;
}
if (!rangeReady && currentTime > RangeEnd && rangeHigh > double.MinValue)
rangeReady = true;
if (!rangeReady || Position.MarketPosition != MarketPosition.Flat)
return;
if (Close[0] > rangeHigh)
EnterLong(1, "LongEntry");
else if (Close[0] < rangeLow)
EnterShort(1, "ShortEntry");
}
}
}