• If this is your first visit, you will have to register before you can post. To view messages, please scroll below and select the forum that you would like to visits. Questions? Be sure to check out the Forum FAQ.

Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Strategy limit and stop orders respect new prices set in ChartTrader or SuperDOM

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

    Strategy limit and stop orders respect new prices set in ChartTrader or SuperDOM

    I'm writing a strategy that maintains limit and stop orders. I'd like the strategy to co-operate with the interactive user. If the user moves the live orders then I'd like the strategy to know about it. This way the strategy could have a couple of different policies for future movement of the orders such as:
    a. Maintaining the delta distance between the price the strategy wants the price and where the user wants it
    b. Or instead the strategy no longer moves the orders ( with a further option that if the user drops the order at the same price that the strategy wants then the strategy again resumes moving it ).
    Without the ability for the strategy to know if a user moved the order I can't be sure of a way to program this. I thought of maintaining some price history and comparing values between Order.LimitPrice, where the strat last set it, where the strat wants it this time, etc. But even if I think I've worked that out there's a couple of things that give me pause: 1, it's complicated logic and 2, I'm not sure if it be introducing a race condition. For example, is a query to Order.LimitPrice in an OnBarUpdate gauranteed to be the price that's already been received by the exchange and is showing in the NT UI? There could be network congestion that causes setting it to be delayed. That's why I'm more confident about a solution to this that involves using OnOrderUpdate. If the OrderUpdate method provided a flag to indicate if the update was caused by user or the strategy then I think it would be a more straight forward implementation.
    Last edited by Brillo; 02-23-2020, 11:11 AM.

    #2
    Hello Brillo,

    Strategies are not intended for manual interaction and the Atm Strategy methods were implemented to automate the entry but allow the user to manually intervene with the exits.
    https://ninjatrader.com/support/help...gy_methods.htm

    Set methods called from an NS strategy also will also snap back to the strategy set price on each tick, and any order methods called would set the price of an order and may undo the users changes.

    In your script, you can monitor the order of prices and use variables to track the price to know if this has changed and OnOrderUpdate() would also update when the order is manually modified with a ChangePending OrderState. So either approach would work.

    With either approach, the Order object assigned from OnOrderUpdate() will always be the object you want to work with and not the object returned from an order method call. This is shown in the help guide on the OnOrderUpdate() page and on the Order page. That Order object will continuously be up-to-date.
    https://ninjatrader.com/support/help...rderupdate.htm
    https://ninjatrader.com/support/help.../nt8/order.htm



    Chelsea B.NinjaTrader Customer Service

    Comment


      #3
      I'm simply asking for a feature that the OnOrderUpdate callback have a flag that indicates if the update is the result of user interaction or from the strategy itself. I feel that would greatly help with the coding. Actually my preference would be for the order entry, order exit and unmanaged api for submitting orders to provide for a "user object" to be passed in. To the api implementation this is simply .NET type Object. The OnOrderUpdate would then provide this back to the user script. I can't over emphasis how useful this is to correlating orders with their responses in a simple object oriented way that avoids the need to add lookup tables and manage state ( which leads to bugs and extra code). Further it addresses this particular concern as a null user object in the OnOrderUpdate could easily be used by the script author as an indication that the order state change event occurred outside the script and is presumably the result of a user interaction. It would be very simple to add this feature to the managed api for order entry. Would you please create a feature request for this?
      Last edited by Brillo; 02-24-2020, 09:58 AM.

      Comment


        #4
        Hello Brillo,

        I will submit a feature request on your behalf for a property in OnOrderUpdate() that marks if an order change was triggered manually.

        Once I have a tracking ID for this request I will post in this thread for future reference.

        You have mentioned the API. Did you want this internally in NinjaScript in OnOrderUpdate(), or did you want this in the API (Application Programming Interface) that provides an interface to external applications?
        https://ninjatrader.com/support/foru...626#post793626
        Chelsea B.NinjaTrader Customer Service

        Comment


          #5
          Thank you Chelsea. I think that the manual order change flag will help.

          The other request is for the managed order API and corresponding OnOrderUpdate parameters to offer a user object of type Object.
          For example:

          Code:
                  public Order EnterLongLimit(double limitPrice, Object userObject)
          
          // SEE NEW userObject parameter added to the end ==================>
                  protected virtual void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string comment, Object userObject)
                  {
                      // now I may downcast the userObject to what I know it to be
                  }

          The NT API implementation would simply forward the userObject that is passed to EnterXXX back into OnOrderUpdate.
          I can't over emphasize how greatly this will help in correlating OnOrderUpdate responses to user script state.
          Last edited by Brillo; 02-25-2020, 09:18 AM.

          Comment


            #6
            Hello Brillo,

            I have received tracking ID# SFT-4667 for this request for an OnOrderUpdate() property to determine if an order change was triggered manually.

            As with all feature requests, interest is tracked before implementation is considered, so we cannot offer an ETA or promise of fulfillment. If implemented, it will be noted in the Release Notes page of the Help Guide.

            Release Notes — https://ninjatrader.com/support/help...ease_notes.htm


            When using the API to allow an external application to interface with NinjaTrader, orders are submitted through the Command method.
            https://ninjatrader.com/support/help.../functions.htm
            https://ninjatrader.com/support/forum/forum/ninjatrader-8/strategy-development/100199-orders-are-not-displayed-in-chart?p=793626#post793626


            To find orders the Orders method is called which returns all order ids for an account.

            The OnOrderUpdate method is not available to the API and is an internal method for NinjaScript Strategies compiled in NinjaTrader.


            That said, in an internally compiled NinjaScript Strategy never use the Order object returned by an order method in NinjaScript.

            Always use the Order object (order) that is provided by OnOrderUpdate().
            There are two examples of this is in the help guide.
            https://ninjatrader.com/support/help...rderupdate.htm
            https://ninjatrader.com/support/help.../nt8/order.htm
            Chelsea B.NinjaTrader Customer Service

            Comment


              #7
              Hi Chelsea,
              Thank you for that feature request and tracking number for OnOrdrUpdate property to distinguish order change triggered by user or by strategy.
              With regard to the other request for the OnOrderUpdate method to carry a user object, I’m sorry I’ve confused you. I will try to clarify.
              The external order submission api that you referenced has nothing to do with what I’m asking for.

              “The OnOrderUpdate method is not available to the API and is an internal method for NinjaScript Strategies compiled in NinjaTrader.”

              Yes this is the api I’m talking about. To me this is called a programming api.

              The OnOrderUpdate is a part of the NinjaScript libraries exposed for script writers to use. Semantics aside, you pointed out the reason why my request for a user object passed to this method is so important: We can’t use the Order object returned by the EntryXXX and ExitXXX methods.
              I’m not sure why we can’t use them but I take it on faith not to. (Makes me wonder why the methods return Order then ).

              Assume for a moment that we could use these Order objects being returned. If that was the case then there would be no need for the userObject facility that I’ve asked for. We could simply use the Order object returned and associate that object with the particular functionality in the script ( rules and such ) that was responsible for that Order. But we can’t. We have to use this asynchronous OnOrderUpdate method. When that method is called as a result of some Entry or Exit order method being called, the program’s call stack for the call to Entry or Exit is long gone. The only possible way to associate the Order received in the OnOrderUpdate with the script/rules that caused it is to use the Order.Name property.

              Order.Name for order identification is useful only in simple scripts. The reason for my request is to enable the composition of large trading programs. NinjaScipt will be a lot more powerful. You may not appreciate how powerful such a small thing can be. I will try to explain with an example.

              Think of a more complicated script that is a single “Master” trading strategy that is itself a class derived from Strategy. The Master strategy is composed of many smaller trading algorithm objects that I’ll call “mini” strategies. The mini strategy objects each implement their own trading rules that are separate and distinct from each other. They’re not derived from Strategy but instead each hold a reference back to the “Master” strategy so that they can place Enter and Exit orders through the Master. The “Master” strategy forwards calls from its OnBarUpdate to each mini strategy so that the mini can apply its own rules to the bar series and in turn calls back through the Master to place orders and learn about market position. This design partitions the code so that each set of rules lives in its own space. It’s a good design for large algos that use many rules and data series.

              Now, we want to combine all the signals from these “mini” strategies such that when the position is flat and the 1st one decides to enter a trade, that 1st one places the order. If the trade is open from the 1st (position exists ) and another “mini” strategy wants to place an order, it uses the same order name and the managed order entry system doesn’t send it. Good. This is desirable as it controls the allocation of the position. This is the reason we want to combine strategies into one master strategy composed of several “mini” strategies – so that we can limit the orders. If this requirement was not needed we could simply code each mini strategy as a separate Ninja Strategy and run them separately. But then we’d over trade our account. We would not be able to produce backtests that show the results of the composite master strategy.

              But it IS the requirement I say many of us have ( or should have ).

              Given this requirement and it’s solution of using Order.Name for containing and avoiding overtrading, a problem arises:
              Using the same order names for all the mini strategies means that we can’t use the order names to identify which “mini” strategy that the order is for in the call to OnOrderUpdate.

              This is the reason I’m asking for a userObject so that the “mini” strategy can pass itself as a UserObject. In OnOrderUpdate we can down cast the UserObject back to what it is for or even pass the OnOrderUpdate method parameters directly to it through a common interface shared by all of the mini strategies.

              If you can imagine for a moment that the UserObjects all implement an interface that has a method that looks just like OnOrderUpdate. Then in the Master strategy’s NinjaTrader OnOrderUpdate will call the OnOrderUpdate method on the user object. There’s no need to perform a search for the userObject in some dictionary using a string. There's no dictionary needed. There’s no state management.

              I hope the pseudo code in the following block makes it clear. Remember, all of this code is stuff we write, not NinjaTrader development. All they need to do is provide for the UserObject to pass from EnterLong to OnOrderUpdate. This example is how that UserObject mechanism should be used.

              Code:
              Interface IHandleOnOrderUpdate{
              void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string comment);
              }
              
              Interface IHandleOnBarUpdate{
              void OnBarUpdate();
              }
              
              Class MyMiniStrat1 : IHandleOnOrderUpdate, IHandleOnBarUpdate
              {
                  Strategy strategyMaster; // back reference to a ninja strategy.
                  public MyMiniStrat1(Strategy strategy){ strategyMaster = strategy; }
              
                  // IHandleOnBarUpdate .  Master strategy forwards calls here
                  public void OnBarUpdate()
                  {
                      if(strategy.Close[0] < strategy.Close[1])
                 strategyMaster.EnterLong(this); // this is the UserObject
                  }
              
                 // IHandleOnOrderUpdate...
                 // calls to here are forwarded from the MasterStrategy. Do something useful for the MiniStrat here!
                 protected void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string comment)
                {
                }
              
              public class MasterStrategy
              {
                 protected MyMiniStrat1 mini1;
                 protected MyMiniStrat2 mini2;
              
                 protected void OnStateConfigure()
                 {
                    mini1 = new MyMiniStrat1(this);
                    mini1 = new MyMiniStrat2(this);
                 }
                 protected override void OnBarUpdate()
                 {
                 // give the mini strats their chance to trade…
                 mini1.OnBarUpdate();
                 mini2.OnBarUpdate();
                 }
              
              // The new OnOrderUpdateMethod carries the userObject parameter through from the original call to EnterLong(this);
                 protected override void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string comment, Object userObject)
                 {
              // Where's the MyMiniStratX ? HERE IT IS!!!!
                    IHandleOnOrderUpdate miniStrategyOnOrderUpdate = userObject as IHandleOnOrderUpdate;
                    if(miniStrategyOnOrderUpdate != null)
                              miniStrategyOnOrderUpdate.OnOrderUpdate(order, limitPrice, stopPrice, quantity, filled, averageFillPrice, orderState, time, error, comment);
                 }
              }
              It’s also cleaner than using type String (the order name) to identify. Order.Name string use still requires some lookup table or switch statement to find the mini strategy it belongs to. In the implementation I’m asking for to be inside the NinjaScript library there’s no lookup table needed ( other then ones that already exist to handle asynchronous request responses to the servers ).
              If you’re not understanding this then I’d like to have a phone conference with you and some members of your staff. It may be that I’m not explaining it well.

              I’ve worked on large systems ( over ˝ million lines of code ) with 12 developers and architects. We had a similar problem to solve and we did it with this pattern of the UserObject in the callback. It works beautifully.

              If all of this example code seems too large and complicated just know one thing: The only thing that NinjaTrader development needs to provide is the passing of the UserObject from the Entry/Exit Order methods to OnOrderUpdate. They don't need to implement anything else in the example code. That's for us NinaScript strategy authors to do.
              Last edited by Brillo; 02-27-2020, 06:13 PM.

              Comment


                #8
                Hello Brillo,

                As a heads up, NinjaTrader does actually have an API in the sense of the word interface. As in this allows an external program to interface with NinjaTrader.

                For inquiries about the API our future replies will directed to the API section of the help guide for interfacing with NinjaTrader using the unamanged or managed dll approach and API/ATI functions. This would be instead of an internally compiled script like NinjaScript or like Easy Language for TradeStation (which also has a separate API).

                From my understanding, due to the nature of how information is transmitted to a connection adapter and how order information is provided to subscriber threads, the order object returned from an order method call is not the actual order that is updated. In NinjaTrader this was handled by having an IOrder object that is updated by the Order object, but for NinjaTrader 8 the developers were attempting to simply this and prevent other issues that can arise with this.

                I am happy to submit a feature request for order methods to be voids and not return an order object.
                I will also submit a feature request for the development to consider allowing the instance of the strategy to be passed as a parameter to an order method as a user object that is also provided as a parameter to OnOrderUpdate().
                Chelsea B.NinjaTrader Customer Service

                Comment


                  #9
                  Originally posted by NinjaTrader_ChelseaB View Post
                  As a heads up, NinjaTrader does actually have an API in the sense of the word interface. As in this allows an external program to interface with NinjaTrader.

                  For inquiries about the API our future replies will directed to the API section of the help guide for interfacing with NinjaTrader using the unamanged or managed dll approach and API/ATI functions. This would be instead of an internally compiled script like NinjaScript or like Easy Language for TradeStation (which also has a separate API).

                  Again, that API for the unmanaged/managed dll and API/ATI functions has nothing to do with what I'm talking about. Please don't direct us to that.

                  Originally posted by NinjaTrader_ChelseaB View Post
                  From my understanding, due to the nature of how information is transmitted to a connection adapter and how order information is provided to subscriber threads, the order object returned from an order method call is not the actual order that is updated. In NinjaTrader this was handled by having an IOrder object that is updated by the Order object, but for NinjaTrader 8 the developers were attempting to simply this and prevent other issues that can arise with this.

                  Okay.

                  Originally posted by NinjaTrader_ChelseaB View Post
                  I am happy to submit a feature request for order methods to be voids and not return an order object.

                  Don't bother with that. It will break existing user ninjascripts unless the methods are overloaded with different parameter lists, which brings us back to what I'm talking about...

                  Originally posted by NinjaTrader_ChelseaB View Post
                  I will also submit a feature request for the development to consider allowing the instance of the strategy to be passed as a parameter to an order method as a user object that is also provided as a parameter to OnOrderUpdate().

                  Thank you but to be perfectly clear, do not specify that the type of the parameter passed must be of type Strategy. The way you worded it "instance of the strategy" implies this and that is not at all what is wanted. The type of the userObject must be of type System.Object. It's more clear to simply state it the way I have here:
                  Provide a parameter on all of the Order placement methods, both managed and unmanaged that is of type System.Object. Further provide that the reference to this object be passed to the OnOrderUpdate method for Order updates associated with the Order that was created to satisify the call to the Order placement method.
                  For example,
                  Code:
                  public void EnterLong() // is overloaded with System.Object so we have both the original public EnterLong() and the new one:
                  public void EnterLong(Object userObject);
                  // Apply the same to all order methods.
                  Finally add the Object to the signature of the OnOrderUpate so that the Object can be passed back as described:
                  Code:
                  protected override void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string comment, Object userObject)

                  Thank you Chelsea!

                  Comment


                    #10
                    Hello Brillo,

                    In your sample code you have:

                    strategy.EnterLong(this); // this is the UserObject

                    In this scope, 'this' refers to the class instance which you have being supplied to EnterLong().

                    May I have you clarify your usage of 'this' being supplied to EnterLong()?
                    Chelsea B.NinjaTrader Customer Service

                    Comment


                      #11
                      Originally posted by NinjaTrader_ChelseaB View Post
                      Hello Brillo,

                      In your sample code you have:

                      strategy.EnterLong(this); // this is the UserObject

                      In this scope, 'this' refers to the class instance which you have being supplied to EnterLong().

                      May I have you clarify your usage of 'this' being supplied to EnterLong()?
                      Sure,

                      To review, here's the code:
                      Code:
                      class MyMiniStrat1 : IHandleOnOrderUpdate, IHandleOnBarUpdate
                      {
                          Strategy strategyMaster; // back reference to a ninja strategy.
                          public MyMiniStrat1(Strategy strategy){ strategyMaster = strategy; }
                      
                          // IHandleOnBarUpdate .  Master strategy forwards calls here
                          public void OnBarUpdate()
                          {
                              if(
                      strategy
                      Master.Close[0] <
                      strategy
                      Master.Close[1]) strategyMaster.EnterLong(this); // this is the UserObject } // IHandleOnOrderUpdate... // calls to here are forwarded from the MasterStrategy. Do something useful for the MiniStrat here! protected void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string comment) { } }
                      This class, MyMiniStrat1 does NOT derive from the Ninjascript.Strategy class. Instead it holds a reference to it. The NinjaScript Strategy I call the Master strategy in the full example earlier in this thread creates an instance of MyMiniStrat1 and passes a reference to itself (the this reference) to the constructor of the MyMiniStrat1. MyMiniSTrat1 calls that reference strategyMaster. I now see that I did NOT use the strategyMaster name for the call to EnterLong in the original posting of this code. I went back and edited that to correctly use the reference name strategyMaster. I hope that clears up the misunderstanding.
                      .
                      FInally, it should now be clear that the this reference in
                      Code:
                                    
                      strategyMaster.EnterLong(this); // this is the UserObject
                      is not the strategy. It is a reference to itself the MyMiniStrat1, a plain old C# object that a user wrote.

                      MyMiniStrat1 implements the IHandleOnOrderUpdate so that later, when the MasterStrategy receives the order update event from the NT strategy framework, MasterStrategy can downcast the Object to IHandeOnOrderUpdate and can then call OnOrderUpate on it.


                      The order of the calls would look like this:

                      1. MasterStrategy.OnBarUpdate
                      2. mini1.OnBarUpdate()
                      3. strategyMaster.EnterLong(this);// where "this" is MyMiniStrat1, not MasterStrategy or Strategy
                      4. MasterStrategy.OnOrderUpdate
                      and in OnOrderUpdate we can downcast Object to IHandleOnOrderUpdate and call OnOrderUpdate on it. In this case the object behind that interface is actually the MyMiniStrat1:
                      5. mini1.OnOrderUpdate()

                      Viola! The orders are glued together with the objects/rules that created the orders!

                      FInally, This request came up as a sort of side bar mention in the original post about coordinating user orders with strategy orders. This facility that I'm asking for could be used to solve that problem by simply checking for a null UserObject in OnOrderUpdate and interpreting that as an OrderUpdate for a user action. But this UserObject mechanism goes way beyond that in terms of offering us the ability to put together large programs. I feel that this thread deserves to be separate from that one and have it's own title. This issue is important.
                      Last edited by Brillo; 02-27-2020, 07:47 PM.

                      Comment


                        #12
                        Hello Brillo,

                        I have forwarded the code you want implemented to the developers.

                        It will be up to development to decide if or when this may be implemented.
                        Chelsea B.NinjaTrader Customer Service

                        Comment


                          #13
                          Thank you Chelsea. If possible I'd like the opportunity to explain it to them.

                          Comment


                            #14
                            Hello Brillo,

                            Thank you for your patience.

                            I have created a feature request on your behalf regarding changes to order methods. This request is being tracked under the number SFT-4673.

                            As with all feature requests, interest is tracked before implementation is considered, so we cannot offer an ETA or promise of fulfillment. If implemented, it will be noted in the Release Notes page of the Help Guide.

                            Release Notes — https://ninjatrader.com/support/help...ease_notes.htm

                            Please let us know if we may be of further assistance to you.
                            Kate W.NinjaTrader Customer Service

                            Comment


                              #15
                              Okay. Thank you!

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by mbcmbc, Yesterday, 11:01 PM
                              0 responses
                              1 view
                              0 likes
                              Last Post mbcmbc
                              by mbcmbc
                               
                              Started by morrnel, Yesterday, 09:39 PM
                              0 responses
                              1 view
                              0 likes
                              Last Post morrnel
                              by morrnel
                               
                              Started by Thesuccesfulinvestor, Yesterday, 09:07 PM
                              0 responses
                              6 views
                              0 likes
                              Last Post Thesuccesfulinvestor  
                              Started by WestonMicah, Yesterday, 12:44 AM
                              1 response
                              17 views
                              0 likes
                              Last Post koganam
                              by koganam
                               
                              Started by xmanjames, Yesterday, 04:22 PM
                              0 responses
                              11 views
                              0 likes
                              Last Post xmanjames  
                              Working...
                              X