#region Using declarations using System; using System.ComponentModel.DataAnnotations; using NinjaTrader.Cbi; using NinjaTrader.Data; using NinjaTrader.NinjaScript.Indicators; #endregion //This namespace holds Strategies in this folder and is required. Do not change it. namespace NinjaTrader.NinjaScript.Strategies { public class MovingAverageCrossoverBot : Strategy { private MovingAverage ma1; private MovingAverage ma2; private MovingAverage ma3; private ATR atr; private OpeningRange openingRange; protected override void OnStateChange() { if (State == State.SetDefaults) { Description = @""; Name = "Moving Average Crossover Bot"; Calculate = Calculate.OnBarClose; EntriesPerDirection = 1; EntryHandling = EntryHandling.AllEntries; IsExitOnSessionCloseStrategy = true; ExitOnSessionCloseSeconds = 30; IsFillLimitOnTouch = false; MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix; OrderFillResolution = OrderFillResolution.Standard; Slippage = 0; StartBehavior = StartBehavior.WaitUntilFlat; TimeInForce = TimeInForce.Gtc; TraceOrders = false; RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose; StopTargetHandling = StopTargetHandling.PerEntryExecution; BarsRequiredToTrade = 100; IsInstantiatedOnEachOptimizationIteration = true; MovingAveragePeriod1 = 3; MovingAveragePeriod2 = 17; MovingAveragePeriod3 = 50; ATRPeriod = 14; ATRMultiplier = 2; } else if (State == State.Configure) { // Data series required by the opening range indicator, must be loaded here. AddDataSeries(BarsPeriodType.Minute, 1); AddDataSeries(Instrument.FullName, BarsPeriod, "US Equities RTH"); } else if (State == State.DataLoaded) { atr = ATR(ATRPeriod); ma1 = MovingAverage(MovingAveragePeriod1); ma2 = MovingAverage(MovingAveragePeriod2); ma3 = MovingAverage(MovingAveragePeriod3); openingRange = OpeningRange(30, OpeningRangeBarType.Minutes); } } protected override void OnBarUpdate() { if (BarsInProgress != 1) return; if (CurrentBar < BarsRequiredToTrade) return; if (Position.MarketPosition != MarketPosition.Flat) return; DateTime now = Time[0]; if (now <= openingRange.GetOpeningRangeEndTime(now)) return; double atrValue = atr[0]; double stopLoss = ATRMultiplier * atrValue; if (CrossAbove(ma1, ma2, 1) && //ma2[0] > ma3[0] && openingRange.ORH[0] > 0.0 && Close[0] > openingRange.ORH[0]) { EnterLong(); SetTrailStop(CalculationMode.Ticks, stopLoss / TickSize); } else if (CrossBelow(ma1, ma2, 1) && //ma2[0] < ma3[0] && openingRange.ORL[0] > 0.0 && Close[0] < openingRange.ORL[0]) { EnterShort(); SetTrailStop(CalculationMode.Ticks, stopLoss / TickSize); } } public override string DisplayName { get { return Name; } } [Range(1, int.MaxValue), NinjaScriptProperty] [Display(Name = "Moving Average Period 1", GroupName = "Moving Average Crossover Bot", Order = 1)] public int MovingAveragePeriod1 { get; set; } [Range(1, int.MaxValue), NinjaScriptProperty] [Display(Name = "Moving Average Period 2", GroupName = "Moving Average Crossover Bot", Order = 2)] public int MovingAveragePeriod2 { get; set; } [Range(1, int.MaxValue), NinjaScriptProperty] [Display(Name = "Moving Average Period 3", GroupName = "Moving Average Crossover Bot", Order = 3)] public int MovingAveragePeriod3 { get; set; } [Range(1, int.MaxValue), NinjaScriptProperty] [Display(Name = "ATR Period", GroupName = "Moving Average Crossover Bot", Order = 4)] public int ATRPeriod { get; set; } [Range(0.1, double.MaxValue), NinjaScriptProperty] [Display(Name = "ATR Multiplier", GroupName = "Moving Average Crossover Bot", Order = 5)] public double ATRMultiplier { get; set; } } }