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

    #46
    Here a Prints video.
    I can see your Event handler method cannot pick up the entryBuyMar****rder KeyDown event (please see entryBuyMar****rder != null : False in the Prints below).
    Why can't it pick it up while it can pick it up when the entryBuyMar****rder is autotriggered from the OnbarUpdate as in your script? Thanks!

    ### 1A. OnBarUpdate() with !KEYDOWN 13/05/2022 19:02:00
    accountPosition == null : True
    profitTargetOrder == nul : True
    sstopLossOrder == nul : True

    ### 1A. OnBarUpdate() with !KEYDOWN 13/05/2022 19:02:00
    accountPosition == null : True
    profitTargetOrder == nul : True
    sstopLossOrder == nul : True

    2A. Account_OrderUpdate() with KEYDOWN 13/05/2022 19:02:00
    entryBuyMar****rder != null : False
    entryBuyMar****rder == orderUpdateArgs.Order : False
    orderUpdateArgs.Order.OrderState == OrderState.Filled : False
    orderUpdateArgs.Order.OrderState == OrderState.Working : False

    accountPosition == null : True
    profitTargetOrder == nul : True
    sstopLossOrder == nul : True

    2A. Account_OrderUpdate() with KEYDOWN 13/05/2022 19:02:00
    entryBuyMar****rder != null : False
    entryBuyMar****rder == orderUpdateArgs.Order : False
    orderUpdateArgs.Order.OrderState == OrderState.Filled : False
    orderUpdateArgs.Order.OrderState == OrderState.Working : False

    accountPosition == null : True
    profitTargetOrder == nul : True
    sstopLossOrder == nul : True

    ### 1A. OnBarUpdate() with !KEYDOWN 13/05/2022 19:02:00
    accountPosition == null : True
    profitTargetOrder == nul : True
    sstopLossOrder == nul : True

    2A. Account_OrderUpdate() with KEYDOWN 13/05/2022 19:02:00
    entryBuyMar****rder != null : False
    entryBuyMar****rder == orderUpdateArgs.Order : False
    orderUpdateArgs.Order.OrderState == OrderState.Filled : False
    orderUpdateArgs.Order.OrderState == OrderState.Working : False

    accountPosition == null : True
    profitTargetOrder == nul : True
    sstopLossOrder == nul : True

    2A. Account_OrderUpdate() with KEYDOWN 13/05/2022 19:02:00
    entryBuyMar****rder != null : False
    entryBuyMar****rder == orderUpdateArgs.Order : False
    orderUpdateArgs.Order.OrderState == OrderState.Filled : False
    orderUpdateArgs.Order.OrderState == OrderState.Working : True

    accountPosition == null : True
    profitTargetOrder == nul : True
    sstopLossOrder == nul : True

    2A. Account_OrderUpdate() with KEYDOWN 13/05/2022 19:02:00
    entryBuyMar****rder != null : False
    entryBuyMar****rder == orderUpdateArgs.Order : False
    orderUpdateArgs.Order.OrderState == OrderState.Filled : True
    orderUpdateArgs.Order.OrderState == OrderState.Working : False

    accountPosition == null : True
    profitTargetOrder == nul : True
    sstopLossOrder == nul : True

    1B. OnBarUpdate() with KEYDOWN 13/05/2022 19:02:00
    accountPosition == null : False
    profitTargetOrder == nul : True
    sstopLossOrder == nul : True

    *
    Last edited by PaulMohn; 05-13-2022, 11:21 AM.

    Comment


      #47
      Hello PaulMohn,

      Where you have stated:
      "I can see your Event handler method cannot pick up the entryBuyMar****rder KeyDown event"

      I don't understand what this means. Which event handler?
      Order objects do not have a keydown event. This makes no sense. entryBuyMar****rder does not have a KeyDown event.

      Your output possibly is showing entryBuyMar****rder is null. Have you assigned entryBuyMar****rder the order object from OnOrderUpdate()?

      accountPosition also appears null. Are you assigning accountPosition from the <Account>.Positions collection?
      Chelsea B.NinjaTrader Customer Service

      Comment


        #48
        Hi Chels, I think I got it right now. The issue was a a2nd local assignment/local variable in the TriggerCustomEvent() Event Handler within my ChartControl_PreviewKeyDown() method.


        protected void ChartControl_PreviewKeyDown(object sender, KeyEventArgs e)
        {
        TriggerCustomEvent(p =>
        {
        Order entryBuyMar****rder = null;

        if (Keyboard.IsKeyDown(Key.NumPad1))
        {
        entryBuyMar****rder = submissionAccount. CreateOrder(
        Instrument,
        OrderAction.Buy,
        OrderType.Market,
        OrderEntry.Manual,
        TimeInForce.Day,
        1,
        0,
        0,
        string.Empty,
        "Entry",
        Core.Globals.MaxDate,
        null);
        }

        submissionAccount.Submit(new[] { entryBuyMar****rder });

        }, null);
        e.Handled = true;
        }






        I removed it as


        protected void ChartControl_PreviewKeyDown(object sender, KeyEventArgs e)
        {
        TriggerCustomEvent(p =>
        {
        //Order entryBuyMar****rder = null;

        if (Keyboard.IsKeyDown(Key.NumPad1))
        {
        entryBuyMar****rder = submissionAccount. CreateOrder(
        Instrument,
        OrderAction.Buy,
        OrderType.Market,
        OrderEntry.Manual,
        TimeInForce.Day,
        1,
        0,
        0,
        string.Empty,
        "Entry",
        Core.Globals.MaxDate,
        null);
        }

        submissionAccount.Submit(new[] { entryBuyMar****rder });

        }, null);
        e.Handled = true;
        }






        Now it seems to work and submit and move the Target and StopLoss.

        I think the reason it didn't work before is because the 2nd assignment of //Order entryBuyMar****rder = null; "conflicted" with the class level 1st assignment of
        entryBuyMar****rder

        namespace NinjaTrader.NinjaScript.Indicators
        {
        public class MyOCOKeyEvent1 : Indicator
        {
        private Order entryBuyMar****rder, profitTargetOrder, stopLossOrder;

        If I understand it right, the 2nd assignment was setting the entryBuyMar****rder order to null? Before and after the order was placed? So it couldn't be picked up by the OnOrderUpdate() method? If that's so, why? I mean my 2nd assignment appears before the if (Keyboard.IsKeyDown(Key.NumPad1)) statement, so shouldn't entryBuyMar****rder "stay" ¬null once it is triggered? Thanks!
        Last edited by PaulMohn; 05-16-2022, 03:10 AM.

        Comment


          #49
          Hello Chelsea, I got a new indicator in the User Apps Share for OCO Orders movable with Hotkeys, mainly thanks to your recent help! Thanks!

          Comment


            #50
            Hello Chelsea, I'm getting back to post #25 and bitdavid's split order method applied to my new OCO Hotkeys Order script shared on the User Apps Share.
            I need to use that handy method for the order to execute split sizes instead of the full size at once, for my next user Apps Share release. So I thought of using bitdavid's method to try and see how it works. If it doesn't work as needed I would resort to more complex code with separated orders (but the Target and StopLoss handling for multiple separated orders would seem more difficult so I'd privilege bitdavid's method if working as well).

            Here's my application of bitdavid's method
            PHP Code:
                private static Random MyRand = new Random(DateTime.Now.Millisecond);

                private const 
            int SHORT = -1;
                private const 
            int NONE 0;
                private const 
            int LONG 1;

                private 
            void EnterOrder(int Directionint totalQuantity)
                {
                  
            int orderNum 1;
                  while (
            totalQuantity 0)
                  {
                    
            int quantity Math.Min(MyRand.Next(14), totalQuantity);
                    if (
            Direction 0)
                    {
                      
            entryBuyMar****rder myAccount.CreateOrder(
                          
            Instrument,
                          
            OrderAction.Buy,
                          
            OrderType.Market,
                          
            OrderEntry.Manual,
                          
            TimeInForce.Day,
                          
            quantity,
                          
            0,
                          
            0,
                          
            string.Empty,
                          
            "Entry"+"L"+orderNum,
                          
            Core.Globals.MaxDate,
                          
            null);
                    }
                    else if (
            Direction 0)
                    {
                      
            entrySellMar****rder myAccount.CreateOrder(
                          
            Instrument,
                          
            OrderAction.Sell,
                          
            OrderType.Market,
                          
            OrderEntry.Manual,
                          
            TimeInForce.Day,
                          
            quantity,
                          
            0,
                          
            0,
                          
            string.Empty,
                          
            "Entry"+"S"+orderNum,
                          
            Core.Globals.MaxDate,
                          
            null);
                    }
                    
            totalQuantity totalQuantity quantity;
                    ++
            orderNum;
                  } 

            Here's my Hotkeys method
            PHP Code:
                  protected void ChartControl_PreviewKeyDown(object senderKeyEventArgs e)
              {
                    
            // LONG Orders
                    
            TriggerCustomEvent(=>
                    {
                      if (
            Keyboard.IsKeyDown(Key.NumPad1))
                      {
                        
            EnterOrder(LONGquantitySelector.Value);
                      }

                      
            myAccount.Submit(new[] { entryBuyMar****rder });

                    }, 
            null);
                    
            e.Handled true;


                    
            // SHORT Orders
                    
            TriggerCustomEvent(=>
                    {
                      if (
            Keyboard.IsKeyDown(Key.NumPad2))
                      {

                        
            EnterOrder(SHORTquantitySelector.Value);
                      }

                      
            myAccount.Submit(new[] { entrySellMar****rder });

                    }, 
            null);
                    
            e.Handled true;
                  } 

            Now, the script executes but only 1 contract instead of the given Quantity Selector value (when I set 10 for example in the QuantitySelector field).

            There's also a Log Tab error
            Time Category Message
            25/05/2022 13:07:53 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 see Kate and Patrick request for the script or Log and Trace files.
            Here's attached the latest version of the script ProfitSniperSplitOrders.zip (the previous is on the User Apps Share page above link).

            How can I make the script execute the full size defined by the QuantitySelector field and not the default 1 contract size?
            How can I fix the Log tab error? I don't understand why the method works and does execute but for the size part. Thanks for your tips!
            Attached Files

            Comment


              #51
              Hello PaulMohn,

              How can I make the script execute the full size defined by the QuantitySelector field and not the default 1 contract size?
              You need to make sure your code is capturing the value from the QuantitySelector. (Use prints to verify.) After you confirm you are fetching the correct value, consider saving that value to a class level variable. Then use that variable for the order submission quantity. I have attached an example that can be helpful for capturing controls from ChartTrader.

              How can I fix the Log tab error? I don't understand why the method works and does execute but for the size part. Thanks for your tips!
              When you add prints to the script to identify the last line of code reached, what line is that?

              After identifying this line of code, are there any objects that are referenced that are null? Use additional prints like Print((someObject1 == null)); Print((someObject2 == null)); to confirm which specific object is null when the error is reached.
              Attached Files
              JimNinjaTrader Customer Service

              Comment


                #52
                Hello Jim and thank you for the reply and tips.
                You need to make sure your code is capturing the value from the QuantitySelector. (Use prints to verify.) After you confirm you are fetching the correct value, consider saving that value to a class level variable. Then use that variable for the order submission quantity. I have attached an example that can be helpful for capturing controls from ChartTrader.
                I've printed the QuantitySelector variable at the top of the EnterOrder() method
                PHP Code:
                 private void EnterOrder(int Directionint totalQuantity)
                {
                Print(
                "totalQuantity : " totalQuantity); 
                and got this mixed result
                Code:
                totalQuantity : 10
                Instrument: CL 07-22 Quantity: 1 Price: 114.22
                Instrument: CL 07-22 Quantity: 1 Price: 114.1
                What does it mean? I think it means the correct quantity is picked up from the QuantitySelector filed, but the default 1 contract is used instead for executing the order.

                I added Print("1. totalQuantity : " + totalQuantity); at the end of the EnterOrder() method next

                PHP Code:
                   private void EnterOrder(int Directionint totalQu antity)
                   {
                      Print(
                "0. totalQuantity : " totalQuantity);
                       
                int orderNum 1;
                      while (
                totalQuantity 0)
                      {
                        
                int quantity Math.Min(MyRand.Next(14), totalQuantity);
                        if (
                Direction &gt0)
                        {
                          
                entryBuyMar****rder myAccount.CreateOrder(
                              
                Instrument,
                              
                OrderAction.Buy,
                              
                OrderType.Market,
                              
                OrderEntry.Manual,
                              
                TimeInForce.Day,
                              
                quantity,
                              
                0,
                              
                0,
                              
                string.Empty,
                              
                "Entry"+"L"+orderNum,
                              
                Core.Globals.MaxDate,
                              
                null);
                        }
                        else if (
                Direction 0)
                        {
                          
                entrySellMar****rder myAccount.CreateOrder(
                              
                Instrument,
                              
                OrderAction.Sell,
                              
                OrderType.Market,
                              
                OrderEntry.Manual,
                              
                TimeInForce.Day,
                              
                quantity,
                              
                0,
                              
                0,
                              
                string.Empty,
                              
                "Entry"+"S"+orderNum,
                              
                Core.Globals.MaxDate,
                              
                null);
                        }
                        
                totalQuantity totalQuantity quantity;
                        ++
                orderNum;
                      Print(
                "1. totalQuantity : " totalQuantity);
                      } 

                And the Prints return (1st Order submitted)
                0. totalQuantity : 10
                1. totalQuantity : 7
                1. totalQuantity : 6
                1. totalQuantity : 4
                1. totalQuantity : 1
                1. totalQuantity : 0
                2nd Order etc.
                0. totalQuantity : 10
                1. totalQuantity : 9
                1. totalQuantity : 6
                1. totalQuantity : 4
                1. totalQuantity : 3
                1. totalQuantity : 0
                The 1st order executed 3 contracts. The 2nd order and next orders executed 1 contract.

                What's strange is the next 1.totalQuantity: ... get printed in spite of not being executed.

                I think it means the QuantitySelector works and the EnterOrder() method does work but it only executes One time. It randomly picks a size between 1 and 4 and executes it once.

                What I need would be to do exactly as it does but keep executing until the whole QuantitySelector initial size is executed, i.e. the 10 contracts, not stop after the 1st randomly generated sub size gets executed.

                Why doesn't it do it like that? The while loop says so yet as long as totalQuantity is greater than 0 keep executing.
                while (totalQuantity > 0)

                Multiple orders
                demo 1

                One orders with unsubmitted but remaining orders initialized state on the orders tab
                demo 2


                How would I make it keep executing until the totalQuantity is zero? Thanks!

                I've sorted chronologically the orders in the orders tab and got this result showing the 4 initialized orders are submitted first and not executed, then the last order gets executed (please see the attached photo)

                Thanks for that
                When you add prints to the script to identify the last line of code reached, what line is that?

                After identifying this line of code, are there any objects that are referenced that are null? Use additional prints like Print((someObject1 == null)); Print((someObject2 == null)); to confirm which specific object is null when the error is reached.
                I'm not sure how to print line by line here because there's only one single order in the method.

                I've added class level variable for

                PHP Code:
                private int orderNumquantity
                I printed the quantity along with totalQuantity and got
                0. totalQuantity : 10
                1. totalQuantity : 9
                1. quantity : 1
                1. totalQuantity : 7
                1. quantity : 2
                1. totalQuantity : 4
                1. quantity : 3
                1. totalQuantity : 1
                1. quantity : 3
                1. totalQuantity : 0
                1. quantity : 1

                0. totalQuantity : 10 Time[0] : 27/05/2022 12:48:00
                1. totalQuantity : 10 Time[0] : 27/05/2022 12:48:00
                1. quantity : 3 Time[0] : 27/05/2022 12:48:00

                2. totalQuantity : 7 Time[0] : 27/05/2022 12:48:00
                2. quantity : 3 Time[0] : 27/05/2022 12:48:00

                1. totalQuantity : 7 Time[0] : 27/05/2022 12:48:00
                1. quantity : 3 Time[0] : 27/05/2022 12:48:00

                2. totalQuantity : 4 Time[0] : 27/05/2022 12:48:00
                2. quantity : 3 Time[0] : 27/05/2022 12:48:00

                1. totalQuantity : 4 Time[0] : 27/05/2022 12:48:00
                1. quantity : 1 Time[0] : 27/05/2022 12:48:00

                2. totalQuantity : 3 Time[0] : 27/05/2022 12:48:00
                2. quantity : 1 Time[0] : 27/05/2022 12:48:00

                1. totalQuantity : 3 Time[0] : 27/05/2022 12:48:00
                1. quantity : 2 Time[0] : 27/05/2022 12:48:00

                2. totalQuantity : 1 Time[0] : 27/05/2022 12:48:00
                2. quantity : 2 Time[0] : 27/05/2022 12:48:00

                1. totalQuantity : 1 Time[0] : 27/05/2022 12:48:00
                1. quantity : 1 Time[0] : 27/05/2022 12:48:00

                2. totalQuantity : 0 Time[0] : 27/05/2022 12:48:00
                2. quantity : 1 Time[0] : 27/05/2022 12:48:00
                PHP Code:
                    private void EnterOrder(int Directionint totalQuantity)
                    {

                      Print(
                "0. totalQuantity : " totalQuantity " Time[0] : " Time[0]);
                //     Print("0. quantity : " + quantity + "Time[0] : " + Time[0]);
                      
                int orderNum 1;
                      while (
                totalQuantity 0)
                      {
                        
                int quantity Math.Min(MyRand.Next(14), totalQuantity);


                      Print(
                "1. totalQuantity : " totalQuantity " Time[0] : " Time[0]);
                      Print(
                "1. quantity : " quantity " Time[0] : " Time[0]);
                        Print(
                " ");
                        if (
                Direction 0)
                        {
                          
                entryBuyMar****rder myAccount.CreateOrder(
                              
                Instrument,
                              
                OrderAction.Buy,
                              
                OrderType.Market,
                              
                OrderEntry.Manual,
                              
                TimeInForce.Day,
                              
                quantity,
                              
                0,
                              
                0,
                              
                string.Empty,
                              
                "Entry"+"L"+orderNum,
                              
                Core.Globals.MaxDate,
                              
                null);
                        }
                        else if (
                Direction 0)
                        {
                          
                entrySellMar****rder myAccount.CreateOrder(
                              
                Instrument,
                              
                OrderAction.Sell,
                              
                OrderType.Market,
                              
                OrderEntry.Manual,
                              
                TimeInForce.Day,
                              
                quantity,
                              
                0,
                              
                0,
                              
                string.Empty,
                              
                "Entry"+"S"+orderNum,
                              
                Core.Globals.MaxDate,
                              
                null);
                        }
                        
                totalQuantity totalQuantity quantity;
                        ++
                orderNum;
                      Print(
                "2. totalQuantity : " totalQuantity " Time[0] : " Time[0]);
                      Print(
                "2. quantity : " quantity " Time[0] : " Time[0]);
                        Print(
                " ");
                      }
                    } 
                Last edited by PaulMohn; 05-27-2022, 05:05 AM.

                Comment


                  #53
                  Hello PaulMohn,

                  If there are multiple prints but only one print call in the method, this would imply the method is being called multiple times.

                  During those multiple times, are you changing the quantity selector value?

                  If this is not being changed, I would not expect the value to change.

                  If this is being changed, I would expect either the user is manually changing the selection or the value is being set in code.

                  If the code is changing the value, where you finding that the value is unexpected?

                  Is the value being changed with ' totalQuantity = totalQuantity - quantity;' not providing the value you expect?

                  Where you have stated 'How would I make it keep executing until the totalQuantity is zero?'

                  This would depend on your logic. Through the addon approach you submit any orders you want. Are you printing the time and all values used in the condition and confirming the condition is evaluating as true and that the line of code is being reached?

                  Below is a link to a forum post that demonstrates using Print() to understand behavior.
                  Chelsea B.NinjaTrader Customer Service

                  Comment


                    #54
                    Hello Chelsea and thanks for the directions and testing steps.

                    I've thought of trying something simpler first to see how it would work.
                    With the following simple loop
                    PHP Code:
                          protected void ChartControl_PreviewKeyDown(object senderKeyEventArgs e)
                          {
                            
                    TriggerCustomEvent(=>
                            {
                              if (
                    Keyboard.IsKeyDown(Key.NumPad1))
                              {
                                Print(
                    "quantitySelector.Value : " quantitySelector.Value);
                                for (
                    int index 0index quantitySelector.Valueindex++)
                                {
                                  
                    entryBuyMar****rder myAccount.CreateOrder(
                                      
                    Instrument,
                                      
                    OrderAction.Buy,
                                      
                    OrderType.Market,
                                      
                    OrderEntry.Manual,
                                      
                    TimeInForce.Day,
                                      
                    1,
                                      
                    0,
                                      
                    0,
                                      
                    string.Empty,
                                      
                    "Entry",
                                      
                    Core.Globals.MaxDate,
                                      
                    null);
                                }

                              }

                              
                    myAccount.Submit(new[] { entryBuyMar****rder });

                            }, 
                    null);
                            
                    e.Handled true
                    As you can see, the loop starts at 0 and must execute until 1 minus quantitySelector.Value.
                    So for quantitySelector.Value equals 10, I expect 10 orders of 1 contracts to be submitted

                    I tested it but it only executed 1 contract and 1 order only.

                    The quantitySelector.Value prints 10
                    quantitySelector.Value : 10
                    Why doesn't it execute the 10 orders? How to make it execute the 10 orders?
                    Why doesn't the loop work as intended?

                    I suspect the cause is an internal way NT8 processes orders that's stopping execution somehow.
                    Is entryBuyMar****rder restricted to be submitted only once? If so how would I make it otherwise to execute the 10 orders?
                    Also in your script line 123 you say
                    // the name of the order must be Entry or the order will get stuck in the intialize state
                    Does this impact the orders submission to only one order? If so how would you modify to allow for multiple orders submissions?

                    Do you have a sample of multiple orders submission in a loop or better method that works? Thanks!


                    I've also tested with a hardcoded loop limit of 3

                    PHP Code:
                          protected void ChartControl_PreviewKeyDown(object senderKeyEventArgs e)
                          {
                            
                    // LONG Orders
                            
                    TriggerCustomEvent(=>
                            {
                              if (
                    Keyboard.IsKeyDown(Key.NumPad1))
                              {
                                Print(
                    "entryBuyMar****rder!=null : " entryBuyMar****rder!=null);
                                for (
                    int index 0index 3index++)
                                {
                                  
                    entryBuyMar****rder myAccount.CreateOrder(
                                      
                    Instrument,
                                      
                    OrderAction.Buy,
                                      
                    OrderType.Market,
                                      
                    OrderEntry.Manual,
                                      
                    TimeInForce.Day,
                                      
                    1,
                                      
                    0,
                                      
                    0,
                                      
                    string.Empty,
                                      
                    "Entry",
                                      
                    Core.Globals.MaxDate,
                                      
                    null);
                                }

                              }

                              
                    myAccount.Submit(new[] { entryBuyMar****rder });

                            }, 
                    null);
                            
                    e.Handled true
                    But still get the Log Tab error
                    Time Category Message
                    30/05/2022 11:40:10 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)
                    Prints for entryBuyMar****rder!=null
                    True
                    When you say
                    Are you printing the time and all values used in the condition and confirming the condition is evaluating as true and that the line of code is being reached?
                    What other variable would I print in this case you would suggest?
                    The condition is evaluating as true as the 1st order gets submited (i.e. NumPad key 1 is pressed).
                    How would it test/know if possible to test if the condition stops being true for the next orders? I can't find a prints example on this. Thanks!
                    Last edited by PaulMohn; 05-30-2022, 03:48 AM.

                    Comment


                      #55
                      Hello PaulMohn,

                      "entryBuyMar****rder = myAccount.CreateOrder("

                      This is not adding to a list or collection. You are overwriting the variable over and over. There is only one variable here and each time you are assigning an object you are changing where the object reference is pointing to in memory. Meaning the variable points to a different object.

                      Trying using a List<Order> and use .Add() to add to the list.
                      Represents a strongly typed list of objects that can be accessed by index. Provides methods to search, sort, and manipulate lists.

                      Create a new List, add elements to it, and loop over its elements with for and foreach.
                      Chelsea B.NinjaTrader Customer Service

                      Comment


                        #56
                        Hello Chelsea and thanks for the tips.

                        Following your submitOrdersArray list model for the ProfitTarget and StopLoss orders I added a multiOrders list as

                        Class level
                        private List<Order> changeOrdersArray, submitOrdersArray, multiOrders;

                        PHP Code:
                              protected void ChartControl_PreviewKeyDown(object senderKeyEventArgs e)
                              {
                                
                        // LONG Orders
                                
                        TriggerCustomEvent(=>
                                {
                                  if (
                        Keyboard.IsKeyDown(Key.NumPad1))
                                  {
                                    
                        multiOrders = new List<Order>();

                                    Print(
                        "entryBuyMar****rder!=null : " entryBuyMar****rder!=null);
                                    for (
                        int index 0index 3index++)
                                    {
                                      
                        entryBuyMar****rder myAccount.CreateOrder(
                                          
                        Instrument,
                                          
                        OrderAction.Buy,
                                          
                        OrderType.Market,
                                          
                        OrderEntry.Manual,
                                          
                        TimeInForce.Day,
                                          
                        1,
                                          
                        0,
                                          
                        0,
                                          
                        string.Empty,
                                          
                        "Entry",
                                          
                        Core.Globals.MaxDate,
                                          
                        null);

                                      
                        multiOrders.Add(entryBuyMar****rder);
                                    }

                                  }

                                  
                        myAccount.Submit(new[] { entryBuyMar****rder });

                                  
                        myAccount.Submit(multiOrders);

                                }, 
                        null);
                                
                        e.Handled true
                        now it's submitting 3 entries of 1 contract/3 orders as expected. Thanks!
                        But I'm only getting 1 OCO orders pair and the Log Tab error
                        Time Category Message
                        31/05/2022 19:10:37 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)
                        What could be preventing the remaining 2 sets of OCO orders to trigger? How can i get all orders to have their OCO brackets?

                        My end goal will be to have
                        1. all OCO pair to be movable as one, meaning with one single hotkey snippet control the movement Up and Down of the 3 Target orders together. The same for StopLoss Orders with a separate hotkey.
                        2. Then with other hotkeys controls specific single OCO leg or predefined subgroup of them. For example, for the 3 orders have one dedicated hotkey key per Target order and the same for StopLoss orders (6 hotkeys in total).

                        Any tips on how to get the concept down for these aims? I'm not sure how to envisage it with the list suggestion. I suspect I'd have to retrieve somehow the orders present in the multiOrders list. But how if that's the best way? Thanks!

                        Comment


                          #57
                          Hello PaulMohn,

                          Is the order created with <Account>.CreateOrder() null?

                          You might need to loop through and check each element is not null.

                          With OCO are you generating a new string and saving this to a variable to be used all orders in the pairing and ensuring that the OCOID string is not being re-used after an order has filled, cancelled, or rejected?

                          Below are links to examples of OCO.


                          Chelsea B.NinjaTrader Customer Service

                          Comment


                            #58
                            Thanks for the directions.

                            Is the order created with <Account>.CreateOrder() null?

                            You might need to loop through and check each element is not null.
                            I'm not sure if you refer to the profitTargetOrder and stopLossOrder orders, but I think you do as the entryBuyMar****rder did return true as not null in post #54 above.

                            Here's my profitTargetOrder and stopLossOrder orders in your Account_OrderUpdate() method.
                            PHP Code:
                                  private void Account_OrderUpdate(object senderOrderEventArgs orderUpdateArgs)
                                  {

                                    
                            // LONG Order Target and StopLoss OCO orders
                                    
                            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;

                                        if (
                            PrintDetails)
                                          Print(
                            string.Format("{0} | Account_OrderUpdate | placing profit target | currentPtPrice: {1}"orderUpdateArgs.TimecurrentPtPrice));

                                        
                            profitTargetOrder myAccount.CreateOrder(orderUpdateArgs.Order.InstrumentOrderAction.SellOrderType.LimitOrderEntry.AutomatedTimeInForce.DayorderUpdateArgs.QuantitycurrentPtPrice0oco"Profit Target"Core.Globals.MaxDatenull);
                                        
                            submitOrdersArray.Add(profitTargetOrder);
                                      }

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

                                        if (
                            PrintDetails)
                                          Print(
                            string.Format("{0} | Account_OrderUpdate | placing stop loss | currentSlPrice: {1}"orderUpdateArgs.TimecurrentSlPrice));

                                        
                            stopLossOrder myAccount.CreateOrder(orderUpdateArgs.Order.InstrumentOrderAction.SellOrderType.StopMarketOrderEntry.AutomatedTimeInForce.DayorderUpdateArgs.Quantity0currentSlPriceoco"Stop Loss"Core.Globals.MaxDatenull);
                                        
                            submitOrdersArray.Add(stopLossOrder);
                                      }

                                      
                            myAccount.Submit(submitOrdersArray);
                                    } 

                            Since the 1st OCO pair is working doesn't that mean it's not null (at least for the 1st order, it might get changed to null after for 2nd and 3rd orders)? I think the 2nd and 3rd OCO pair don't execute because the Account_OrderUpdate() method only detects/expects/it is set to only detect 1 order (entryBuyMar****rder). But as you can see profitTargetOrder and stopLossOrder are added to the submitOrdersArray list. Would it need to detect the orders in the multiOrders new list (post #56)? I suspect it does need to detect it, but this list gets populated in the separate ChartControl_PreviewKeyDown() method. i suspect i would need to call the multiOrders list somehow in the Account_OrderUpdate() method for it to pick up that there are multiple entryBuyMar****rder orders and not just one. But if that's what it needs, how would you get the Account_OrderUpdate() to pick up the content of the multiOrders list? Thanks!


                            As you can see the OCO string is uniquely generated and saved into the string variable oco (that was your code, thanks!).

                            With OCO are you generating a new string and saving this to a variable to be used all orders in the pairing and ensuring that the OCOID string is not being re-used after an order has filled, cancelled, or rejected?
                            I'm not sure it is not being reused after an order has filled, cancelled, or rejected.

                            I tried adding oco = null; below but to work I needed to move the oco string up to the Account_OrderUpdate() method level
                            PHP Code:
                            private void Account_OrderUpdate(object senderOrderEventArgs orderUpdateArgs)
                            {
                                   
                            string oco     Guid.NewGuid().ToString("N");

                            ...  
                            the the profitTargetOrder and stopLossOrder snippets here

                                    
                            // 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;
                                      
                            oco null;
                                    } 
                            I tested and only the 1st order OCO is generated still no 2nd and 3rd OCO pairs.


                            I just tested adding 2 loops for the profitTargetOrder and stopLossOrder snippets in the Account_OrderUpdate() method as

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

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

                            Now it does trigger the 3 OCO pairs as expected. Thanks!

                            But after testing if they trigger I saw only the 1st OCO pair triggers/executes and the 2 remaining pairs get cancelled with it but no order is submited (i.e the 2 remaining contracts remain with their OCO pairs gone).

                            So I checked the Orders Tab and discovered that the same OCO ID gets generated for all the 6 OCO single orders. I suspect that's the cause for only the 1st OCO pair to execute while the 2 remaining OCO pairs just trigger/cancel themselves but do not actually execute their orders. Is that the right cause? If so How would you get unique OCO IDs for each pair? If you know of a sample/or have a better suggestion than using the 2 added loops method thanks for sharing. Thanks!

                            Ah, I found a way to get specific OCO ID per pair by just adding +index to the oco parameter in the profitTargetOrder and stopLossOrder snippets as
                            PHP Code:
                            for (int index 0index 3index++)
                            {
                                 
                            profitTargetOrder myAccount.CreateOrder(
                                                
                            orderUpdateArgs.Order.Instrument,
                                                
                            OrderAction.Sell,
                                                
                            OrderType.Limit,
                                                
                            OrderEntry.Automated,
                                                
                            TimeInForce.Day,
                                                
                            orderUpdateArgs.Quantity,
                                                
                            currentPtPrice,
                                                
                            0,
                                                
                            oco+index,
                                                
                            "Profit Target",
                                                
                            Core.Globals.MaxDate,
                                                
                            null);
                                 
                            submitOrdersArray.Add(profitTargetOrder);

                            PHP Code:
                            for (int index 0index 3index++)
                            {
                                 
                            stopLossOrder myAccount.CreateOrder(
                                                
                            orderUpdateArgs.Order.Instrument,
                                                
                            OrderAction.Sell,
                                                
                            OrderType.StopMarket,
                                                
                            OrderEntry.Automated,
                                                
                            TimeInForce.Day,
                                                
                            orderUpdateArgs.Quantity,
                                                
                            0,
                                                
                            currentSlPrice,
                                                
                            oco+index,
                                                
                            "Stop Loss",
                                                
                            Core.Globals.MaxDate,
                                                
                            null);
                                 
                            submitOrdersArray.Add(stopLossOrder);

                            So now it works executing all OCO orders. Thanks!

                            But now I'm wondering how to make my hotkeys move multiple OCO leg at once (not just as currently only the 1st OCO order's leg. Any tip/sample on doing that? Thanks!

                            For example, here's one of my Hotkeys snippet for moving the Target order
                            PHP Code:
                                    // Move Up Target OCO Order
                                    
                            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);

                                          
                            profitTargetOrder.LimitPriceChanged currentPtPrice;

                                          
                            changeOrdersArray.Add(profitTargetOrder);

                                          
                            myAccount.Change(changeOrdersArray);
                                        }
                                      }
                                      else if (
                            entrySellMar****rder != null)
                                      {

                                        if (
                            Keyboard.IsKeyDown(Key.NumPad7) && !(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
                                        {
                                          
                            changeOrdersArray = new List<Order>();

                                          
                            currentPtPrice profitTargetOrder.LimitPrice - (ProfitTargetMove TickSize);

                                          
                            profitTargetOrder.LimitPriceChanged currentPtPrice;

                                          
                            changeOrdersArray.Add(profitTargetOrder);

                                          
                            myAccount.Change(changeOrdersArray);
                                        }
                                      }
                                    }, 
                            null);
                                    
                            e.Handled true

                            As you can see it it currently set to pick up (I think) the 1st profitTargetOrder added to the changeOrdersArray list.
                            How would I set it to pick up more that 1 order in the changeOrdersArray list? How would I access more than one order? And then make it to change that subset of the changeOrdersArray list? Thanks!
                            Last edited by PaulMohn; 05-31-2022, 02:43 PM.

                            Comment


                              #59
                              Hello PaulMohn,

                              I am referring to the order that caused the error.
                              Which order caused the error?

                              A string is a non-nullable type from what I understand and cannot be set to null.
                              However, I am not understanding, why are you trying to set the string to null?
                              The string should be set to a generated OCOID before submitting oco linked orders.
                              If an order has filled, cancelled, or rejected, that OCOID can no longer be used and a new OCO string needs to be generated.

                              I do not have any examples of the exact specific logic you have requested. I have already provided examples of capturing key presses and working with OCO.

                              When the key is pressed what are you wanting to do? Change the stop and limit price of orders? This is done with <Account>.Change().


                              Please reduce the information you are providing to just the relevant part you need help with.

                              Where are you specifically stuck? Are you still stuck on OCOIDs and this is why you are posting the code about OCO?

                              Chelsea B.NinjaTrader Customer Service

                              Comment


                                #60
                                Thanks Chelsea for the request.
                                For now everything seems to be working but for my attempt at

                                changing profitTargetOrder of more than 1 Target OCO at the same time.

                                For example i have 3 Targets with those OCO IDs
                                461c8ed1ea00427bb4c38752fbfb371a0
                                461c8ed1ea00427bb4c38752fbfb371a1
                                461c8ed1ea00427bb4c38752fbfb371a2

                                How can I move all 3 or 2 of those targets with my NumPad7 Hotkey?

                                Currently my below snippet uses
                                profitTargetOrder.LimitPriceChanged = currentPtPrice;

                                to change the order.

                                I tried something like
                                profitTargetOrder[0].LimitPriceChanged = currentPtPrice;
                                profitTargetOrder[1].LimitPriceChanged = currentPtPrice;
                                ​​​​​​​profitTargetOrder[2].LimitPriceChanged = currentPtPrice;

                                to access each individual order
                                but that's returning a compile error.

                                PHP Code:
                                        // Move Up Target OCO Order
                                        
                                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);

                                              
                                profitTargetOrder.LimitPriceChanged currentPtPrice;

                                              
                                changeOrdersArray.Add(profitTargetOrder);

                                              
                                myAccount.Change(changeOrdersArray);
                                            }
                                          }
                                          else if (
                                entrySellMar****rder != null)
                                          {

                                            if (
                                Keyboard.IsKeyDown(Key.NumPad7) && !(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
                                            {
                                              
                                changeOrdersArray = new List<Order>();

                                              
                                currentPtPrice profitTargetOrder.LimitPrice - (ProfitTargetMove TickSize);

                                              
                                profitTargetOrder.LimitPriceChanged currentPtPrice;

                                              
                                changeOrdersArray.Add(profitTargetOrder);

                                              
                                myAccount.Change(changeOrdersArray);
                                            }
                                          }
                                        }, 
                                null);
                                        
                                e.Handled true
                                I'm thinking now of maybe accessing each profitTargetOrder from the changeOrdersArray list but I'm not sure how nor if that's the correct way to do it.
                                Is seems that in order to change the order one must call the order variable (i.e. profitTargetOrder).

                                Or I'm thinking of accessing them via their OCO ID but i'm still even less sure of how and if it's possible.

                                Do you have any tip on this? Thanks!

                                Comment

                                Latest Posts

                                Collapse

                                Topics Statistics Last Post
                                Started by JoMoon2024, Today, 06:56 AM
                                0 responses
                                6 views
                                0 likes
                                Last Post JoMoon2024  
                                Started by Haiasi, 04-25-2024, 06:53 PM
                                2 responses
                                18 views
                                0 likes
                                Last Post Massinisa  
                                Started by Creamers, Today, 05:32 AM
                                0 responses
                                6 views
                                0 likes
                                Last Post Creamers  
                                Started by Segwin, 05-07-2018, 02:15 PM
                                12 responses
                                1,786 views
                                0 likes
                                Last Post Leafcutter  
                                Started by poplagelu, Today, 05:00 AM
                                0 responses
                                3 views
                                0 likes
                                Last Post poplagelu  
                                Working...
                                X