Announcement

Collapse

Looking for a User App or Add-On built by the NinjaTrader community?

Visit NinjaTrader EcoSystem and our free User App Share!

Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less

Partner 728x90

Collapse

Stop Market orders aren't getting filled

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

    Stop Market orders aren't getting filled

    Here is the strategy script:
    Code:
    namespace NinjaTrader.NinjaScript.Strategies
    {
        public class UA653GC60 : Strategy
        {
            private NinjaTrader.NinjaScript.Indicators.Features.MichaelsFunction MF;
            private bool StartTimeInv;
            private Series<int> MP;
            private int daysintrade;
            private Order LongOrder = null;
            private Order ShortOrder = null;
            private bool LongSignal, ShortSignal;
            
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                    Description                                    = @"Enter the description for your new custom Strategy here.";
                    Name                                        = "UA653GC60";
                    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                                    = true;
                    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;
                    
                    SessionStartTime                            = DateTime.Parse("19:00", System.Globalization.CultureInfo.InvariantCulture);
                    SessionEndTime                                = DateTime.Parse("17:00", System.Globalization.CultureInfo.InvariantCulture);
                    MyStartTime                                    = DateTime.Parse("10:00", System.Globalization.CultureInfo.InvariantCulture);
                    MyEndTime                                    = DateTime.Parse("16:00", System.Globalization.CultureInfo.InvariantCulture);
                    TE_Day_close                                = 5;
                    Quantity                                    = 1;
                    ProfitTarget                                = 2300;
                    StopLoss                                    = 2200;
                }
                else if (State == State.Configure)
                {
                    AddDataSeries(this.Instrument.FullName, BarsPeriodType.Day, 1);
                    SetProfitTarget(@"Long1", CalculationMode.Currency, ProfitTarget);
                    SetStopLoss(@"Long1", CalculationMode.Currency, StopLoss, false);
                    SetProfitTarget(@"Short1", CalculationMode.Currency, ProfitTarget);
                    SetStopLoss(@"Short1", CalculationMode.Currency, StopLoss, false);
                    
                }
                else if (State == State.DataLoaded)
                {
                    MF         = MichaelsFunction(SessionStartTime, SessionEndTime, false);
                    MP        = new Series<int>(this);
                    AddChartIndicator(MichaelsFunction(SessionStartTime, SessionEndTime, false));
                }
            }
    
            protected override void OnBarUpdate()
            {
                if (BarsInProgress != 0)
                    return;
                
                if (CurrentBars[1] < 2)
                    return;
                
                MP[0] = Position.MarketPosition == MarketPosition.Long ? 1 : Position.MarketPosition == MarketPosition.Short ? -1 : 0;
                
                if (ToTime(MyStartTime) > ToTime(MyEndTime))
                    StartTimeInv = ToTime(Time[0]) > ToTime(MyStartTime) || ToTime(Time[0]) < ToTime(MyEndTime);
                
                else if (ToTime(MyStartTime) < ToTime(MyEndTime))
                    StartTimeInv = (ToTime(Time[0]) > ToTime(MyStartTime) && ToTime(Time[0]) < ToTime(MyEndTime));
                
                //Long
                if (LongOrder == null && !LongSignal && MF.highd0[0] > (Lows[1][0] + (Highs[1][0] - Lows[1][0]) * 0.5) && StartTimeInv && MP[0] != 1)
                {
                    LongSignal = true;
                    Draw.TriangleDown(this, "Long1" + CurrentBar, true, 0, Low[0]-1, Brushes.Green);                
                    EnterLongStopMarket(0, true, Quantity, MF.highd0[0], "Long1");
                }
                //Short
                if (!ShortSignal && MF.lowd0[0] < (Highs[1][0] - (Highs[1][0] - Lows[1][0]) * 0.5) && StartTimeInv && MP[0] != -1)
                {
                    ShortSignal = true;
                    Draw.TriangleUp(this, "Short1" + CurrentBar, true, 0, High[0] + 1, Brushes.Red);
                    EnterShortStopMarket(0, true, Quantity, MF.lowd0[0], "Short1");
                }
                //Exit based on days
                if (MP[0] != MP[1] && MP[0] != 0)
                    daysintrade = 1;
                
                if (ToTime(Time[1]) < ToTime(MyEndTime) && ToTime(Time[0]) >= ToTime(MyEndTime) && MP[0] != 0)
                    daysintrade = daysintrade + 1;
                
                if (MP[0] == 1 && daysintrade >= TE_Day_close && TE_Day_close > 0 && ToTime(Time[0]) >= 1600)
                    ExitLong(0, Quantity, "ExitLong1", "Long1");
                
                if (MP[0] == -1 && daysintrade >= TE_Day_close && TE_Day_close > 0 && ToTime(Time[0]) >= 1600)
                    ExitShort(0, Quantity, "ExitShort1", "Short1");
                
                if (LongOrder != null && Position.MarketPosition != MarketPosition.Long && ToTime(Time[0]) >= ToTime(MyEndTime))
                    CancelOrder(LongOrder);
                
                if (ShortOrder != null && Position.MarketPosition != MarketPosition.Short && ToTime(Time[0]) >= ToTime(MyEndTime))
                    CancelOrder(ShortOrder);
                
                if (ToTime(Time[0]) >= ToTime(MyEndTime))
                {
                    LongSignal = false;
                    ShortSignal = false;
                }
                
                Print(ShortSignal + "  " + Time[0]);
            }
            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 == "Long1")
                {
                    LongOrder = order;    
                    
                    if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
                        LongOrder = null;
                        
                    if (order.OrderState == OrderState.Filled)
                          LongOrder = null;
                }
                
                if(order.Name == "Short1")
                {
                    ShortOrder = order;    
                    
                    if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
                        ShortOrder = null;
                    
                    if (order.OrderState == OrderState.Filled)
                          ShortOrder = null;
                }
            }​
    Now here is a screenshot of the Print:

    Click image for larger version

