Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

SetStopLoss Huge Slippage

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    SetStopLoss Huge Slippage

    When I used SetStopLoss(CalculationMode.Currency, 3000), the average loss was $3000 but the maximum loss was $11875.
    How can I prevent this huge slippage?
    Click image for larger version

Name:	image.png
Views:	151
Size:	54.4 KB
ID:	1336062

    #2
    Hello muaythai,

    Is this historical (backtest) or real-time?

    If this is historical for accurate order fill executions you will need to stop using Set methods and use Exit methods (or the unmanaged approach) and implement 1-tick intra-bar granularity.

    See the support article linked below which includes an example script.
    Chelsea B.NinjaTrader Customer Service

    Comment


      #3
      If I use the ExitLongStopMarket, am I required to select the tick replay?
      I have the following code.

      Code:
      if (BarsInProgress == 1)
                  {
                      if (CurrentBar < BarsRequiredToTrade)
                      {
                          return;
                      }
                      currentOpen = CurrentDayOHL().CurrentOpen[0];
                      
                      if (Position.MarketPosition == MarketPosition.Flat)
                      {
                          if (Close[0] > currentOpen + atr * 0.40)
                          {
                              EnterLong("long");
                              entryTime = Time[0];
                              double stopPrice = Close[0] - 50;
                              ExitLongStopMarket(1, true, 1, stopPrice, "stop long", "");
                                  
                              //SetStopLoss(CalculationMode.Price, Close[0] - 100);
                          }
                          else if (Close[0] < currentOpen - atr * 2)
                          {
                              EnterShort("short");
                              entryTime = Time[0];
                              double stopPrice = Close[0] + 50;
                              ExitLongStopMarket(1, true, 1, stopPrice, "stop short", "");
                              //SetStopLoss(CalculationMode.Price, Close[0] + 100);
                          }
                      }
                  }​
      This code doesn't set any stop loss when I don't use the tick replay.
      I use 1Day as a primary data series and 1Second as a secondary data series. I want to set a stop loss in the secondary data series.
      Last edited by muaythai; 02-27-2025, 09:43 PM.

      Comment


        #4
        Hello muaythai,

        TickReplay only affects historical and allows Calculate to update for each tick or price change in historical.

        The Exit orders should be sent from OnExecutionUpdate() when the entry order fills. Until the entry fills and a position is taken any exit orders will be ignored.

        Below is a link to an example script (ProfitCasestopTrailExitOrdersExample) that submits the exit stop and limit from OnExecutionUpdate(). (You can focus just on that part of the code)
        Chelsea B.NinjaTrader Customer Service

        Comment


          #5
          Hi!

          Thank you for the information. ExitLongStopMarket() works with most of the cases, but it seems that my code does not allow the long entry and stop loss on the same day. I have 1Day as a primary data series and 1Second as a secondary data series.

          The Problem
          Click image for larger version

