Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Problem with unmanaged OrderType.StopMarket

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

    Problem with unmanaged OrderType.StopMarket

    Hello,

    I have problem with unmanaged mode and stop orders.

    When I used it, NT8 in backest not buy anything.

    I use amp futures, instrument TF 09-15, 15 minutes.

    If I run strategy without stoporders, NT8 buy orders.

    If I run strategy with stoporders, NT8 don't buy orders.

    See pictures, strategy is in file strategy.cs.

    You must comment/un-comment line 97 for testing.

    Petr
    Attached Files

    #2
    Hello,

    After some preliminary testing, the issue appears to stem from re-using the orderEntry object for more than one entry. When I change the reference on line 97 to a new, unique Order object, I'm seeing the orders placed as expected. Do you see the same after making that change?
    Dave I.NinjaTrader Product Management

    Comment


      #3
      svopex
      With unmanaged orders, you may need to Cancel the previous order if it doesn't fill. Also, you should also "ChangeOrder" if you are updating price or quantity.

      More information can be found here:


      Market orders, by definition, are always completed, so you don't need to go through this overhead (although you should keep it in mind for robustness). But the LIMIT orders stay until filled or cancelled.

      Comment


        #4
        @NinjaTrader_Dave:

        Yes. If I change line 97 to
        Order orderEntry1 = this.SubmitOrderUnmanaged(1, OrderAction.Buy, OrderType.StopMarket, 1, 0, longBreakout, "", GetOrderName("STOP_ORDER"));
        market orders works.

        But I clear orderEntry variable on lines 86-90, by CancelOrder (if position is flat => StopMarket order is not filled).
        I don't understand, why it's don't work.

        In NinjaTrader 7 this works without any problem.
        NinjaTrader7 strategy version is in the attachment.

        Thanks Petr
        Attached Files
        Last edited by svopex; 09-09-2015, 02:27 PM.

        Comment


          #5
          @NJA_MC:
          Thanks for answer, yes, I know about it.
          But I cancel order on the lines 86-90 when position is flat => limit order is not filled.
          In NT7 this work perfect.
          Last edited by svopex; 09-09-2015, 02:27 PM.

          Comment


            #6
            Hummm.... NT8 has made improvements with Unmanaged orders. Certainly, for a market order, you will never need to cancel that so that portion doesn't need to execute. I am wondering if you are destroying the "Order" object before the cancel process is complete. I keep the same Order object until I get the OnOrderUpdate() stating it has been canceled.

            Can you create another Order object when you make the STOPLIMIT order and copy that in place. Remove the "NULL assignment near the cancel"? I am hoping that C# will keep the older Order until the order is canceled and Garbage collection will clear that one.

            It could be that you have destroyed the Order before the "cancel" is completed.

            Comment


              #7
              Since you now have access to the core order objects and events, it's expected that certain scenarios will not match between NT7 and NT8. Specific to what I'm seeing in the NT8 version you posted, you need to make sure you're assigning order objects within OnOrderUpdate. This is because OnOrderUpdate will run inside of your SubmitOrder() calls and therefore those order methods will not return the order object until after it has completed. Whereas, NT7 you were dealing with an interface and the IOrder would have been assigned in OBU as soon as you called.

              If you check the code breaking changes doc, we have some information specifically on how you should be handling which I've copied below

              Strategies, Orders, and Accounts
              Low level access has been provided to allow more flexibility with the information pertaining to trade data.

              • IOrders, IExecution, and IPosition interfaces have all been replaced directly with the corresponding object
              • The signatures of the related NinjaScript events have changed to match the NinjaTrader internal Update events
              • Methods now return and update with the object instance generated, instead of the previously used interface

              Tip: Since NinjaTrader 8 now exposes the direct Order object, rather than an IOrder interface, it is possible to receive null object reference errors if you attempt to access an order object before the entry or exit order method has returned. To prevent these situations, it is recommended to assign your strategies Order variables in the OnOrderUpdate() method and match them by their signal name (order.Name). Please see the example beginning on line #22 below for demonstration of assigning order objects to private variables.
              Code:
              Order myOrder = null;
               
              protected override void OnBarUpdate()
              {         
                 if (Position.MarketPosition == MarketPosition.Flat && myOrder == null)
                    EnterLongLimit(Low[0], "Entry");
                 
                 if (myOrder != null)
                 {
                    Print(myOrder.OrderState);
                    
                    if (myOrder.OrderState == OrderState.Cancelled || myOrder.OrderState == OrderState.Filled)
                       myOrder = null;            
                 }
              }      
               
              protected override void OnOrderUpdate(Cbi.Order order, double limitPrice, double stopPrice, 
                 int quantity, int filled, double averageFillPrice, 
                 Cbi.OrderState orderState, DateTime time, Cbi.ErrorCode error, string comment)
              {      
                 // compare the order object created via EnterLongLimit by the signal name
                 if (myOrder == null && order.Name == "Entry")
                 {
                    // assign myOrder to matching order update
                    myOrder = order;         
                 }
              }
              MatthewNinjaTrader Product Management

              Comment


                #8
                @NinjaTrader_Matthew:

                Thanks for answer.
                Ok, i understand, but I create in OnOrderUpdate(...) stoploss-order and not handle with orderEntry.
                It's a bug, but this is not "core" of this problem .

                I reduce length of code, please see this:
                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.Data;
                using NinjaTrader.NinjaScript;
                using NinjaTrader.Core.FloatingPoint;
                using NinjaTrader.NinjaScript.Indicators;
                using NinjaTrader.NinjaScript.DrawingTools;
                #endregion
                
                namespace NinjaTrader.NinjaScript.Strategies
                {
                	public class Test : Strategy
                	{
                		private Order orderEntry = null;
                			
                		protected override void OnStateChange()
                		{
                			if (State == State.SetDefaults)
                			{
                				Description = @"Test.";
                				Name = "Test";
                				Calculate = Calculate.OnBarClose;
                				IsExitOnCloseStrategy = false;
                				IsUnmanaged = true;				
                			}
                		}
                
                		protected override void OnBarUpdate()
                		{		
                			if (CurrentBar < BarsRequiredToTrade)
                			{				
                				return;
                			}
                				
                			if (Position.MarketPosition == MarketPosition.Flat)
                			{
                				if (orderEntry != null)
                				{
                					this.CancelOrder(orderEntry);
                					
                					Print(orderEntry.OrderState);
                					if (orderEntry.OrderState != OrderState.Cancelled)
                					{
                						throw new Exception("State != Canceled");
                					}
                				}
                				double longBreakout = Close[0] + 10;
                				orderEntry = this.SubmitOrderUnmanaged(0, OrderAction.Buy, OrderType.StopMarket, 1, 0, longBreakout, "", "STOP_ORDER");
                			}
                		}
                	}
                }
                When you show ninjascript output window, strategy write this to this window:
                Cancelled
                Working
                Strategy 'Test': Error on calling 'OnBarUpdate' method on bar 22: State != Canceled
                Firstly CancelOrder cancel the order, order state is "Cancelled".
                Secondly not, orderEntry.OrderState != OrderState.Cancelled after CancelOrder, order state is still "Working". Why?

                This is core of problem.

                Regards Petr




                PS: below is original strategy for NT8 without SL handling. Market order is not filled:
                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.Data;
                using NinjaTrader.NinjaScript;
                using NinjaTrader.Core.FloatingPoint;
                using NinjaTrader.NinjaScript.Indicators;
                using NinjaTrader.NinjaScript.DrawingTools;
                #endregion
                
                namespace NinjaTrader.NinjaScript.Strategies
                {
                	public class Test : Strategy
                	{
                		private Order orderEntry = null;
                		
                		public static string GetOrderName(string s)
                		{
                			return s + "_" + Guid.NewGuid().ToString("N");
                		}		
                			
                		protected override void OnStateChange()
                		{
                			if (State == State.SetDefaults)
                			{
                				Description = @"Test.";
                				Name = "Test";
                				Calculate = Calculate.OnBarClose;
                				IsExitOnCloseStrategy = false;
                				IsUnmanaged = true;				
                			}
                		}
                
                		protected override void OnBarUpdate()
                		{		
                			if (CurrentBar < BarsRequiredToTrade)
                			{				
                				return;
                			}
                				
                			if (Position.MarketPosition == MarketPosition.Flat)
                			{
                				if (orderEntry != null)
                				{
                					this.CancelOrder(orderEntry);
                					orderEntry = null;
                				}
                				if (CurrentBar < 100)
                				{
                					double longBreakout = Close[0] + 10;
                					Draw.Line(this, "STOP" + CurrentBar, -1, longBreakout, 0, longBreakout, Brushes.Black);
                					orderEntry = this.SubmitOrderUnmanaged(0, OrderAction.Buy, OrderType.StopMarket, 1, 0, longBreakout, "", GetOrderName("STOP_ORDER"));
                				}
                				else						
                				{
                					double longBreakout = Close[0] - 5;
                					Draw.Line(this, "MARKET" + CurrentBar, -1, longBreakout, 0, longBreakout, Brushes.Red);
                					orderEntry = this.SubmitOrderUnmanaged(0, OrderAction.Buy, OrderType.Market, 1, 0, 0, "", GetOrderName("MARKET_ORDER"));
                				}							
                			}		
                			if (CurrentBar > 200 && Position.MarketPosition != MarketPosition.Flat)
                			{
                				this.SubmitOrderUnmanaged(0, OrderAction.Sell, OrderType.Market, 1, 0, 0, "", GetOrderName("SELL_ORDER"));
                			}
                		}
                	}
                }
                Last edited by svopex; 09-09-2015, 05:56 PM.

                Comment


                  #9
                  @NJA_MC:

                  Thanks for answer.

                  "NULL assignment" by my opinion cannot destroy object, if NinjaTrader have another reference to this object. "NULL assignment" only clean "pointer" to object, don't destroy object alone.

                  Comment


                    #10
                    Does the code in the top block of your last post represent the most recent version of your code? In your last post, it looks like the code does not take Matthew's points and advice into account. When I run the code as you've shared it, I see the same results as you are seeing, but that is to be expected. When I run the code I've attached to this post, I'm seeing much better results.

                    I've added comments in the attached code to point out a few key items. The first key is that you are checking for a Cancelled order state immediately after cancelling the order. This will be checking the order state before it has actually had a chance to change, and throwing the exception at that time. Just to clarify this further, it can be considered a "race condition." Imagine you have a driver in a car about to race down the road, and you have another person using a stop watch to time the driver. If you tell the driver to "go," then tell the timer to tell you the race results immediately after, the timer will tell you that the driver has not even finished yet, thus he cannot give you the results. The race has to finish before you can see the outcome. The same applies here -- the cancellation request must be sent, received, and processed, then the cancellation confirmation must be sent and received, and then the order state is changed to Cancelled. This cannot all happen in the time it takes to go from one line of code to the next.

                    Instead, it is best practice to assign the Order object within OnOrderUpdate, and if anything needs to be done at the moment the Cancelled order state is entered, it would be best to do this in OnOrderUpdate as well (as in the attached code).
                    Attached Files
                    Last edited by NinjaTrader_DaveI; 09-10-2015, 12:58 PM.
                    Dave I.NinjaTrader Product Management

                    Comment


                      #11
                      Ok, I change program by your instruction, but program below not close order secondly.
                      Second run of "CancelOrder" function didn't call OnOrderUpdate never and order never closed...
                      First run of "CancelOrder" work perfect.

                      Please trace it in visual studio.

                      I use NinjaTrader beta 4 and VS 2015.

                      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.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
                      {
                          public class Test2 : Strategy
                          {
                              private Order orderEntry = null;
                      
                              protected override void OnStateChange()
                              {
                                  if (State == State.SetDefaults)
                                  {
                                      Description = @"Enter the description for your new custom Strategy here.";
                                      Name = "Test2";
                                      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 = 20;
                                      this.IsUnmanaged = true;
                                  }
                                  else if (State == State.Configure)
                                  {
                                  }
                              }
                      
                              protected override void OnBarUpdate()
                              {
                                  if (CurrentBar < BarsRequiredToTrade)
                                  {
                                      return;
                                  }
                      
                                  if (Position.MarketPosition == MarketPosition.Flat)
                                  {
                                      if (orderEntry != null)
                                      {
                                          // this CancelOrder don't in second run close orderentry
                                          // this CancelOrder don't in second run call OnOrderUpdate
                                          this.CancelOrder(orderEntry);
                                      }
                      
                                      if (CurrentBar > 200)
                                      {
                                          this.SubmitOrderUnmanaged(0, OrderAction.Sell, OrderType.Market, 1, 0, 0, "", "myEntry");
                                      }
                                      else if (CurrentBar > 100)
                                      {
                                          this.SubmitOrderUnmanaged(0, OrderAction.Buy, OrderType.Market, 1, 0, 0, "", "myEntry");
                                      }
                                      else
                                      {
                                          double longBreakout = Close[0] + 100;
                                          this.SubmitOrderUnmanaged(0, OrderAction.Buy, OrderType.StopMarket, 1, 0, High[0] + 10 * TickSize, "", "myEntry");
                                      }
                                  }
                              }
                      
                              protected override void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string comment)
                              {
                                  base.OnOrderUpdate(order, limitPrice, stopPrice, quantity, filled, averageFillPrice, orderState, time, error, comment);
                      
                                  if (orderEntry == null && order.Name == "myEntry")
                                  {
                                      orderEntry = order;
                                  }
                      
                                  // This is the key. We are never assuming an order state, but rather are waiting until the OnOrderUpdate() event triggered when the order state = cancelled
                                  if (order.OrderState == OrderState.Cancelled && order.Name == "myEntry")
                                  {
                                      orderEntry = null;
                                  }
                              }
                          }
                      }
                      Last edited by svopex; 09-10-2015, 01:48 PM.

                      Comment


                        #12
                        Thank you -- I'm seeing the issue clearly now. In my debugging, I see the first order go through all order states all the way through Cancelled. Then the second order placed goes through the states up to Working, and seems to stay at Working for the remainder of the strategy.

                        I will continue to dig into this one and get back to you as soon as I have more info to share. I may ask one of our NinjaScript specialists to take a look, as well. Either way, you should hear back with more information soon.
                        Dave I.NinjaTrader Product Management

                        Comment


                          #13
                          @NinjaTrader_Dave: thank you.

                          Additional note:
                          Market order in my last example is never executed.
                          See this part of the code:

                          Code:
                          ...
                          ...
                          ...
                          else if (CurrentBar > 100)
                          {
                              // this line of code is runned, but market order is not executed
                              this.SubmitOrderUnmanaged(0, OrderAction.Buy, OrderType.Market, 1, 0, 0, "", "myEntry");
                          }
                          ...
                          ...
                          ...
                          But I think it's related to the fact that CloseOrder don't work. It's same problem.

                          Comment


                            #14
                            I believe I've identified a bug related to this issue, and our team is currently looking into it. Thank you for bringing this to our attention. I will post back here with any updates.
                            Dave I.NinjaTrader Product Management

                            Comment


                              #15
                              I've got an update for you on this one. NTEIGHT-8791 (CancelOrder() only running once when using Unmanaged order-entry method SubmitOrder()) has been resolved, and it should no longer be an issue in the next build released.
                              Dave I.NinjaTrader Product Management

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by andrewtrades, Today, 04:57 PM
                              1 response
                              8 views
                              0 likes
                              Last Post NinjaTrader_Manfred  
                              Started by chbruno, Today, 04:10 PM
                              0 responses
                              6 views
                              0 likes
                              Last Post chbruno
                              by chbruno
                               
                              Started by josh18955, 03-25-2023, 11:16 AM
                              6 responses
                              436 views
                              0 likes
                              Last Post Delerium  
                              Started by FAQtrader, Today, 03:35 PM
                              0 responses
                              7 views
                              0 likes
                              Last Post FAQtrader  
                              Started by rocketman7, Today, 09:41 AM
                              5 responses
                              19 views
                              0 likes
                              Last Post NinjaTrader_Jesse  
                              Working...
                              X