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

2 entry orders help!

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

    #61
    Hello PaulMohn,

    What are you trying to change?

    If you are trying to change the price of an order, OCO would not be involved. The OCO is only specified when the order is submitted and cannot be changed.

    Changing a price of an order does not involve the OCOID in anyway.

    To change the price of an order set the StopPriceChanged or LImitPriceChanged of the order and use Account.Change().

    myOrder.StopPriceChanged = stopOrder.StopPrice - 4 * stopOrder.Instrument.MasterInstrument.TickSize;

    myAccount.Change(new Orders[] { myOrder } );

    If you want to loop through orders, then you can add the orders to a List<Order> collection and loop through the collection.

    myOrderList = new List<Order>();

    myOrderList.Add(myAccount.CreateOrder());

    myOrderList[index of order].StopPriceChanged = 100;


    You mentioned you are getting a compile error. If you want help with the compile error, please provide the full error message (including the line numbers).
    Chelsea B.NinjaTrader Customer Service

    Comment


      #62
      Thanks again for the directions and very helpful explanations.

      I've modified as
      PHP Code:
              TriggerCustomEvent(qa =>
              {
                if (
      entryBuyMar****rder != null)
                {
                  if (
      Keyboard.IsKeyDown(Key.NumPad7) && !(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
                  {
                    
      changeOrdersArray = new List<Order>();

                    
      currentPtPrice profitTargetOrder.LimitPrice + (ProfitTargetMove TickSize);

                    for (
      int index 0index 3index++)
                    {
                      
      changeOrdersArray[index].LimitPriceChanged currentPtPrice;
                    }
                    
      changeOrdersArray.Add(profitTargetOrder);

                    
      myAccount.Change(changeOrdersArray);
                  }
                } 
      But it's returning error.
      Time Category Message
      31/05/2022 23:47:45 Default Error on triggering custom event for NinjaScript 'ProfitSniper' on bar 5279: You are accessing an index with a value that is invalid since it is out-of-range. I.E. accessing a series [barsAgo] with a value of 5 when there are only 4 bars on the chart.


      Time Category Message
      31/05/2022 23:47:45 Order Failed to submit orders: System.NullReferenceException: Object reference not set to an instance of an object. at NinjaTrader.Cbi.Account.Submit(IEnumerable`1 orders)
      I think the only difference between my modification and your suggestion is
      I used
      changeOrdersArray.Add(profitTargetOrder);
      for your
      myOrderList.Add(myAccount.CreateOrder());

      and used a single list changeOrdersArray to add and change orders.
      But it seems correct. Any tip on why it's not picking up the 3 orders as expected? Thanks!


      It seems I got the solution as
      PHP Code:
              TriggerCustomEvent(qa =>
              {
                if (
      entryBuyMar****rder != null)
                {
                  if (
      Keyboard.IsKeyDown(Key.NumPad7) && !(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
                  {
                    
      changeOrdersArray = new List<Order>();

                    
      currentPtPrice profitTargetOrder.LimitPrice + (ProfitTargetMove TickSize);

                    for (
      int index 0index 3index++)
                    {

                      
      submitOrdersArray[index].LimitPriceChanged currentPtPrice;

                      
      changeOrdersArray.Add(submitOrdersArray[index]);
                    }

                    
      myAccount.Change(changeOrdersArray);
                  }
                } 

      It seems it was about mixing the 2 lists submitOrdersArray and changeOrdersArray in a loop (1st time mixing lists concept acquaintance).
      Actually,
      • looping through the previous list submitOrdersArray[index] to select the number of order limit with the loop index limit (to set the new LimitPrice value)
      • adding the submitOrdersArray[index] orders to a new list changeOrdersArray
      • then changing all at once every orders in the new list's LimitPrices
      I tested and it seems to works as well with only the one single submitOrdersArray list as
      PHP Code:
              TriggerCustomEvent(qa =>
              {
                if (
      entryBuyMar****rder != null)
                {
                  if (
      Keyboard.IsKeyDown(Key.NumPad7) && !(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
                  {
                    
      currentPtPrice profitTargetOrder.LimitPrice + (ProfitTargetMove TickSize);

                    for (
      int index 0index 3index++)
                    {
                      
      submitOrdersArray[index].LimitPriceChanged currentPtPrice;
                    }

                    
      myAccount.Change(submitOrdersArray);
                  }
                } 

      Not sure why you used 2 lists but i think it was to differenciate between submitted orders and changed orders for didactic purpose. I'll see more into it asa.

      many thanks for the directions again. I'll do more tests tomorrow asa and be back! You have a good evening!
      Last edited by PaulMohn; 05-31-2022, 04:50 PM.

      Comment


        #63
        Hello PaulMohn,

        I'm not clear on the exact issue. Is all of the code you have posted causing the error?

        Is profitTargetOrder null?

        What is the collection size of submitOrdersArray?

        Is submitOrdersArray[0] null?

        Is submitOrdersArray[1] null?

        Is SubmitOrdersArray[2] null?

        I am seeing one order 'profitTargetOrder', used over and over and there is no code showing the order is being created and checked that it is not null.
        Chelsea B.NinjaTrader Customer Service

        Comment


          #64
          Hello Chelsea and thanks for the reply and request.
          The orders movement seems to work fine as the last previous loop does control multiple targets at the same time.
          I think the only remaining issue is there are Log tabs errors showing but they don't impact order submission it seems.

          I am seeing one order 'profitTargetOrder', used over and over and there is no code showing the order is being created and checked that it is not null.
          I'll record a demo video asa. I'll clean the script a bit and share it attached to next post. Back asa. Thanks!

          Comment


            #65
            Hello PaulMohn,

            If everything is working, what are you needing help with in the code you posted?

            As a recommendation, reduce the amount of words and information you are posting. Try to reduce to the minimum amount that is directly related to what you need help with.

            If you found a solution and you want to share this, you can export the file and upload to the file sharing section of the forums.
            Chelsea B.NinjaTrader Customer Service

            Comment


              #66
              Hello Chelsea and thanks for the recommendation.

              Please find attached the script.

              For some reason the Account_OrderUpdate() method throws this error when using the quantitySelector.Value as upper limit to the loops
              Time Category Message
              01/06/2022 21:38:29 Default Unhandled exception: Exception has been thrown by the target of an invocation.
              But no error is thrown when hardcoding the upper limit.

              I tested printing Print("qsxy : " + quantitySelector.Value);

              lines 377-380
              PHP Code:
              private void Account_OrderUpdate(object senderOrderEventArgs orderUpdateArgs)
              {
                   
              // Print("qsx : " + quantitySelector.Value);
                   
              if (entryBuyMar****rder != null && entryBuyMar****rder == orderUpdateArgs.Order && orderUpdateArgs.Order.OrderState == OrderState.Filled)
                   {
                        Print(
              "qsxy : " quantitySelector.Value); 
              The 1st print statement (line 377) above is the line causing the error (if uncommented the error/the script fails), while the 2nd (line 380) is fine but somehow doesn't print.

              lines 392 and 421 are the loops statement.
              This causes the error.
              for (int index = 0; index < quantitySelector.Value; index++)
              while this works fine
              for (int index = 0; index < 6; index++)

              Why doesn't the quantitySelector.Value gets working? How can I make it work so as to avoid the hardcoded way? Thanks!
              Attached Files

              Comment


                #67
                Hello quantitySelector,

                Is quantitySelector null?

                Do you have a print to show that is not null?

                Do you have a check to ensure that quantitySelector is not null before attempting to use it?

                Are you using a dispatcher invoke async to access UI thread objects from the Account thread?

                What code is assigning quantitySelector an object?

                Do you have print to show this is not null after the variable is assigned?

                Does this print appear before or after the print where the variable is attempted to be used in the Account_OrderUpdate method?

                Is this the chartTrader quantity selector?
                Chelsea B.NinjaTrader Customer Service

                Comment


                  #68
                  New script attached.

                  Is quantitySelector null?

                  Do you have a print to show that is not null?

                  Do you have a check to ensure that quantitySelector is not null before attempting to use it?
                  Thanks for the check suggestion, I tested and it prints ok at the top of your Account_OrderUpdate() method

                  PHP Code:
                  private void Account_OrderUpdate(object senderOrderEventArgs orderUpdateArgs)
                  {
                       if (
                  quantitySelector!=null)
                       {
                            Print(
                  "ok");
                       } 

                  Are you using a dispatcher invoke async to access UI thread objects from the Account thread?

                  What code is assigning quantitySelector an object?
                  Yes
                  The below snippets


                  Class level QuantitySelector variables

                  PHP Code:
                  private Chart chartWindow;

                  NinjaTrader.Gui.Tools.QuantityUpDown quantitySelector null;

                  // QS
                  private bool Is_ToolBar_Controls_Added;

                  // QS
                  private int qs

                  State.Historical and State.Terminated
                  PHP Code:

                          
                  else if (State == State.Historical)
                          {
                            
                  //Call the custom addButtonToToolbar method in State.Historical to ensure it is only done when applied to a chart
                            // -- not when loaded in the Indicators window
                            
                  if (!Is_ToolBar_Controls_AddedAdd_Controls_To_Toolbar();
                          }
                          else if (
                  State == State.DataLoaded)
                          {
                            
                  // Find our account
                            
                  lock (Account.All)
                              
                  myAccount Account.All.FirstOrDefault(=> a.Name == AccountName);

                            if (
                  myAccount != null)
                              
                  myAccount.OrderUpdate += Account_OrderUpdate;

                            if (
                  ChartControl != null)
                            {
                              
                  ChartControl.PreviewKeyDown += ChartControl_PreviewKeyDown;


                              
                  ChartControl.Dispatcher.InvokeAsync((Action)(() =>
                              {
                                
                  quantitySelector = (Window.GetWindow(ChartControl.Parent).FindFirst(" ChartTraderControlQuantitySelector") as NinjaTrader.Gui.Tools.QuantityUpDown);
                              }));      
                            }
                          }
                          else if (
                  State == State.Terminated)
                          {
                            if (
                  myAccount != null)
                              
                  myAccount.OrderUpdate -= Account_OrderUpdate;

                            if (
                  ChartControl != null)
                            {
                              
                  ChartControl.PreviewKeyDown -= ChartControl_PreviewKeyDown;    
                            }

                            
                  //Call a custom method to dispose of any leftover objects in State.Terminated
                            
                  DisposeCleanUp();
                          }
                        } 

                  Add_Controls_To_Toolbar() and On_quantitySelector_PreviewKeyDown() and DisposeCleanUp()
                  PHP Code:
                      #region Add Controls To Toolbar

                        
                  private void Add_Controls_To_Toolbar()
                        {
                          
                  // Use this.Dispatcher to ensure code is executed on the proper thread
                          
                  ChartControl.Dispatcher.InvokeAsync((Action)(() =>
                          {

                            
                  //Obtain the Chart on which the indicator is configured
                            
                  chartWindow Window.GetWindow(this.ChartControl.Parent) as Chart;
                            if (
                  chartWindow == null)
                            {
                              Print(
                  "chartWindow == null");
                              return;
                            }

                            
                  quantitySelector = new NinjaTrader.Gui.Tools.QuantityUpDown();
                            
                  //quantitySelector.ValueChanged += On_quantitySelector_ValueChanged;
                            
                  quantitySelector.PreviewKeyDown   += On_quantitySelector_PreviewKeyDown;

                            
                  chartWindow.MainMenu.Add(quantitySelector);

                            
                  Is_ToolBar_Controls_Added true;
                          }));
                        }

                      
                  #endregion


                      #region QuantitySelector Snippets

                        
                  private void On_quantitySelector_PreviewKeyDown(object senderKeyEventArgs p)
                        {
                          
                  NinjaTrader.Gui.Tools.QuantityUpDown qs sender as NinjaTrader.Gui.Tools.QuantityUpDown;

                          if (
                  p.Key == Key.Delete || p.Key == Key.Back)
                          {
                            
                  p.Handled true;
                            
                  qs.Value 0;
                          }

                          if ((
                  p.Key >= Key.D0 && p.Key <= Key.D9 || (p.Key >= Key.NumPad0 && p.Key <= Key.NumPad9)))
                          {
                            
                  p.Handled true;

                            
                  string number p.Key.ToString();
                            
                  string newnumber qs.Value.ToString();

                            
                  number number.Replace("NumPad""");
                            
                  number number.Replace("D""");
                            
                  int num int.Parse(newnumber number);

                            if (
                  qs != nullqs.Value num;
                          }
                        }

                      
                  #endregion


                      #region DisposeCleanUp Snippet

                        
                  private void DisposeCleanUp()
                        {
                          
                  //ChartWindow Null Check
                          
                  if (chartWindow != null)
                          {
                            
                  //Dispatcher used to Assure Executed on UI Thread
                            
                  ChartControl.Dispatcher.InvokeAsync((Action)(() =>
                            {
                              if( 
                  quantitySelector != null chartWindow.MainMenu.Remove(quantitySelector);
                            }));
                          }
                        }

                      
                  #endregion 

                  Do you have print to show this is not null after the variable is assigned?

                  Does this print appear before or after the print where the variable is attempted to be used in the Account_OrderUpdate method?

                  Is this the chartTrader quantity selector?
                  Yes (the ok check above)
                  Before (at the top of the Account_OrderUpdate method)
                  The ChartControl


                  quantitySelector.Value works in the ChartControl_PreviewKeyDown() method:
                  lines 158, 194, 230, 246, 268, 283, 305, 320, 342, 357.

                  But not in your Account_OrderUpdate method
                  lines 392, 406, 431, 445

                  Thanks!
                  Attached Files
                  Last edited by PaulMohn; 06-01-2022, 02:47 PM.

                  Comment


                    #69
                    Hello PaulMohn,

                    NinjaTrader.Gui.Tools.QuantityUpDown quantitySelector is declared on line 80 within the action block for OnStateChange(). This variable can only be used in OnStateChange() since it is declared within the scope of OnStateChange().

                    You will either need to declare it within the scope of the class, or remove all references to this variable outside of OnStateChange() (lines 158, 194, 230, 246, 268, 283, etc).

                    I very highly recommend you make a new test script that removes all code that is not relevant to the inquiry at hand so that you are not causing others to debug your code, and only the few lines relevant code is provided.

                    You have previously stated:
                    "For some reason the Account_OrderUpdate() method throws this error when using the quantitySelector.Value as upper limit to the loops"

                    I am not seeing quantitySelector.Value used anywhere in the Account_OrderUpdate() method from lines 377 to 468.

                    I may be overlooking the line. On what line is quantitySelector.Value within the action block for Account_OrderUpdate()?

                    Are you starting a new inquiry?

                    Have you resolved your previous inquiry?

                    Please reduce the script (or make a test script) to just the line of code you are having an issue with and only the supporting code necessary to run that one line.
                    Chelsea B.NinjaTrader Customer Service

                    Comment


                      #70
                      NinjaTrader.Gui.Tools.QuantityUpDown quantitySelector is declared on line 80 within the action block for OnStateChange(). This variable can only be used in OnStateChange() since it is declared within the scope of OnStateChange().
                      Ah yes I had forgot about it being there too, sorry.

                      You have previously stated:
                      "For some reason the Account_OrderUpdate() method throws this error when using the quantitySelector.Value as upper limit to the loops"

                      I am not seeing quantitySelector.Value used anywhere in the Account_OrderUpdate() method from lines 377 to 468.

                      I may be overlooking the line. On what line is quantitySelector.Value within the action block for Account_OrderUpdate()?
                      You're right
                      ProfitSnipermultiOrders1.zip has the hardcoded loops limit lines 392, 406, 431, 445, not the quantitySelector.Value.
                      however, post #66 ProfitSnipermultiOrders.zip did have the quantitySelector.Value and not the hardcoded values.

                      But if you try substituting the hardcoded value with quantitySelector.Value as

                      PHP Code:
                      for (int index 0index 3index++) 
                      with

                      PHP Code:
                      for (int index 0index quantitySelector.Valueindex++) 
                      lines 392, 406, 431, 445 in ProfitSnipermultiOrders1.zip script

                      you will see the script fails (while it doesn't fail with the hardcoded value. Why? Thanks!).

                      Please see attached the new script (ProfitSnipermultiOrders2.zip script) with those substitutions (or if you prefer/faster please try substituting the hardcoded values with quantitySelector.Value lines 392, 406, 431, 445 in ProfitSnipermultiOrders1.zip script) Thanks!


                      You will either need to declare it within the scope of the class, or remove all references to this variable outside of OnStateChange() (lines 158, 194, 230, 246, 268, 283, etc).
                      I tried declaring it at class level scope (line 65 in ProfitSnipermultiOrders2.zip script) and removing it from the OnStateChange scope (line 82), but it still fails with quantitySelector.Value as upper limit in the loops in the Account_OrderUpdate() (lines 399, 413, 438, 452 in ProfitSnipermultiOrders2.zip script).

                      Are you starting a new inquiry?

                      Have you resolved your previous inquiry?

                      Please reduce the script (or make a test script) to just the line of code you are having an issue with and only the supporting code necessary to run that one line.
                      No, still the quantitySelector inquiry
                      No, still the quantitySelector inquiry isn't solved

                      I need the 151-374 lines ChartControl_PreviewKeyDown() method in ProfitSnipermultiOrders2.zip script to show that those work with using quantitySelector.Value in the Hotkeys loops snippets (lines 151-374) and the hardcoded loops snippets of your Account_OrderUpdate() lines 392, 406, 431, 445 in ProfitSnipermultiOrders1.zip script/lines 399, 413, 438, 452 in ProfitSnipermultiOrders2.zip script.
                      I also need quantitySelector.Value in the Hotkeys loops snippets so I can use the quantitySelector input value and not the hardcoded values in the Hotkeys snippets to change orders (151-374 lines ChartControl_PreviewKeyDown() method in ProfitSnipermultiOrders2.zip).
                      But the script fails with the substitution (i.e. with quantitySelector.Value both in the Hotkeys loops snippets (lines 151-374) and your Account_OrderUpdate() lines 392, 406, 431, 445 in ProfitSnipermultiOrders1.zip script/lines 399, 413, 438, 452 in ProfitSnipermultiOrders2.zip script.).

                      I don't understand why quantitySelector.Value works in 151-374 lines ChartControl_PreviewKeyDown() regardless if declared at class level or at OnStateChange level scope but not in your Account_OrderUpdate() method. Thanks!
                      Attached Files
                      Last edited by PaulMohn; 06-01-2022, 03:51 PM.

                      Comment


                        #71
                        Hello PaulMohn,

                        Please provide a reduced script if you are wanting someone to look at your code.

                        In the code you have not provided, is quantitySelector used inside of a dispatcher to invoke into the UI thread from the Account thread?
                        Chelsea B.NinjaTrader Customer Service

                        Comment


                          #72
                          Please find the reduced script ProfitSnipermultiOrders3.zip attached. I kept the minimum Hotkeys and reduced the Account_OrderUpdate() as well.

                          Yes a dispatcher, lines 104-107

                          PHP Code:
                          ChartControl.Dispatcher.InvokeAsync((Action)(() =>
                          {
                          quantitySelector = (Window.GetWindow(ChartControl.Parent).FindFirst(" ChartTraderControlQuantitySelector") as NinjaTrader.Gui.Tools.QuantityUpDown);
                          })); 

                          and 391-394

                          PHP Code:
                          ChartControl.Dispatcher.InvokeAsync((Action)(() =>
                          {
                          if( 
                          quantitySelector != null chartWindow.MainMenu.Remove(quantitySelector);
                          })); 

                          and 325-336

                          PHP Code:
                                private void Add_Controls_To_Toolbar()
                                {
                                  
                          // Use this.Dispatcher to ensure code is executed on the proper thread
                                  
                          ChartControl.Dispatcher.InvokeAsync((Action)(() =>
                                  {
                                    
                          //Obtain the Chart on which the indicator is configured
                                    
                          chartWindow Window.GetWindow(this.ChartControl.Parent) as Chart;
                                    if (
                          chartWindow == null)
                                    {
                                      Print(
                          "chartWindow == null");
                                      return;
                                    }

                                    
                          quantitySelector = new NinjaTrader.Gui.Tools.QuantityUpDown();
                                    
                          //quantitySelector.ValueChanged += On_quantitySelector_ValueChanged;
                                    
                          quantitySelector.PreviewKeyDown   += On_quantitySelector_PreviewKeyDown;

                                    
                          chartWindow.MainMenu.Add(quantitySelector);

                                    
                          Is_ToolBar_Controls_Added true;
                                  }));
                                } 

                          not sure about to invoke into the UI thread from the Account thread. The quantitySelector is for use in the Toolbar. I see post #67 you refer to Chris's snippet with AccountSelector (2nd snippet). I didn't need/use it and it works without it for the Hotkeys/ChartControl_PreviewKeyDown() method and quantitySelector.Value. Would I need it with the Account_OrderUpdate()? If so why and how?

                          I suspect the Exception error post #66 might stem from the use of the bools conditions lines 259-270 if (UseProfitTarget)/ if (UseStopLoss) or possibly from the OCO ID generation + index line 265, 276, 255 as those seem to be the only differences in processing the Account_OrderUpdate() method with quantitySelector.Value from the other working method processing ChartControl_PreviewKeyDown() with quantitySelector.Value. Is that right? If so why ad how to fix it? Thanks!
                          Attached Files
                          Last edited by PaulMohn; 06-02-2022, 05:04 AM.

                          Comment


                            #73
                            Hello PaulMohn,

                            We don't need the code where the variable is declared or the QuantityUpDown is found and assigned to a value. Yes, that does need to be in a dispatcher as well, but that's not where the error is occurring and is irrelevant code.

                            Where is the quantitySelector.Value variable holding the QuantityUpDown object being used?

                            To confirm, this is now being used in the hotkey press and is not being used in Account_OrderUpdate() as you has previously suggested, is this correct?

                            The error is happening when you press the key and not when the account order updates right?

                            Do you have the quantitySelector.Value in a dispatcher invokeasync from the keypress event handler method where the variable is used?

                            Where you have inquired 'Would I need it with the Account_OrderUpdate()'?

                            Most definitely YES!! Anywhere quantitySelector.Value, or any other UI object like buttons, grids, the UserControlCollection, etc, is used that is not in the UI thread must have a dispatcher invoke into the UI thread or an error will occur.

                            Below is a link to the help guide.
                            https://ninjatrader.com/support/help...-threading.htm

                            OCO would not cause this issue. I do not expect OCO will be involved in any way.
                            Chelsea B.NinjaTrader Customer Service

                            Comment


                              #74
                              Hello Cheslea and thanks for the reply and doc and Dispatcher.CheckAccess()) new reference.

                              Where is the quantitySelector.Value variable holding the QuantityUpDown object being used?
                              In both methods ChartControl_PreviewKeyDown() (lines 139, 175, 211, 227) and Account_OrderUpdate() (lines 263, 274) (script version of post #72 above).

                              To confirm, this is now being used in the hotkey press
                              and is not being used in Account_OrderUpdate() as you has previously suggested, is this correct?
                              Yes it is being used in ChartControl_PreviewKeyDown() (lines 139, 175, 211, 227).
                              No, Account_OrderUpdate() (lines 263, 274) does use quantitySelector.Value (it is called in the loops conditions lines 263 and line 274, the purpose being able to set the upper limit value for those loops directly from the quantity selector field in the Chart Toolbar instead of having to manually hardcode and modify the hardcoded value every time in the script).

                              The error is happening when you press the key and not when the account order updates right?
                              Yes it it happening upon the NumPad1 key press. I don't know if it is also happening or not when the order updates.

                              What it happening is:

                              Please see the explained below issue in this 4min demo video

                              With lines 263 and 274 having the quantitySelector.Value as upper value
                              for (int index = 0; index < quantitySelector.Value; index++)
                              for (int index = 0; index < quantitySelector.Value; index++)
                              when I press the NumPad1 key with say 5 units in the Quantity Selector field inputted in the Chart's toolbar,
                              the 6 orders get filled but their expected 5 OCO pairs don't get submitted and the Exception Error is thrown instead.
                              What I need is for those 6 OCO pairs to be submitted as well.

                              What it happening is:
                              With lines 263 and 274 having the hardcoded 3 value as upper value
                              for (int index = 0; index < 3; index++)
                              for (int index = 0; index < 3; index++)
                              when I press the NumPad1 key with say 5 units in the Quantity Selector field inputted in the Chart's toolbar,
                              the 6 orders get filled and their expected 3 OCO pairs do get submitted and the Exception Error is not thrown.
                              That is what I need, but with the quantitySelector.Value instead of the hardcoded 3 value as the loops upper limits.

                              Do you have the quantitySelector.Value in a dispatcher invokeasync from the keypress event handler method where the variable is used?
                              Are you asking if the ChartControl_PreviewKeyDown() contains a dispatcher snippet? No.
                              Or if the Account_OrderUpdate() contains a dispatcher snippet? No.
                              Or if both the ChartControl_PreviewKeyDown() and Account_OrderUpdate() contains a dispatcher snippet? No.
                              Can you clarify please what you asked? Thanks!


                              Where you have inquired 'Would I need it with the Account_OrderUpdate()'?

                              Most definitely YES!! Anywhere quantitySelector.Value, or any other UI object like buttons, grids, the UserControlCollection, etc, is used that is not in the UI thread must have a dispatcher invoke into the UI thread or an error will occur.
                              I'm not sure I understand. Isn't the quantitySelector.Value already invoked on the UI Thread? How would I check?
                              I found this example which I adapted as
                              PHP Code:
                                  private void Account_OrderUpdate(object senderOrderEventArgs orderUpdateArgs)
                                    {
                                      if (
                              quantitySelector!=null)
                                      {
                                        Print(
                              "ok");
                                        
                              // Checking if this thread has access to the object.
                                        
                              if (quantitySelector.Dispatcher.CheckAccess())
                                        {
                                          
                              // This thread has access so it can update the UI thread.
                              //           UpdateButtonUI(quantitySelector);
                                          
                              Print("ok1");
                                        }
                                        else
                                        {
                                          
                              // This thread does not have access to the UI thread.
                                          // Place the update method on the Dispatcher of the UI thread.
                                          // quantitySelector.Dispatcher.BeginInvoke(Dispatcher Priority.Normal,
                                          //  new UpdateUIDelegate(UpdateButtonUI), quantitySelector);
                                          
                              Print("ok2"); 
                              It prints
                              ok
                              ok2
                              Which suggest the quantitySelector's thread isn't the UI thread.
                              How would I redirect the quantitySelector on the UI thread?

                              the doc give this example
                              PHP Code:
                              // check if the current object is already on the calling thread
                              if (Dispatcher.CheckAccess())
                              {
                                
                              // execute action directly
                                
                              action(args);
                              }
                              // otherwise run the action from the thread that created the object
                              else
                              {
                                
                              // dispatch action to calling thread
                                
                              Dispatcher.InvokeAsync(actionargs);

                              I think I should modify mine as
                              PHP Code:
                                    private void Account_OrderUpdate(object senderOrderEventArgs orderUpdateArgs)
                                    {
                                      if (
                              quantitySelector!=null)
                                      {
                                        Print(
                              "ok");
                                        
                              // Checking if this thread has access to the object.
                                        
                              if (quantitySelector.Dispatcher.CheckAccess())
                                        {
                                          
                              // This thread has access so it can update the UI thread.
                              //           UpdateButtonUI(quantitySelector);
                                          
                              Print("ok1");
                                        }
                                        else
                                        {
                                          
                              // Use this.Dispatcher to ensure code is executed on the proper thread
                                          
                              ChartControl.Dispatcher.InvokeAsync((Action)(() =>
                                          {

                                          }));
                                        }
                                      } 

                              then embed all the remaining in the Dispatcher as
                              PHP Code:
                              private void Account_OrderUpdate(object senderOrderEventArgs orderUpdateArgs)
                                    {
                                      if (
                              quantitySelector!=null)
                                      {
                                        Print(
                              "ok");
                                        
                              // Checking if this thread has access to the object.
                                        
                              if (quantitySelector.Dispatcher.CheckAccess())
                                        {
                                          
                              // This thread has access so it can update the UI thread.
                              //           UpdateButtonUI(quantitySelector);
                                          
                              Print("ok1");
                                        }
                                        else
                                        {
                                          
                              // Use this.Dispatcher to ensure code is executed on the proper thread
                                          
                              ChartControl.Dispatcher.InvokeAsync((Action)(() =>
                                          {
                                            if (
                              entryBuyMar****rder != null && entryBuyMar****rder == orderUpdateArgs.Order && orderUpdateArgs.Order.OrderState == OrderState.Filled)
                                            {
                                              
                              string oco     Guid.NewGuid().ToString("N");
                                              
                              submitOrdersArray = new List<Order>();

                                              if (
                              UseProfitTarget)
                                              {
                                                
                              currentPtPrice orderUpdateArgs.AverageFillPrice ProfitTargetDistance TickSize;

                                                for (
                              int index 0index quantitySelector.Valueindex++)
                                                {
                                                  
                              profitTargetOrder myAccount.CreateOrder(orderUpdateArgs.Order.Instru mentOrderAction.SellOrderType.LimitOrderEntry.AutomatedTimeInForce.DayorderUpdateArgs.QuantitycurrentPtPrice0oco+index"Profit Target"Core.Globals.MaxDatenull);
                                                  
                              submitOrdersArray.Add(profitTargetOrder);
                                                }
                                              }

                                              if (
                              UseStopLoss)
                                              {
                                                
                              currentSlPrice orderUpdateArgs.AverageFillPrice StopLossDistance TickSize;

                                                for (
                              int index 0index quantitySelector.Valueindex++)
                                                {
                                                  
                              stopLossOrder myAccount.CreateOrder(orderUpdateArgs.Order.Instru mentOrderAction.SellOrderType.StopMarketOrderEntry.AutomatedTimeInForce.DayorderUpdateArgs.Quantity0currentSlPriceoco+index"Stop Loss"Core.Globals.MaxDatenull);
                                                  
                              submitOrdersArray.Add(stopLossOrder);
                                                }
                                              }

                                              
                              myAccount.Submit(submitOrdersArray);
                                            }

                                            
                              // once the exit orders are closed, reset for a new entry.
                                            
                              else if ((profitTargetOrder != null && (profitTargetOrder.OrderState == OrderState.Filled
                                                                
                              || profitTargetOrder.OrderState == OrderState.Rejected
                                                                
                              || profitTargetOrder.OrderState == OrderState.Cancelled))
                                              || (
                              stopLossOrder != null && (stopLossOrder.OrderState == OrderState.Filled
                                                                
                              || stopLossOrder.OrderState == OrderState.Rejected
                                                                
                              || stopLossOrder.OrderState == OrderState.Cancelled)))
                                            {
                                              
                              entryBuyMar****rder   null;
                                              
                              profitTargetOrder   null;
                                              
                              stopLossOrder     null;
                                            }

                                          }));
                                        }
                                      } 
                              That solves the Exception error but now it generates unexpected behavior (it sells instead of buying) and I get those log Tab errors

                              Time Category Message
                              02/06/2022 17:53:47 Order Sim101, Order '2616282c085944b79879749df33d104e' can't be submitted: order status is CancelPending. affected Order: Sell 1 StopMarket @ -0.1

                              Time Category Message
                              02/06/2022 17:57:02 Order Sim101, Order '71e83eaca1d14108b6105bf2380696b7' can't be submitted: order status is CancelPending. affected Order: Sell 1 StopMarket @ -0.1

                              Time Category Message
                              02/06/2022 17:57:01 Order Sim101, Order 'b3405812c3374c2194eb31161b277e4b' can't be submitted: order status is CancelPending. affected Order: Sell 1 StopMarket @ -0.1

                              etc.

                              What fix would you suggests? hanks!

                              Comment


                                #75
                                Hello PaulMohn,

                                It now appears you are using in the Account_OrderUpdate() method. You must use a dispatcher to access this UI item on the UI thread from the Account thread.

                                Where you have stated:
                                "Are you asking if the ChartControl_PreviewKeyDown() contains a dispatcher snippet? No.
                                Or if the Account_OrderUpdate() contains a dispatcher snippet? No.
                                Or if both the ChartControl_PreviewKeyDown() and Account_OrderUpdate() contains a dispatcher snippet? No."

                                Use dispatcher to access the UI item from the Account thread.

                                Where you have inquired:
                                "I'm not sure I understand. Isn't the quantitySelector.Value already invoked on the UI Thread? How would I check?"

                                Any access to a UI item needs to be done with a dispatcher to allow access into the thread.
                                Instantiating a new object or finding an object with an AutomationID and assigning this to a variable does not remove the UI item from the UI thread. You will need to use a dispatcher to instantiate, to assign to a variable, to get a value from, to assign a value to, or any use of the UI object.

                                You will need to use dispatcher anytime the UI item is referenced from any thread that is not the UI thread.

                                Anywhere quantitySelector.Value, or any other UI object like buttons, grids, the UserControlCollection, etc, is used that is not in the UI thread must have a dispatcher invoke into the UI thread or an error will occur.

                                Use a dispatcher invoke async to access this UI item from the Account update thread.

                                Where you have stated:
                                "Which suggest the quantitySelector's thread isn't the UI thread."

                                This is incorrect. All UI items are in the UI thread. Buttons, drop-downs, radio buttons, text boxes, grids, stack panels, dock panels, checkboxs, all UI items, all on the UI thread.
                                Chelsea B.NinjaTrader Customer Service

                                Comment

                                Latest Posts

                                Collapse

                                Topics Statistics Last Post
                                Started by jxs_xrj, 01-12-2020, 09:49 AM
                                6 responses
                                3,290 views
                                1 like
                                Last Post jgualdronc  
                                Started by Touch-Ups, Today, 10:36 AM
                                0 responses
                                8 views
                                0 likes
                                Last Post Touch-Ups  
                                Started by geddyisodin, 04-25-2024, 05:20 AM
                                8 responses
                                61 views
                                0 likes
                                Last Post NinjaTrader_Gaby  
                                Started by Option Whisperer, Today, 09:55 AM
                                0 responses
                                8 views
                                0 likes
                                Last Post Option Whisperer  
                                Started by halgo_boulder, 04-20-2024, 08:44 AM
                                2 responses
                                24 views
                                0 likes
                                Last Post halgo_boulder  
                                Working...
                                X