#region Using declarations using System; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using NinjaTrader.Cbi; using NinjaTrader.Data; using NinjaTrader.Gui; using NinjaTrader.Gui.Chart; using NinjaTrader.Gui.SuperDom; using NinjaTrader.Gui.Tools; using NinjaTrader.NinjaScript; using NinjaTrader.NinjaScript.DrawingTools; using NinjaTrader.NinjaScript.Indicators; #endregion namespace NinjaTrader.NinjaScript.Strategies { public class PropFirmBot_ES : Strategy { // Indicators private SMA fastMA; private SMA slowMA; private RSI rsi; private MACD macd; private ATR atr; // Strategy Parameters [NinjaScriptProperty] [Range(1, int.MaxValue)] [Display(Name = "Fast MA Period", Order = 1, GroupName = "Parameters")] public int FastMAPeriod { get; set; } [NinjaScriptProperty] [Range(1, int.MaxValue)] [Display(Name = "Slow MA Period", Order = 2, GroupName = "Parameters")] public int SlowMAPeriod { get; set; } [NinjaScriptProperty] [Range(1, int.MaxValue)] [Display(Name = "RSI Period", Order = 3, GroupName = "Parameters")] public int RSIPeriod { get; set; } [NinjaScriptProperty] [Range(0.1, double.MaxValue)] [Display(Name = "Profit Target (Ticks)", Order = 4, GroupName = "Parameters")] public double ProfitTargetTicks { get; set; } [NinjaScriptProperty] [Range(0.1, double.MaxValue)] [Display(Name = "Stop Loss (Ticks)", Order = 5, GroupName = "Parameters")] public double StopLossTicks { get; set; } // Trailing Stop Parameters [NinjaScriptProperty] [Range(0.1, double.MaxValue)] [Display(Name = "ATR Multiplier for Trailing Stop", Order = 6, GroupName = "Parameters")] public double AtrMultiplier { get; set; } // Contract Quantity [NinjaScriptProperty] [Range(1, int.MaxValue)] [Display(Name = "Contract Quantity", Order = 7, GroupName = "Risk Management")] public int ContractQuantity { get; set; } [NinjaScriptProperty] [Range(0.0, double.MaxValue)] [Display(Name = "Maximum Drawdown ($)", Order = 8, GroupName = "Risk Management")] public double MaximumDrawdown { get; set; } [NinjaScriptProperty] [Range(0.0, double.MaxValue)] [Display(Name = "Maximum Daily Loss ($)", Order = 9, GroupName = "Risk Management")] public double MaximumDailyLoss { get; set; } [NinjaScriptProperty] [Range(0.0, double.MaxValue)] [Display(Name = "Maximum Daily Profit ($)", Order = 10, GroupName = "Risk Management")] public double MaximumDailyProfit { get; set; } // Session Filter (Optional) private bool isWithinTradingHours; private double dailyPnl = 0; private double startingAccountValue; protected override void OnStateChange() { if (State == State.SetDefaults) { Description = @"PropFirmBot_ES: Enhanced MA Crossover Strategy with RSI and MACD Confirmation, ATR-Based Trailing Stops, and Improved Risk Management tailored for E-mini S&P 500 (ES) futures."; Name = "PropFirmBot_ES"; Calculate = Calculate.OnEachTick; FastMAPeriod = 10; SlowMAPeriod = 30; RSIPeriod = 14; ProfitTargetTicks = 40; StopLossTicks = 20; AtrMultiplier = 1.5; ContractQuantity = 1; MaximumDrawdown = 2500; MaximumDailyLoss = 1250; MaximumDailyProfit = 2000; IsOverlay = false; } else if (State == State.Configure) { AddDataSeries(Data.BarsPeriodType.Minute, 5); } else if (State == State.DataLoaded) { fastMA = SMA(BarsArray[0], FastMAPeriod); slowMA = SMA(BarsArray[0], SlowMAPeriod); rsi = RSI(BarsArray[0], RSIPeriod, 1); macd = MACD(BarsArray[0], 12, 26, 9); atr = ATR(BarsArray[0], 14); AddChartIndicator(fastMA); AddChartIndicator(slowMA); AddChartIndicator(rsi); AddChartIndicator(macd); AddChartIndicator(atr); startingAccountValue = Account.Get(AccountItem.CashValue, Currency.UsDollar); } } protected override void OnBarUpdate() { // Only process primary bars if (BarsInProgress != 0) return; // Check Maximum Drawdown and Daily Loss Limits double currentAccountValue = Account.Get(AccountItem.CashValue, Currency.UsDollar); double currentDrawdown = startingAccountValue - currentAccountValue; if (currentDrawdown >= MaximumDrawdown) { Print("Maximum drawdown reached. Stopping trading."); return; } if (dailyPnl <= -MaximumDailyLoss) { Print("Maximum daily loss reached. Stopping trading."); return; } if (dailyPnl >= MaximumDailyProfit) { Print("Maximum daily profit reached. Stopping trading."); return; } // Set a manual minimum bar count based on indicator periods int minBars = Math.Max(SlowMAPeriod, Math.Max(macd.Slow, macd.Smooth)) + RSIPeriod; if (CurrentBar < minBars) return; // Ensure strategy runs within session hours TimeSpan sessionStart = new TimeSpan(9, 30, 0); // 9:30 AM TimeSpan sessionEnd = new TimeSpan(16, 0, 0); // 4:00 PM TimeSpan currentTime = Time[0].TimeOfDay; isWithinTradingHours = currentTime >= sessionStart && currentTime <= sessionEnd; if (!isWithinTradingHours) return; // Long Entry Condition with MACD Confirmation if (CrossAbove(fastMA, slowMA, 1) && rsi[0] > 50 && macd.Diff[0] > 0) { EnterLong(ContractQuantity, "LongEntry"); } // Short Entry Condition with MACD Confirmation if (CrossBelow(fastMA, slowMA, 1) && rsi[0] < 50 && macd.Diff[0] < 0) { EnterShort(ContractQuantity, "ShortEntry"); } } // Corrected OnExecutionUpdate method protected override void OnExecutionUpdate(Execution execution, string executionId, double price, int quantity, MarketPosition marketPosition, string orderId, DateTime time) { // Ensure execution details are valid if (execution == null) return; // Update daily profit and loss double tradeProfitLoss = execution.Quantity * (price - execution.Order.AverageFillPrice) * (execution.MarketPosition == MarketPosition.Long ? 1 : -1); dailyPnl += tradeProfitLoss; // Set Profit Target and Stop Loss based on order name if (orderId == "LongEntry") { // Set Profit Target in Ticks SetProfitTarget(orderId, CalculationMode.Ticks, ProfitTargetTicks); // Set Stop Loss in Ticks SetStopLoss(orderId, CalculationMode.Ticks, StopLossTicks, false); // Set ATR-Based Trailing Stop in ATR multiples SetTrailStop(orderId, CalculationMode.Price, execution.Price - atr[0] * AtrMultiplier, false); } else if (orderId == "ShortEntry") { // Set Profit Target in Ticks SetProfitTarget(orderId, CalculationMode.Ticks, ProfitTargetTicks); // Set Stop Loss in Ticks SetStopLoss(orderId, CalculationMode.Ticks, StopLossTicks, false); // Set ATR-Based Trailing Stop in ATR multiples SetTrailStop(orderId, CalculationMode.Price, execution.Price + atr[0] * AtrMultiplier, false); } } } }