Name:	image.png
Views:	189
Size:	25.8 KB
ID:	1336280
          The sample code:
          Code:
          #region Using declarations
          using System;
          using System.Collections.Generic;
          using System.ComponentModel;
          using System.ComponentModel.DataAnnotations;
          using System.Linq;
          using System.Text;
          using System.Threading.Tasks;
          using System.Windows;
          using System.Windows.Input;
          using System.Windows.Media;
          using System.Xml.Serialization;
          using NinjaTrader.Cbi;
          using NinjaTrader.Gui;
          using NinjaTrader.Gui.Chart;
          using NinjaTrader.Gui.SuperDom;
          using NinjaTrader.Gui.Tools;
          using NinjaTrader.Data;
          using NinjaTrader.NinjaScript;
          using NinjaTrader.Core.FloatingPoint;
          using NinjaTrader.NinjaScript.Indicators;
          using NinjaTrader.NinjaScript.DrawingTools;
          #endregion
          
          //This namespace holds Strategies in this folder and is required. Do not change it.
          namespace NinjaTrader.NinjaScript.Strategies.experiment
          {
              public class SampleStopLoss : Strategy
              {
                  private Order entryOrder = null;
                  private Order stopOrder = null;
                  private Order targetOrder = null;
                  private int sumFilled = 0;
                  
                  private double currentOpen;
                  private double atr;
                  
                  protected override void OnStateChange()
                  {
                      if (State == State.SetDefaults)
                      {
                          Description                                    = @"Enter the description for your new custom Strategy here.";
                          Name                                        = "SampleStopLoss";
                          Calculate                                    = Calculate.OnBarClose;
                          EntriesPerDirection                            = 1;
                          EntryHandling                                = EntryHandling.AllEntries;
                          IsExitOnSessionCloseStrategy                = false;
                          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                            = 20;
                          // Disable this property for performance gains in Strategy Analyzer optimizations
                          // See the Help Guide for additional information
                          IsInstantiatedOnEachOptimizationIteration    = true;
                      }
                      else if (State == State.Configure)
                      {
                          AddDataSeries(BarsPeriodType.Second, 1);
                      }
                      else if (State == State.Realtime)
                      {
                          if (entryOrder != null)
                              entryOrder = GetRealtimeOrder(entryOrder);
                          if (stopOrder != null)
                              stopOrder = GetRealtimeOrder(stopOrder);
                          if (targetOrder != null)
                              targetOrder = GetRealtimeOrder(targetOrder);
                      }
                  }
          
                  protected override void OnBarUpdate()
                  {
                      //Add your custom strategy logic here.
                      if (CurrentBar < BarsRequiredToTrade)
                          return;
                      if (BarsInProgress == 0)
                      {
                          atr = ATR(2)[1];
                      }
                      if (BarsInProgress == 1)
                      {
                          currentOpen = CurrentDayOHL().CurrentOpen[0];
                          bool condition = (Close[0] > currentOpen + atr * 0.4);
                          if (entryOrder == null && Position.MarketPosition == MarketPosition.Flat && condition)
                          {
                              EnterLong(1, 1, "MyEntry");
                          }
                          
                          if (Position.MarketPosition == MarketPosition.Long)
                          {
                              if (Close[0] > Position.AveragePrice && BarsSinceEntryExecution(0, "MyEntry", 0) >= 3)
                              {
                                  ExitLong(1, 1, "MyExit", "MyEntry");
                              }
                          }
                          /*
                          if (Position.MarketPosition == MarketPosition.Long && Close[0] >= Position.AveragePrice + (7 * (TickSize / 2)))
                          {
                              if (stopOrder != null && stopOrder.StopPrice < Position.AveragePrice)
                              {
                                  stopOrder = ExitLongStopMarket(0, true, stopOrder.Quantity, Position.AveragePrice, "MyStop", "MyEntry");
                              }
                          }
                          */
                      }
                      
                  }
                  
                  protected override void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string nativeError)
                  {
                      if (order.Name == "MyEntry")
                      {
                          entryOrder = order;
                          if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
                          {
                              entryOrder = null;
                              sumFilled = 0;
                          }
                      }
                  }
                  
                  protected override void OnExecutionUpdate(Execution execution, string executionId, double price, int quantity, MarketPosition marketPosition, string orderId, DateTime time)
                  {
                      if (entryOrder != null && entryOrder == execution.Order)
                      {
                          if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
                          {
                              sumFilled += execution.Quantity;
                              
                              if (execution.Order.OrderState == OrderState.PartFilled)
                              {
                                  stopOrder = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - 100, "MyStop", "MyEntry");
                              }
                              else if (execution.Order.OrderState == OrderState.Filled && sumFilled == execution.Order.Filled)
                              {
                                  // Stop-Loss order for OrderState.Filled
                                  stopOrder = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - 100, "MyStop", "MyEntry");
                                  //targetOrder = ExitLongLimit(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + 8 * TickSize, "MyTarget", "MyEntry");
                              }
                              if (execution.Order.OrderState != OrderState.PartFilled && sumFilled == execution.Order.Filled)
                              {
                                  entryOrder = null;
                                  sumFilled = 0;
                              }
                          }
                      }
                      if (stopOrder != null && stopOrder == execution.Order)
                      {
                          if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled)
                          {
                              stopOrder = null;
                          }
                      }
                  }
              }
          }
          ​

          Comment


            #6
            Hello muaythai,

            Submit the stop market orders to BarsInProgressIndex 1 (the 1 second series)

            ExitLongStopMarket(1, true, execution.Order.Filled, execution.Order.AverageFillPrice - 100, "MyStop", "MyEntry");


            Also, assign orders to variables from OnOrderUpdate() and not directly from the order method return object. (See lines 238, 250, 100 and 101 in the example I provided)
            Chelsea B.NinjaTrader Customer Service

            Comment


              #7
              Now, I have the following AssignOrderToVariable function.
              Code:
              private void AssignOrderToVariable(ref Order order)
                      {
                          if (order.Name == "MyEntry" && entryOrder != order)
                              entryOrder = order;
                          if (order.Name == "MyStop" && stopOrder != order)
                              stopOrder = order;
                      }​
              And I called it in OnOrderUpdate.
              Code:
              protected override void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string nativeError)
                      {
                          AssignOrderToVariable(ref order);
                          
                          if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
                          {
                              entryOrder = null;
                              sumFilled = 0;
                          }
                          
                      }​
              Is this correct?

              Comment


                #8
                Hello muaythai,

                Yes, the assigning to variables appears correct.
                Chelsea B.NinjaTrader Customer Service

                Comment


                  #9
                  If my current code resets the order of all the entry orders to null when any order is called, then this is not what I intend.
                  I just want the entryOrder of the specific entry which is cancelled to be null.

                  Is there a better way to do this?

                  Comment


                    #10
                    Hello muaythai,

                    if (order == entryOrder && order.OrderState == OrderState.Cancelled && order.Filled == 0)
                    Chelsea B.NinjaTrader Customer Service

                    Comment


                      #11
                      Thank you so much for being patient with me! You've helped me a lot!

                      Comment

                      Latest Posts

                      Collapse

                      Topics Statistics Last Post
                      Started by NullPointStrategies, Today, 05:17 AM
                      0 responses
                      39 views
                      0 likes
                      Last Post NullPointStrategies  
                      Started by argusthome, 03-08-2026, 10:06 AM
                      0 responses
                      124 views
                      0 likes
                      Last Post argusthome  
                      Started by NabilKhattabi, 03-06-2026, 11:18 AM
                      0 responses
                      64 views
                      0 likes
                      Last Post NabilKhattabi  
                      Started by Deep42, 03-06-2026, 12:28 AM
                      0 responses
                      41 views
                      0 likes
                      Last Post Deep42
                      by Deep42
                       
                      Started by TheRealMorford, 03-05-2026, 06:15 PM
                      0 responses
                      46 views
                      0 likes
                      Last Post TheRealMorford  
                      Working...
                      X