Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Strategy Order Dispatcher?

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

    Strategy Order Dispatcher?

    Hi. I did a search and couldn't find any suggestions.

    Does a Strategy have a designated Order submission thread "dispatch" queue?
    This would "marshal" a Task<T> onto a single threaded execution queue, and
    be able to wait for the result T, like a return Order object, for example.

    I'm currently using the GUI thread for Order Task executions, but I think it
    needs to be maybe some other available dispatcher for proper synchronization?

    This is for single-threading Orders, which may originate from other
    asynchronous threads.

    Thanks,
    hyperscalper

    #2
    Hello Hyper,

    Thank you for your post.

    A dispatcher is not necessary for using order methods such as EnterLong() or SubmitOrderUnmanaged() from another thread.

    If you are using series information such as the Close series, you can use TriggerCustomEvent() must be used to reliably synchronize the barAgo indexer to the recent current bar being updated. When calling this event, NinjaTrader will synchronize all internal pointers and then call your custom event handler where your user code is located.

    Here is a help guide link demonstrating how TriggerCustomEvent() may be used - https://ninjatrader.com/support/help...ustomevent.htm

    Please let us know if we may further assist.

    Brandon H.NinjaTrader Customer Service

    Comment


      #3
      OK, thanks for that answer but this is what I was planning to post:

      To get the ball rolling, here's how I set up a TaskFactory
      on a thread in the GUI which uses the "CurrentSynchronizationContext". I'm not trying to post
      reusable elegant code here The point of all this is to get Task<T> dispatching
      working on a "safe" Order processing thread, with dispatches from any thread.

      So firstly, I created a static Executor class, defined like this:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;

      /*
      * This class is used to set to the Form's single-threaded GUI thread
      * and we will execute orders over that same thread task queue
      */

      namespace NinjaTrader.NinjaScript.Strategies {
      public class Executor {

      private static TaskScheduler uiTaskScheduler = null;
      private static TaskFactory taskFactory = null;

      public static void setTaskScheduler(TaskScheduler scheduler) {
      if (uiTaskScheduler==null) {
      uiTaskScheduler = scheduler; // don't set it twice
      }
      }

      public static void setTaskFactory(TaskFactory factory) {
      if (taskFactory==null) {
      taskFactory = factory;
      }
      }

      readonly static object mutex = new object();

      public static TaskScheduler getTaskScheduler() {
      lock (mutex) {
      return uiTaskScheduler;
      }
      }

      public static TaskFactory getTaskFactory() {
      lock (mutex) {
      return taskFactory;
      }
      }

      }
      }

      Then, when during execution of a GUI thread creating a Form... I initialized
      it like this. Here I wanted cross thread access to Forms operations; but in this
      post, I'm thinking the same approach can be used to get access to thread safe
      Order operations. (Ignore the fact that this was done from Winforms and not WPF).
      The key here is the next line, which uses "Current Synchronization Context".

      Executor.setTaskScheduler(TaskScheduler.FromCurren tSynchronizationContext());
      // one-time initialization
      // just some notes to self
      // WindowsFormsSynchronizationContext (System.Windows.Forms.dll:
      // System.Windows.Forms) Windows Forms apps will create and install
      // a WindowsFormsSynchronizationContext as the current context for
      // any thread that creates UI controls. This SynchronizationContext
      // uses the ISynchronizeInvoke methods on a UI control, which passes
      // the delegates to the underlying Win32 message loop. (this is what we want)
      // The context for WindowsFormsSynchronizationContext is a single UI thread.

      Executor.setTaskFactory(new TaskFactory(Executor.getTaskScheduler()));
      // now this Executor static method Executor.getTaskFactory can be used
      // everywhere to queue Tasks<T> to the GUI single thread for execution ?
      // it seems to work, by the way...

      Here's how a request with a return result can be executed on the single thread:

      // this is executed on the GUI thread
      private int _getLotSizeImpl() {
      return (int)orderQtySpinner.Value;
      }

      // any thread can call this, and get the return result from the Form control
      public int getLotSize() {

      try {

      Task<int> task = Executor.getTaskFactory().StartNew(() => { // Lambda, be careful
      return _getLotSizeImpl();
      }, CancellationToken.NONE, TaskCreationOptions.NONE, Executor.getTaskScheduler()); // CORRECTION NOTE these 3 additional params are required for correct compiler overload binding

      return task.Result; // caller waits for Task completion; then normal return here

      } catch (Exception ex) {
      print("getLotSize exception: " + ex.StackTrace);
      }
      return 0; // invalid return, error result
      }


      Now, assuming all of this works; and it appears to work well, then why
      can't I use this approach to "hook" onto any Current Synchronization Context
      and set up a TaskFactory ?

      (Caution: the usage
      of Lambda expressions to define the anonymous task requires that parameter variables
      be "captured" as local Task body variables, but this example doesn't send
      any parameters to the function; it just gets a return result.)

      So here's my preliminary idea. I could initialize an Executor in the same way,
      *** while in the context of some NinjaTrader callback *** using
      Executor.setTaskScheduler(TaskScheduler.FromCurren tSynchronizationContext());
      like in OnBarUpdate or whatever; and
      then if that thread was "safe" to call Order operations; then the TaskFactory
      which was set up while in that "current synchronization context" would be
      able to safely single-thread order operations, dispatched onto the same thread
      as the original callback thread, which I assume is always safe to do
      Order operations.

      What do you think about this approach using available C# concurrency framework,
      to set up a TaskFactory which would make Order operations safe from any thread
      within a Strategy ?

      hyperscalper
      Last edited by Hyper; 09-17-2020, 02:59 PM. Reason: technical code correction

      Comment


        #4
        Hello Hyper,

        Thank you for your note.

        The scope of the code goes beyond what NinjaScript would be able to support, however, we would not expect the issue. You would need to test out your idea in order to test out its feasibility.

        As this approach would go outside the context of what we would support, we will leave the thread open for community members to share their insight if they have tried something similar.

        If you have any other inquires, please don't hesitate to open a new thread
        Brandon H.NinjaTrader Customer Service

        Comment


          #5
          Weird, it looks like the space in there can't be edited out in the forum's rendering LOL
          Executor.setTaskScheduler(TaskScheduler.FromCurren tSynchronizationContext());
          but anyway, there isn't a space in there... hyperscalper

          Comment


            #6
            Originally posted by NinjaTrader_BrandonH View Post
            Hello Hyper,

            Thank you for your note.

            The scope of the code goes beyond what NinjaScript would be able to support, however, we would not expect the issue. You would need to test out your idea in order to test out its feasibility.

            As this approach would go outside the context of what we would support, we will leave the thread open for community members to share their insight if they have tried something similar.

            If you have any other inquires, please don't hesitate to open a new thread
            I get it. But can you confirm whether or not NInjaTrader SubmitOrderUnmanaged() is completely
            thread-safe? It seems you were suggesting that it is... and in that case, I don't have to worry?
            I just don't like assuming thread safety anywhere for something as significant as Order operations.
            hyperscalper

            Comment


              #7
              Hello Hyper,

              Thank you for your post.

              Through our testing with different threads, the order submission methods may be performed from any thread. We have not seen cases contrary to this which would imply it is not thread safe.

              Let us know if we may assist further.
              Brandon H.NinjaTrader Customer Service

              Comment


                #8
                Originally posted by NinjaTrader_BrandonH View Post
                Hello Hyper,

                Thank you for your post.

                Through our testing with different threads, the order submission methods may be performed from any thread. We have not seen cases contrary to this which would imply it is not thread safe.

                Let us know if we may assist further.
                Thanks for that, but it was not a guarantee of thread safety. The concept of
                thread safety is way too broad; and I'm not talking about multiple simultaneous
                usages of the Order facility in a "concurrent" fashion; since I think that may be
                a recipe for disaster. I'm just talking about the "owning thread" for Order
                executions; and whether there is a proper "dispatch" thread for Orders or not.

                I'm going to continue to invoke
                Order operations from a "single thread" and to make sure they are strictly serially
                executed in an effort to avoid any Order issues. I was just trying to figure out whether
                there was a preferred Order dispatcher thread; and it sounds like you're saying
                there really isn't.

                hyperscalper

                Comment


                  #9
                  Hello Hyper,

                  Thank you for your inquiry.

                  NinjaTrader does not have a specific order dispatcher that may be used. The Managed and Unmanaged order entry methods could be used to submit orders from other threads.

                  Please let us know if we may further assist.
                  Brandon H.NinjaTrader Customer Service

                  Comment

                  Latest Posts

                  Collapse

                  Topics Statistics Last Post
                  Started by funk10101, Today, 12:02 AM
                  1 response
                  11 views
                  0 likes
                  Last Post NinjaTrader_LuisH  
                  Started by GLFX005, Today, 03:23 AM
                  1 response
                  6 views
                  0 likes
                  Last Post NinjaTrader_Erick  
                  Started by nandhumca, Yesterday, 03:41 PM
                  1 response
                  13 views
                  0 likes
                  Last Post NinjaTrader_Gaby  
                  Started by The_Sec, Yesterday, 03:37 PM
                  1 response
                  11 views
                  0 likes
                  Last Post NinjaTrader_Gaby  
                  Started by vecnopus, Today, 06:15 AM
                  0 responses
                  1 view
                  0 likes
                  Last Post vecnopus  
                  Working...
                  X