Name:	image.png
Views:	92
Size:	29.2 KB
ID:	1293580​As you can see, at 11AM a StopMarket Short order is placed at 2020.0 on GC. Now look at the chart:

    Click image for larger version

Name:	image.png
Views:	39
Size:	42.8 KB
ID:	1293581
    This should have entered Short. Why did it not enter?

    #2
    Hello Lance El Camino,

    Thank you for your post.

    To confirm, you're seeing that the strategy is entering short at this timestamp at 11:00AM however this isn't being reflected on the chart?

    Are there any further messages from TraceOrders in the output further down related to this order, that may indicate if the order was eventually ignored or not submitted? If so, please share the full output.

    Can you open the DataBox so we can see the exact timestamp of the bar you are looking at on the chart to confirm this matches? Please send a screenshot.



    Thank you in advance.
    Gaby V.NinjaTrader Customer Service

    Comment


      #3
      I draw triangles when the orders get placed on the chart and included another chart screenshot below. It matches.

      A stop market order named "Short1" is being submitted at 11AM but it doesn't get filled when price reaches it at the 12PM bar. This should have shown on the chart yet there is no entrance. Here is the rest of the print for that day:
      Click image for larger version

Name:	image.png
Views:	49
Size:	50.0 KB
ID:	1293697
      I also see that the "Long1" order is properly cancelled at 4PM as coded, but the "Short1" order isn't cancelled even though it isn't filled. I notice throughout the entire backtest that the Short orders are exhibiting this behavior but not the Longs. Is it something to do with OnOrderUpdate?

      Click image for larger version

Name:	image.png
Views:	38
Size:	65.1 KB
ID:	1293698
      When I pull up the strategy orders in the analyzer it doesn't show that it was submitted. So it shows submitted in the output but not in the analyzer.
      ​​
      Click image for larger version

