Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Orders are not going NULL

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

    Orders are not going NULL

    Day two using N8 and the problems continue. Not sure why I'm having this one. Hopefully it is just something stupid I'm overlooking.

    1) I'm using unmanaged orders.
    2) Market Replay (using E-mini ES)
    3) Logging whether the order "_buyOrder" is null or not as it progresses through order completion.
    4) Always seems to be null when passing through OnOrderUpdate and OnExecutionUpdate
    4) Mysteriously goes back to being != null when logging from OnBarUpdate


    Sample output
    12/18/2015 6:30:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
    NinjaScript strategy 'testNull/69020941' submitting order
    12/18/2015 6:31:00 AM :: OnOrderUpdate _buyOrder = null
    12/18/2015 6:31:00 AM :: OnOrderUpdate _buyOrder = null
    12/18/2015 6:31:00 AM :: OnOrderUpdate _buyOrder = null
    12/18/2015 6:31:00 AM :: OnOrderUpdate _buyOrder = null
    12/18/2015 6:31:00 AM :: OnExecutionUpdate. Price: 2020.75 Quantity: 1 execution.Order.Name: buyOrder
    12/18/2015 6:31:00 AM :: buyOrder has executed @ 2020.75
    12/18/2015 6:31:00 AM :: Order must of been nulled in OnOrderUpdate
    12/18/2015 6:31:00 AM :: CURRENTLY != NULL... Every min, we check to see if _buyOrder is null.
    12/18/2015 6:32:00 AM :: CURRENTLY != NULL... Every min, we check to see if _buyOrder is null.
    Try the code below..

    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 testNull : Strategy
        {
            // RUN THIS STRATEGY ON ES WITH MARKET REPLAY.  Set to start @ 6:30am (may have to adjust to your timezone)
            //
            private Order _buyOrder = null;
            double tickSize = .25;
            double currentBid;
            double currentOffer;
    
            
            
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                    Description                            = @"RUN THIS STRATEGY ON ES WITH MARKET REPLAY.";
                    Name                                = "testNull";
                    Calculate                            = Calculate.OnBarClose;
                    EntriesPerDirection                    = 1000;
                    EntryHandling                        = EntryHandling.AllEntries;
                    IsExitOnSessionCloseStrategy        = true;
                    ExitOnSessionCloseSeconds            = 30;
                    IsFillLimitOnTouch                    = false;
                    IsUnmanaged = true;
                    MaximumBarsLookBack                    = MaximumBarsLookBack.TwoHundredFiftySix;
                    OrderFillResolution                    = OrderFillResolution.Standard;
                    Slippage                            = 0;
                    StartBehavior                        = StartBehavior.WaitUntilFlat;
                    TimeInForce                            = TimeInForce.Gtc;
                    TraceOrders                            = false;
                    RealtimeErrorHandling                = RealtimeErrorHandling.StopCancelClose;
                    StopTargetHandling                    = StopTargetHandling.PerEntryExecution;
                    BarsRequiredToTrade                    = 0;
                }
                else if (State == State.Configure)
                {
                }
            }
    
    
    
    
    
    
    
    
            protected override void OnBarUpdate()
            {
                if (State == State.Realtime)
                {
                    if (Position.MarketPosition == MarketPosition.Flat && ToTime(Time[0]) > 63000)
                        _buyOrder = SubmitOrderUnmanaged(0, OrderAction.Buy, OrderType.Limit, 1, currentOffer + tickSize, 0, "", "buyOrder");
                    
                    if (_buyOrder == null)
                        P(1,"CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.");
                    else
                        P(1,"CURRENTLY != NULL... Every min, we check to see if _buyOrder is null.");
                }
                
            }
    
            protected override void OnMarketData(MarketDataEventArgs e)
            {
                if (e.MarketDataType == MarketDataType.Bid)
                {
                    currentBid = e.Price;
                }
    
                if (e.MarketDataType == MarketDataType.Ask)
                {
                    currentOffer = e.Price;
                }
            }
    
     
    
    
    
            private void P(int outputWindow, string message)
            {
                if (outputWindow == 1) PrintTo = PrintTo.OutputTab1;
                if (outputWindow == 2) PrintTo = PrintTo.OutputTab2;
                   
                Print(Time[0] + " :: " + message);
            }
    
    
    
        
    
    
    
            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)
            {
                if (_buyOrder == null)
                {
                    P(1, "OnOrderUpdate _buyOrder = null");
                }
                else
                {
                    P(1, "OnOrderUpdate _buyOrder != null");
                    
                    if (_buyOrder == order)
                    {
                        P(1, "try nulling here");
                        if (order.OrderState == OrderState.Filled)
                        {
                            P(1, "Null happening");
                            _buyOrder = null;
                        }
                    }
                }
            }
    
            protected override void OnExecutionUpdate(Cbi.Execution execution, string executionId, double price, int quantity, Cbi.MarketPosition marketPosition, string orderId, DateTime time)
            {
                P(1, "OnExecutionUpdate.  Price: " + price + "   Quantity: " + quantity + "    execution.Order.Name: " + execution.Order.Name);
    
                if (execution.Order.OrderState == OrderState.Filled)
                {
                    if (execution.Order.Name == "buyOrder")
                    {
                        P(1, "buyOrder has executed @ " + execution.Order.LimitPrice);
    
                        if (_buyOrder == null)
                            P(1, "Order must of been nulled in OnOrderUpdate");
                        else
                        {
                            P(1, "Order wasn't nulled in OnOrderUpdate.  Let's null it here");
                            _buyOrder = null;
                        }
                    }
                }
            }
    
            protected override void OnPositionUpdate(Cbi.Position position, double averagePrice, int quantity, Cbi.MarketPosition marketPosition)
            {
            }
    
           
    
            protected override void OnAccountItemUpdate(Cbi.Account account, Cbi.AccountItem accountItem, double value)
            {
            }
    
    
    
        }
    }

    #2
    Any comments about this? I've yet to get this to act like I'd expect (something like NT7). Am I missing something?

    Comment


      #3
      I am looking into this and will get back to you shortly. Thanks for providing the code example.
      MatthewNinjaTrader Product Management

      Comment


        #4
        Thanks for your patience while I reviewed this behavior.

        NT8 has seen an implementation change where you're actually dealing with the internal core order objects and order updates themselves. This has some implicit changes down stream which you need to be aware of, and as a result, will not match NT7 apple to apples.

        Specific to the code example you provided, you are only assigning _buyOrder during OnBarUpdate as you call SubmitOrderUnamanged. However, now with NT8, OnOrderUpdate will actually occur inside of that SubmitOrderUnamanged method. In other words, it is not until the OnOrderUpdate has completed, would that order object exist and be returned.

        This explains why the order is not available until the next on bar update, and you're getting the code executed which prints "CURRENTLY != null..."

        You should be assigning any order objects in the OnOrderUpdate() handler, which will give you the earlierst possible chance for you to catch this order and access it else where:

        Code:
               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)
                {
                    if (_buyOrder == null)
                    {
        				// if the current update order matches the buyOrder signal name
        				if (order.Name == "buyOrder");  
        					_buyOrder = order;  // tie this current order to the order object
        			}
        			
        			// rest of order logic
        Later on, your logic where you assume "Order must of been nulled in OnOrderUpdate", is not exactly correct - the _buyOrder is null because it was not assigned yet, as the order events have not yet completed.

        Again, it is not until the next OnBarUpdate is your _buyOrder object exist, which is explains why it was later "Mysteriously" recovered in OnBarUpdate as you noted.

        I apologize if you missed this change however it is reflected in the Code Breaking Changes under "Strategies, Orders, and Accounts":



        There is also some details on the "OnOrderUpdate" section of the help guide which covers this behavior:


        "OnOrderUpdate() will run inside of order methods such as EnterLong() or SubmitOrderUnmanaged(), therefore attempting to assign an order object outside of OnOrderUpdate() may not return as soon as expected. If your strategy is dependent on tracking the order object from the very first update, you should try to match your order objects by the order.Name (signal name) from during the OnOrderUpdate() as the order is first updated."
        I've attached a modified version of your script which reflects this change to OnOrderUpdate and works to my expectations and produces the output at the bottom of this post - however do let me know if there is something I am missing or if you have any questions on this implementation change.

        3/14/2016 6:30:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
        NinjaScript strategy 'testNull/69540219' submitting order
        3/14/2016 6:31:00 AM :: OnOrderUpdate _buyOrder != null
        3/14/2016 6:31:00 AM :: try nulling here
        3/14/2016 6:31:00 AM :: OnOrderUpdate _buyOrder != null
        3/14/2016 6:31:00 AM :: try nulling here
        3/14/2016 6:31:00 AM :: OnOrderUpdate _buyOrder != null
        3/14/2016 6:31:00 AM :: try nulling here
        3/14/2016 6:31:00 AM :: Null happening
        3/14/2016 6:31:00 AM :: OnExecutionUpdate. Price: 2006.25 Quantity: 1 execution.Order.Name: buyOrder
        3/14/2016 6:31:00 AM :: buyOrder has executed @ 2006.5
        3/14/2016 6:31:00 AM :: Order must of been nulled in OnOrderUpdate
        Attached Files
        MatthewNinjaTrader Product Management

        Comment


          #5
          Thanks much.

          I did read that, but I guess I didn't fully understand. Now it makes sense. Thanks for taking the time to straighten me out.

          Comment


            #6
            I ran your adjusted version of the strategy to make sure I understand what you've done. Unfortunately, I'm still a little fuzzy on something.

            Your output shows the log until 6:31am. What happens if you let it run further for a few more OnBarUpdates? Does it show _buyOrder as being null or != null?

            I'm still showing the _buyOrder as being != null when it is long 1 contract and no open orders. Should I expect that to be the case? Wouldn't it remain null as reported in OnExecutionUpdate after that 1 and only buy order executed and filled and was then set to null?

            Thanks again

            Comment


              #7
              I get "CURRENTLY == NULL... Every min, we check to see if _buyOrder is null" indefinitely on each OnBarUpdate.

              3/14/2016 6:31:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:32:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:33:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:34:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:35:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:36:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:37:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:38:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:39:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:40:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:41:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:42:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:43:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:44:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:45:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:46:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:47:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:48:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:49:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              3/14/2016 6:50:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
              I would expect the order to be null after you set it to null after it has reported as filled.

              Specifically, where are you seeing _buyOrder as 1= null? From your print in OnBarUpdate?

              Your strategy is only checking if the Strategy Position is flat, so if you meant that you are seeing the Account Position Long and no open orders, your SubmitOrder logic is still going to fire, and that order object would then exist again.
              MatthewNinjaTrader Product Management

              Comment


                #8
                Here is what is happening.

                1) OnBarUpdate properly reports _buyOrder == null
                2) _buyOrder is sent and after fill, it is now properly nulling in OnOrderUpdate.
                3) We are long 1 contract
                4) No open orders and no new orders sent (nothing is triggered since the strategy is waiting for our position to be flat)
                5) Each minute, OnBarUpdate is still reporting:

                "CURRENTLY != NULL... Every min, we check to see if _buyOrder is null."

                Here is the full log;;

                CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
                12/18/2015 6:30:00 AM :: CURRENTLY == NULL... Every min, we check to see if _buyOrder is null.
                NinjaScript strategy 'testNull/69020946' submitting order
                12/18/2015 6:31:00 AM :: OnOrderUpdate _buyOrder != null
                12/18/2015 6:31:00 AM :: try nulling here
                12/18/2015 6:31:00 AM :: OnOrderUpdate _buyOrder != null
                12/18/2015 6:31:00 AM :: try nulling here
                12/18/2015 6:31:00 AM :: OnOrderUpdate _buyOrder != null
                12/18/2015 6:31:00 AM :: try nulling here
                12/18/2015 6:31:00 AM :: Null happening
                12/18/2015 6:31:00 AM :: OnExecutionUpdate. Price: 2020.75 Quantity: 1 execution.Order.Name: buyOrder
                12/18/2015 6:31:00 AM :: buyOrder has executed @ 2020.75
                12/18/2015 6:31:00 AM :: Order must of been nulled in OnOrderUpdate
                12/18/2015 6:31:00 AM :: CURRENTLY != NULL... Every min, we check to see if _buyOrder is null.
                12/18/2015 6:32:00 AM :: CURRENTLY != NULL... Every min, we check to see if _buyOrder is null.
                Our strategies should be the same, but just in case, I've attached my latest CS file.


                Thanks
                Attached Files
                Last edited by lookOutBelow; 03-17-2016, 09:48 AM.

                Comment


                  #9
                  Thanks for uploading your code, I see what you mean. There was another point I missed and neglected to mention in my first post ( I also uploaded a version without this point so I see where you confusion is coming from - sorry about that)

                  Your assignment of _buyOrder = SumbitOrderUnmanged() is actually re-assigning that order as soon as it comes out of the OnOrderUpdate/Execution logic, which is after you have nulled it out.

                  Here is what is happening to your code if you were to step through your scenario with a debugger
                  • SubmitOrderUnamanged() is being called from OnBarUpdate
                  • Which fires OnOrderUpdate() within the SubmitOrderUnamanged method
                  • The order is updated through Working to Filled.
                  • During OnOrderUpdate(), you detect that the OrderState == OrderState.Filled
                  • The order object is set to null.
                  • We step out of the OnOrderUpdate() logic and back into OnBarUpdate() which triggered that logic
                  • Since SubmitOrderUnamanged returns an order object, it is returning your _buyOrder object (albeit, the OrderState is filled).


                  In other words, you return the order object after you have already nulled it out.

                  In principle, you should not be doing any sort of Order assignment outside of the order update handlers, since they run asynchronously to the market data events.

                  This is exaggerated in Playback/MarketReplay since order updates happen *immediately* to help ensure repeatability. In Live mode, or forward testing running the Sim101 account, there is an inherent delay in the OnOrderUpdate() logic calling, so the behavior would not always be seen. This is not to say live mode runs synchronously, it is simply that the simulated or live encounter a few milliseconds of delay that is created due to the amount of time it takes to submit an order to the broker/exchange and for that to be reported back to your PC.

                  To completely avoid these issues, any sort of order assignment or nulling of order objects should be done strictly in the order handlers.

                  Once you have a copy of that order, you can, of course, attempt to access in OnBarUpdate if you wanted to e.g., get the Fill Price of an order for some other logic - but when it comes down to assigning and nulling the order, it should only be handled by order handlers
                  Attached Files
                  MatthewNinjaTrader Product Management

                  Comment


                    #10
                    Thanks for taking the time to further clarify. This makes sense to me now.

                    Comment

                    Latest Posts

                    Collapse

                    Topics Statistics Last Post
                    Started by kujista, Today, 06:23 AM
                    0 responses
                    1 view
                    0 likes
                    Last Post kujista
                    by kujista
                     
                    Started by traderqz, Yesterday, 04:32 PM
                    1 response
                    10 views
                    0 likes
                    Last Post NinjaTrader_Gaby  
                    Started by f.saeidi, Today, 05:56 AM
                    1 response
                    4 views
                    0 likes
                    Last Post Jltarrau  
                    Started by Jltarrau, Today, 05:57 AM
                    0 responses
                    4 views
                    0 likes
                    Last Post Jltarrau  
                    Started by Stanfillirenfro, Yesterday, 09:19 AM
                    7 responses
                    52 views
                    0 likes
                    Last Post NinjaTrader_Gaby  
                    Working...
                    X