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

Adopting Working Orders

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

    Adopting Working Orders

    Hi,

    I've been failing to get my strategy to adopt an existing account order, and am also seeing some odd behaviour. Connecting to FXCM, if there is an existing working order, I would like the strategy to begin managing it. The behaviour I think I'm seeing is that the strategy will only successfully map the order if it was generated by the strategy whilst it is currently loaded in memory.

    Let's say I have a sole Limit Order active on the account, in a 'working' state. If I disable the strategy and then re-enable it in the main NT window, it successfully maps the order and begins managing it. If I right click on the chart and reload the ninjascript (F5), it succesfully maps the order and begins managing it.

    However, if I do both (disable, refresh, enable), it submits a new working order to the account matching the existing one, resulting in two identical working orders on the account. Likewise, if I delete the strategy in the main NT window and then add it to the chart again, it submits a second working order.

    The code below is successfully detecting the working order under all conditions, and also submits it historically on the same bar as the original with all the same details. However, NT only maps the order to the existing order in the situations mentioned above. If the strategy is deleted and re-added to the chart, then although the code identifies the order and submits it historically, NT fails to map it to the existing order and instead submits as a new one.


    public class EntryTest : Strategy
    {

    private Order existingOrder;
    private Order matchOrder;

    protected override void OnStateChange()
    {
    if (State == State.SetDefaults)
    {
    Description = @"Enter the description for your new custom Strategy here.";
    Name = "EntryTest";
    Calculate = Calculate.OnBarClose;
    EntriesPerDirection = 1;
    EntryHandling = EntryHandling.AllEntries;
    IsExitOnSessionCloseStrategy = true;
    ExitOnSessionCloseSeconds = 30;
    IsFillLimitOnTouch = false;
    MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
    OrderFillResolution = OrderFillResolution.Standard;
    Slippage = 0;
    TimeInForce = TimeInForce.Gtc;
    TraceOrders = false;
    RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
    StopTargetHandling = StopTargetHandling.PerEntryExecution;
    BarsRequiredToTrade = 1;
    IsInstantiatedOnEachOptimizationIteration = true;

    IsAdoptAccountPositionAware = true;
    StartBehavior = StartBehavior.ImmediatelySubmit;

    }
    else if (State == State.Configure)
    {
    IsUnmanaged = true;
    var myAcct = Account.All.FirstOrDefault(x => x.Name == this.Account.Name); //identify the working order
    foreach (Order order in myAcct.Orders)
    {
    if (order.Instrument.FullName == Instrument.FullName)
    {
    if (order.OrderState == OrderState.Working)
    {
    existingOrder = order;
    }
    }
    }
    }
    }

    protected override void OnBarUpdate() //submit the order on the same bar as the original
    {
    if (existingOrder != null && State == State.Historical)
    {
    if(CurrentBar > BarsRequiredToTrade && Time[0] <= existingOrder.Time && Time[0].Add(Time[0] - Time[1]) > existingOrder.Time)
    {
    Print (existingOrder.ToString());
    matchOrder = SubmitOrderUnmanaged(0, existingOrder.OrderAction, existingOrder.OrderType, existingOrder.Quantity, existingOrder.LimitPrice, existingOrder.StopPrice, existingOrder.Oco, existingOrder.Name);
    Print (matchOrder.ToString());
    }
    }
    }
    }
    }
    Attached Files

    #2
    Hello beastment,

    Thanks for opening the thread and providing a concise example of what you are trying to do.

    I would highly suspect that your code to intercept live working orders is interfering with the ImmediatelySubmit StartBehavior. ImmediatelySubmit will handle this behavior for you.

    When we enable strategies they first process historical data to generate a strategy position and the orders that would have been generated by the strategy. What happens next is determined by the Start Behavior.

    Immediately Submit will use the order information from the calculated historical data to see if those orders match any live working orders on the account. If the strategy orders generated by the historical data match the live working orders, the strategy will resume them. This behavior assumes the account position is where you want it when you enable the strategy. The strategy will then submit all subsequent orders generated with realtime data to the live account. This is what your code looks like it is trying to accomplish which could cause the second order from firing.

    I've attached an example Unmanaged strategy that can be used as an example of a working ImmediatelySubmit strategy. You will also have to update order references in upon State.Realtime. More information on StartBehaviors is publicly available in the help guide, and I've also linked to documentation on updating Order objects. This must be followed for Unmanaged strategies as well.

    Transitioning Order objects - https://ninjatrader.com/support/help...storicaltolive

    Start Behaviors - https://ninjatrader.com/support/help..._positions.htm

    Please let us know if you have any additional questions.
    Attached Files
    JimNinjaTrader Customer Service

    Comment


      #3
      Thanks for your prompt and detailed response Jim. I take your point about the interception potentially causing trouble, and have had a good look through the sample you sent through.

      The problem is that the strategy I'm working on does not generate trades in response to chart data. Rather, it's more of an interface. When enabled, it places buttons on the chart and information etc, and when the user presses one of those buttons it enters or exits orders accordingly. Orders are placed in response to user actions (clicking a button), not chart data.

      As such, it is not known in advance whether there are any orders on the account, at least not simply by looking at the chart data. So, I can't simply submit an order on the relevant bar, because unless I query the account I don't even know if there is an order, or what price and quantity the order might have been. Hence me trying to identify any existing orders on the account first so that I can get the details of those, and then submitting them historically to try and get the strategy to start managing them.

      As mentioned, the odd behaviour is that it all works perfectly so long as I'm just enabling/disabling the strategy or refreshing it from the chart. It's only if I delete the strategy and then add it back to the chart (or if I have to reconnect as it turns out) that I run in to problems.

      Any other ideas?

      Comment


        #4
        Hello beastment,

        There will only be so much I could advise to work around the current Start Behaviors so you are getting the right behavior you are looking for. Since what you are doing is outside of how we describe to use the Start Behaviors and we don't offer a supported means to control manual submissions from NinjaScript strategies, this starts to fall into the "unsupported" category.

        To give some further direction that may lead you to a resolution, I may suggest adding a single tick data series to the script and then having your script take either of the following approaches when a button is pressed:
        • Use a bool to signal an order to be submitted on that single tick data series. The information used to submit the order can then be saved to a file and then parsed on the next run of the strategy. The strategy should then use this information to submit the order on the same historical bar that was noted. The virtual historical order should then be matched with the live working order.
        • Record as much information about the current tick and the order submission when the button is pressed and submit the order immediately. Save this information to file and use it to recreate the submission historically. This should also recreate the order submission as if the strategy has submitted it on its own.


        I'll leave this thread open ended if other clients have had experience writing a strategy that controls manual submissions and can recapture control after reloading the strategy or adding a fresh instance.
        JimNinjaTrader Customer Service

        Comment


          #5
          Thanks for those suggestions Jim, I was thinking along the same lines myself.

          However, I've done a little more testing with this, and I think it is pointing to an issue with how NT maps the orders. I'll try to keep it in the scope of what would be supported this time. No trade intercepts, and no manual placement of orders outside the strategy.

          Steps to replicate:

          Take the following very simple code below (also attached). Create a 1-minute chart with just 10 bars on it, set the entryMinute variable to a few minutes in the future, and apply the strategy to the chart. Wait a couple of minutes for it to place the order in realtime at your specified minute. Now, after a couple more minutes delete the strategy from the main NT window, add it back to the chart again, and it will fail to pick up the (now historical) order and instead submit a new live one.

          As with the previous examples, if the strategy is just disabled or reloaded, then the strategy maps the order as intended and does not submit a new order. But if the strategy is deleted rather than disabled, it fails to map. Also, any filled orders are mapped just fine, it's only working orders that have the issue.

          Is there any way then to have a strategy map an existing working order? The UnmanagedTemplate that you sent through actually shows the same behaviour (I had to tweak it a little to get it to run).

          public class EntryTest2 : Strategy
          {

          private Order myOrder;
          private int entryMinute = 37; //set this to a few minutes in the future before enabling the strategy

          protected override void OnStateChange()
          {
          if (State == State.SetDefaults)
          {
          Description = @"Enter the description for your new custom Strategy here.";
          Name = "EntryTest2";
          Calculate = Calculate.OnBarClose;
          EntriesPerDirection = 1;
          EntryHandling = EntryHandling.AllEntries;
          IsExitOnSessionCloseStrategy = true;
          ExitOnSessionCloseSeconds = 30;
          IsFillLimitOnTouch = false;
          MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
          OrderFillResolution = OrderFillResolution.Standard;
          Slippage = 0;
          TimeInForce = TimeInForce.Gtc;
          TraceOrders = false;
          RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
          StopTargetHandling = StopTargetHandling.PerEntryExecution;
          BarsRequiredToTrade = 1;
          IsInstantiatedOnEachOptimizationIteration = true;

          IsAdoptAccountPositionAware = true;
          StartBehavior = StartBehavior.ImmediatelySubmit;

          }
          else if (State == State.Configure)
          {
          IsUnmanaged = true;
          }
          }

          protected override void OnBarUpdate() //submit the order at the specified minute
          {
          if (Time[0].Minute == entryMinute)
          {
          myOrder = SubmitOrderUnmanaged(0, OrderAction.Buy, OrderType.Limit, 1000, Low[0] - 1000 * TickSize, 0, "", "TestOrder");
          Print (Time[0].Minute + " " + myOrder.ToString());
          }
          }
          }
          Attached Files
          Last edited by beastment; 07-17-2018, 06:19 AM.

          Comment


            #6
            Hello beastment,

            Thank you for your response.

            The behavior you see with your recent instructions and test strategy 'EntryTest2' is expected. Removing the strategy and then adding it back again is not the same as disabling and re-enabling or even reloading NinjaScript. Removing the strategy kills the instance and any references it has to working orders that it submitted.

            Please let me know if you have any questions.

            Comment


              #7
              Okay, that means that the two suggestions that Jim made won't work either. In short, it's simply not possible to have a strategy map a pre-existing working order. That seems a little odd given that filled orders are mapped without issue, and that the strategy can clearly see the pre-existing orders.

              The best alternative I have is to have the strategy cancel the existing orders first if it detects them, and then resubmit. Not ideal, as this creates further issues if the strategy is enabled outside of market hours, but I can work with it.

              Thanks Patrick.

              Comment


                #8
                For anyone else bumping in to similar issues, I've found that if you submit the historical orders with a different OcoID than the originals, then any successfully mapped orders (courtesy of a reload or re-enable) will ignore the new OcoID, but any orders submitted that do not get mapped (because it's a new strategy or the original strategy has been deleted) will acquire the new OcoID on submission.

                Using the order intercept code in my OP, you can then use this behaviour to determine whether the strategy is being refreshed or starting from scratch, and cancel any pre-existing working orders if needed to avoid a double up. If you can live with the cancel and resubmit under those conditions, this effectively allows your strategy to acquire and begin managing all pre-existing orders, even if they were not submitted by the strategy.

                Comment

                Latest Posts

                Collapse

                Topics Statistics Last Post
                Started by Waxavi, Today, 02:10 AM
                1 response
                16 views
                0 likes
                Last Post NinjaTrader_LuisH  
                Started by Kaledus, Today, 01:29 PM
                5 responses
                13 views
                0 likes
                Last Post NinjaTrader_Jesse  
                Started by Waxavi, Today, 02:00 AM
                1 response
                12 views
                0 likes
                Last Post NinjaTrader_LuisH  
                Started by alifarahani, Today, 09:40 AM
                5 responses
                23 views
                0 likes
                Last Post NinjaTrader_Jesse  
                Started by gentlebenthebear, Today, 01:30 AM
                3 responses
                17 views
                0 likes
                Last Post NinjaTrader_Jesse  
                Working...
                X