Name:	image.png
Views:	38
Size:	177.4 KB
ID:	1293699
      So as you can see, something weird is happening.

      Comment


        #4
        Hello Lance,

        Thank you for your response.

        It looks like your strategy attempted to submit a Buy stop market order and a SellShort stop market order at the same time at 11:00 AM on 8/1/2023. This may have caused it to hit one of the Internal Order Handling Rules that causes a position to be ignored:

        "The strategy position is flat and an order submitted by an enter method (EnterLongLimit() for example) is active and the order is used to open a position in the opposite direction"



        I recommend adding prints to help illustrate exactly what is going on with the strategy. Print the order object in OnOrderUpdate(). Printing the order object in OnOrderUpdate() will allow us to track the progression of the order from submitted, to working, to filled, cancelled, or rejected.

        These tools will let you know what happens to the order. Also make sure TraceOrders is set to true.

        TraceOrders - https://ninjatrader.com/support/help...raceorders.htm
        OnOrderUpdate() - https://ninjatrader.com/support/help...rderupdate.htm

        I also recommend adding prints one line above your conditions that print the values of every variable used in every condition that places an order along with the time of that bar. Also, add a print within the condition after the Enter() method to confirm the condition was triggered and the order should have been placed.

        The prints should include the time of the bar and should print all values from all variables and all hard coded values in all conditions that must evaluate as true for this action to be triggered. It is very helpful to include labels and operators in the print to understand what is being compared in the condition sets.

        This will print to the output window. Backtest the script and when the output from the output window appears save this by right-clicking the output window and selecting Save As... -> give the output file a name and save -> then attach the output text file to your reply.

        I look forward to assisting further. ​
        Gaby V.NinjaTrader Customer Service

        Comment


          #5
          It looks like your strategy attempted to submit a Buy stop market order and a SellShort stop market order at the same time at 11:00 AM on 8/1/2023. This may have caused it to hit one of the Internal Order Handling Rules that causes a position to be ignored:
          It definitely does that and I notice in the print log that the Shorts aren't filling when both are submitted at the same bar yet it doesn't say an order was ignored. I did have the RealTimeErrorHandling set to StopCancelClose so wouldn't I see the cancel in the print? Why does it not show in the Strategy Analyzer Orders log but it shows as submitted in the Output?

          I recommend adding prints to help illustrate exactly what is going on with the strategy. Print the order object in OnOrderUpdate(). Printing the order object in OnOrderUpdate() will allow us to track the progression of the order from submitted, to working, to filled, cancelled, or rejected.
          I have 2 order objects: LongOrder and ShortOrder. So do I add a Print statement inside OnOrderUpdate()? Will this work: Print(LongOrder + " " + ShortOrder + " " + Time[0]); ?
          Also, TraceOrders is set to True.

          I also recommend adding prints one line above your conditions that print the values of every variable used in every condition that places an order along with the time of that bar. Also, add a print within the condition after the Enter() method to confirm the condition was triggered and the order should have been placed.
          I have already done this. I also draw triangles on the chart where this should occur and output the variables to plots. These are working perfectly so the issue has to do with order handling. I just need to see if the Short orders are being ignored. They are second in line in the code so when both Long and Short are entered on the same bar the first one must be remaining. This must be why the backtest has 5 times more Longs than Shorts.

          Comment


            #6
            "The strategy position is flat and an order submitted by an enter method (EnterLongLimit() for example) is active and the order is used to open a position in the opposite direction"​

            This is definitely the case. There are times when both long and short conditions are true so the strategy should have stop market orders for both active at the same time. Are you saying that NinjaTrader can't allow this? We can't have Buy Stop and Sell Stop orders placed at the same time?

            Comment


              #7
              Looks like I need to use the Unmanaged Approach

              Comment


                #8
                Hello Lance El Camino,

                so wouldn't I see the cancel in the print? Why does it not show in the Strategy Analyzer Orders log but it shows as submitted in the Output?
                I'm unable to say with certainty without seeing the output. Specifically printing the order object from OnOrderUpdate() would help illustrate this more clearly. OnOrderUpdate() is called each time an order managed by your strategy changes state. Every order update will have an order.Name you can use to check if this is the long entry or short entry. You could do something like:

                Print(Time[0] + " " + order.Name + ": " + order.State);

                Your current prints aren't descriptive to understand why a condition is evaluating as true or not, since we can't see the actual values being used in the conditions. The prints only print true or false, but do not provide any information on the values that would help us understand why the condition is evaluating as true or false.

                We can't have Buy Stop and Sell Stop orders placed at the same time?
                Using the Managed Approach, no this would not be possible as it is against the internal order handling rules.

                You can use the Unmanaged Approach for more flexibility in terms of order submission and management.

                Below is the Help Guide page on the Unmanaged Approach.



                Please let me know if I can assist further.
                Gaby V.NinjaTrader Customer Service

                Comment


                  #9
                  Thanks! Can you cancel orders in the OnOrderUpdate() method? So if both Long and Short orders are submitted in the same bar and let's say the LongOrder gets filled can I tell the ShortOrder to cancel in OnOrderUpdate()?

                  Comment


                    #10
                    Hello Lance,

                    You can cancel orders in OnOrderUpdate using CancelOrder(), however anytime an order submitted by an enter method is active and the order is used to open a position in the opposite direction your strategy will immediately violate the internal order handling rules and will be ignored. Since the order is ignored it will not get any updates in OnOrderUpdate().

                    https://ninjatrader.com/support/help...ancelorder.htm
                    Gaby V.NinjaTrader Customer Service

                    Comment

                    Latest Posts

                    Collapse

                    Topics Statistics Last Post
                    Started by poplagelu, Today, 05:00 AM
                    0 responses
                    3 views
                    0 likes
                    Last Post poplagelu  
                    Started by fx.practic, 10-15-2013, 12:53 AM
                    5 responses
                    5,407 views
                    0 likes
                    Last Post Bidder
                    by Bidder
                     
                    Started by Shai Samuel, 07-02-2022, 02:46 PM
                    4 responses
                    98 views
                    0 likes
                    Last Post Bidder
                    by Bidder
                     
                    Started by DJ888, Yesterday, 10:57 PM
                    0 responses
                    8 views
                    0 likes
                    Last Post DJ888
                    by DJ888
                     
                    Started by MacDad, 02-25-2024, 11:48 PM
                    7 responses
                    160 views
                    0 likes
                    Last Post loganjarosz123  
                    Working...
                    X