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

Unmanaged Order Quantity

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

    Unmanaged Order Quantity

    Originally posted by NinjaTrader_ChelseaB View Post
    Hello Community,

    I've had to make changes to these scripts once again.

    With NinjaTrader 8, order objects returned from an order method may not be an equal object to the order object for the same order in OnOrderUpdate.

    From the help guide:
    // Assign entryOrder in OnOrderUpdate() to ensure the assignment occurs when expected.
    // This is more reliable than assigning Order objects in OnBarUpdate, as the assignment is not guaranteed to be complete if it is referenced immediately after submitting.

    Below is a publicly available link to the help guide.
    https://ninjatrader.com/support/help...rderupdate.htm

    This is especially noticeable in Market Replay.

    The NinjaTrader 7 versions can be found in the post linked below.
    https://ninjatrader.com/support/foru...604#post478604

    As a heads up, these scripts are just examples. Each approach has different aspects and limitations and may place orders at different times. These scripts are not designed to perfectly produce the same results. Instead, these are educational examples designed to show how one would move a stop and limit order with custom logic.

    (Update Sept 12th, 2018: Small change to ProfitChaseStopTrailUnmanagedExample logic cancelling stop and target to start flat. Changes to all three with prints.)

    (Update April 16th, 2020: Changed initial target placement price to use ProfitTargetDistance instead of hard coded 10)

    (Update Oct 28th, 2020: Added ProfitChaseStopTrailIndicatorExample)

    (Update Aug 3rd, 2021: Corrected ProfitChaseStopTrailUnmanagedExample line 215 to use StopLossDistance when calculating stop price instead of ProfitTargetDistance)
    Hi Chelsea,

    How to get the SubmitOrderUnmanaged() quantity to detect and use the manual order quantity? I don't find any valid syntax example in the documentation.

    My strategy as default has 1 as quantity:
    SubmitOrderUnmanaged(0, OrderAction.Buy, OrderType.StopMarket, 1, 0, PositionAccount.AveragePrice +30*TickSize, "", @"Exit Short" );



    But I need for it to use whatever quantity the manually entered order it's gonna manage the exit of has.
    For example, if the manually entered order has 5 contracts then the SubmitOrderUnmanaged() should automatically detect 5 contracts and execute a 5 contracts quantity exit.


    How do I set the quantity?


    Would PositionAccount.Quantity work?
    SubmitOrderUnmanaged(0, OrderAction.Buy, OrderType.StopMarket, PositionAccount.Quantity, 0, PositionAccount.AveragePrice +30*TickSize, "", @"Exit Short" );



    What potential problem could there be with that way? For example if I have 2 position on 2 different instruments at the same time, will it auto-detect and auto-manage the correct position separately?

    If not what best other way/ways do you suggest?

    Thank you for an example.
    Last edited by Cormick; 08-19-2021, 12:14 AM.

    #2
    Hi Cormick,

    The best way to manage stop loss and target for the order is to use OnExecutionUpdate to detect when the order has been filled. We have an example here:


    Since you are doing manually placed orders, you need to set up an Addon style account object and use the OnExecution event as shown here:


    Kind regards.
    Chris L.NinjaTrader Customer Service

    Comment


      #3
      Hi Chris,

      Thanks for the answer.

      Thank you for the commented SampleOnOrderUpdate_NT8.zip sample reference. Potential typo line 79:
      entryOrder1 for entryOrder

      Line 93:
      stopOrder = ExitLongStopMarket(0, true, stopOrder.Quantity, Position.AveragePrice, "MyStop", "MyEntry");


      For my use, would that do in detecting the exact manually entered order quantity? If not, why not, and what else would?

      initialExitOrderLong = SubmitOrderUnmanaged(0, OrderAction.Sell, OrderType.StopMarket, 1, 0, PositionAccount.AveragePrice -30*TickSize, "", @"Exit Long FULL STOP" );

      initialExitOrderLong = SubmitOrderUnmanaged(0, OrderAction.Sell, OrderType.StopMarket, initialExitOrderLong.Quantity, 0, PositionAccount.AveragePrice -30*TickSize, "", @"Exit Long FULL STOP" );



      Thank you for the Addon style account object and the OnExecution event reference too.

      I don't find any OnExecution event reference in the documentation page you provided:

      Do you mean the last snippet example:

      private void OnExecutionUpdate(object sender, ExecutionEventArgs e)
      {
      // Do something with the execution update
      }

      If that is the reference you mean, I don't understand it as it's to poor of an example (it demonstrates nothing).

      I checked next the ExecutionUpdate page (was that you reference)?


      There too too poor of an example.

      Do you have other samples useful in context? Thanks.



      Since you are doing manually placed orders, you need to set up an Addon style account object and use the OnExecution event as shown here:
      https://ninjatrader.com/support/help...ount_class.htm
      Do you please have samples examples of an Addon code useful in context? I don't find any on the documentation page. Thank you.

      Comment


        #4
        Hi Cormick,

        You would need to capture the order.Filled quantity in OnExecutionUpdate e.g.

        Code:
        if (execution.Order.OrderState == OrderState.PartF illed)
                            {
                                stopOrder = ExitLongStopMa rket(0, true, execution.Order.Filled, execution.Or der.AverageFillPrice - 4 * TickSize, "MyStop", "MyEntry");
                                targetOrder = ExitLongLimi t(0, true, execution.Order.Filled, execution.Order .AverageFillPrice + 8 * TickSize, "MyTarget", "MyE ntry");
                            }
                            // Update our exit order quantities once orderstate  turns to filled and we have seen execution quantit ies match order quantities
                            else if (execution.Order.Order State == OrderState.Filled && sumFilled == executi on.Order.Filled)
                            {
                                // Stop-Loss order for OrderState.Filled
                                stopOrder = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Or der.AverageFillPrice - 4 * TickSize, "MyStop", "MyEntry");
                                targetOrder = ExitLongLimi t(0, true, execution.Order.Filled, execution.Order .AverageFillPrice + 8 * TickSize, "MyTarget", "MyE ntry");
                            }
        The ExecutionUpdate event for Addon style account object is here:


        Kind regards,
        -ChrisL
        Chris L.NinjaTrader Customer Service

        Comment


          #5
          Hi Chris,

          Thank you for the reply.

          I was aware of the order.Filled quantity in OnExecutionUpdate snippet you mention, thanks.

          My 1st issue is that the SampleOnOrderUpdate_NT8.zip script is geared for automated orders,
          not for unmanaged manually entered orders.

          It uses the entryOrder variable / MyEntry order label. Those are for automated orders.
          That's clearly not what I need.

          See the entryOrder variable / MyEntry order label at the following lines https://pastebin.com/qmczyy1z

          Line 33:

          private Order entryOrder = null;

          Line 65-66:
          1. if (entryOrder != null)
          2. entryOrder= GetRealtimeOrder(entryOrder);


          Lines 77 to 81:
          1. if (entryOrder== null && Position.MarketPosition == MarketPosition.Flat && CurrentBar > BarsRequiredToTrade)
          2. {
          3. /* Enter Long. We will assign the resulting Order object to entryOrder1 in OnOrderUpdate() */
          4. EnterLong(1, "MyEntry");
          5. }

          Lines 103-113:
          1. if (order.Name == "MyEntry")
          2. {
          3. entryOrder= order;
          4. // Reset the entryOrder object to null if order was cancelled without any fill
          5. if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
          6. {
          7. entryOrder = null;
          8. sumFilled = 0;
          9. }
          10. }

          Lines 120-139:
          1. if (entryOrder!= null && entryOrder== execution.Order)
          2. {
          3. if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
          4. {
          5. // We sum the quantities of each execution making up the entry order
          6. sumFilled += execution.Quantity;
          7. // Submit exit orders for partial fills
          8. if (execution.Order.OrderState == OrderState.PartFilled)
          9. {
          10. stopOrder = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - 4 * TickSize, "MyStop", "MyEntry");
          11. targetOrder = ExitLongLimit(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + 8 * TickSize, "MyTarget", "MyEntry");
          12. }
          13. // Update our exit order quantities once orderstate turns to filled and we have seen execution quantities match order quantities
          14. else if (execution.Order.OrderState == OrderState.Filled && sumFilled == execution.Order.Filled)
          15. {
          16. // Stop-Loss order for OrderState.Filled
          17. stopOrder = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - 4 * TickSize, "MyStop", "MyEntry");
          18. targetOrder = ExitLongLimit(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + 8 * TickSize, "MyTarget", "MyEntry");
          19. }
          Lines 142-146:
          1. if (execution.Order.OrderState != OrderState.PartFilled && sumFilled == execution.Order.Filled)
          2. {
          3. entryOrder= null;
          4. sumFilled = 0;
          5. }
          I don't need a method to detect orders with automated entry as the SampleOnOrderUpdate_NT8.zip demonstrates.
          What I need is detection of the manually entered orders, i.e. the orders I entered manually by pressing the Buy Mkt or Sell Mkt buttons on the ChartTrader panel.

          If the OnExecutionUpdate() snippet you say does work for manually entered orders does in fact work, clearly nothing in the SampleOnOrderUpdate_NT8.zip shows how it does so.
          Instead it shows only how to detect orders with automated entry (which is unusable for the given purpose):
          By
          • creating a variable entryOrder (line 33),
          • assigning it an automatically entered order (EnterLong(1, "MyEntry") (line80); / entryOrder= order; (line 105)),
          • and then using that automatically order name/label as reference for use in the stopOrder variable of the ExitLongStopMarket() method (stopOrder = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - 4 * TickSize, "MyStop", "MyEntry") (line 130);



          The 2nd issue is I don't use the ExitLongStopMarket() method.

          ExitLongStopMarket(int barsInProgressIndex, bool isLiveUntilCancelled, int quantity, double stopPrice, string signalName, string fromEntrySignal)

          I use instead the SubmitOrderUnmanaged() method.
          SubmitOrderUnmanaged(int selectedBarsInProgress, OrderAction orderAction, OrderType orderType, int quantity, double limitPrice, double stopPrice, string oco, string signalName)


          There are no string fromEntrySignal parameter with the SubmitOrderUnmanaged() method.
          Therefore I cannot use the "MyEntry" reference as shown in the SampleOnOrderUpdate_NT8.zip script.

          How do I adapt my SubmitOrderUnmanaged() method?

          initialExitOrderLong = SubmitOrderUnmanaged(0, OrderAction.Sell, OrderType.StopMarket, initialExitOrderLong.Quantity, 0, PositionAccount.AveragePrice -30*TickSize, "", @"Exit Long FULL STOP" );

          From the example, here's what I've come up to so far:

          stopOrder = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - 4 * TickSize, "MyStop", "MyEntry");

          initialExitOrderLong = SubmitOrderUnmanaged(0, OrderAction.Sell, OrderType.StopMarket, execution.Order.Filled, 0, execution.Order.PositionAccount.AveragePrice -30*TickSize, "", @"Exit Long FULL STOP" );

          But there's no way to reference/assign it to the manually entered/unmanaged order in this syntax.

          How do reference/assign it to the manually entered/unmanaged order other than by linking it to the (absent in context) entryOrder/myEntry?


          My full (Long Only) OnExecutionUpdate snippet:

          protected override void OnExecutionUpdate(Execution execution, string executionId, double price, int quantity, MarketPosition marketPosition, string orderId, DateTime time)
          {
          if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
          {
          // We sum the quantities of each execution making up the entry order
          sumFilled += execution.Quantity;

          // Submit exit orders for partial fills
          if (execution.Order.OrderState == OrderState.PartFilled)
          {
          initialExitOrderLong = SubmitOrderUnmanaged(0, OrderAction.Sell, OrderType.StopMarket, execution.Order.Filled, 0, execution.Order.PositionAccount.AveragePrice -30*TickSize, "", @"Exit Long FULL STOP" );
          }
          // Update our exit order quantities once orderstate turns to filled and we have seen execution quantities match order quantities
          else if (execution.Order.OrderState == OrderState.Filled && sumFilled == execution.Order.Filled)
          {
          // Stop-Loss order for OrderState.Filled
          initialExitOrderLong = SubmitOrderUnmanaged(0, OrderAction.Sell, OrderType.StopMarket, execution.Order.Filled, 0, execution.Order.PositionAccount.AveragePrice -30*TickSize, "", @"Exit Long FULL STOP" );

          }

          // Resets the entryOrder object and the sumFilled counter to null / 0 after the order has been filled
          if (execution.Order.OrderState != OrderState.PartFilled && sumFilled == execution.Order.Filled)
          {
          sumFilled = 0;
          }
          }

          // Reset our stop order and target orders' Order objects after our position is closed. (1st Entry)
          if ((stopOrder != null && stopOrder == execution.Order) || (targetOrder != null && targetOrder == execution.Order))
          {
          if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled)
          {
          initialExitOrderLong = null;
          }
          }
          }



          The 3rd issue is that my code separates Long and Short conditions that way:

          if (PositionAccount.MarketPosition == MarketPosition.Long)
          {
          {
          StopLossModeLong = 0;
          }


          // Set 2
          if ((PositionAccount.MarketPosition == MarketPosition.Long)
          && (initialExitOrderLong == null)
          && (StopLossModeLong == 0))
          {
          initialExitOrderLong = SubmitOrderUnmanaged(0, OrderAction.Sell, OrderType.StopMarket, 1, 0, PositionAccount.AveragePrice -30*TickSize, "", @"Exit Long FULL STOP" );
          }
          ...

          else if (PositionAccount.MarketPosition == MarketPosition.Short)
          {
          {
          StopLossModeShort = 0;
          }


          // Set 2
          if ((PositionAccount.MarketPosition == MarketPosition.Short)
          && (initialExitOrderShort == null)
          && (StopLossModeShort == 0))
          {
          initialExitOrderShort = SubmitOrderUnmanaged(0, OrderAction.Buy, OrderType.StopMarket, 1, 0, PositionAccount.AveragePrice +30*TickSize, "", @"Exit Short FULL STOP" );
          }
          But the OnExecutionUpdate() method only checks for status, not position direction. Therefore the following issues arises:


          Long example:
          A Long order is filled and the Unmanaged short stop order is assigned to it in place of the Unmanaged long stop order (since the OnExecutionUpdate() method only checks for status, and does not distinguish Long or Short— no parameter for it).
          I've checked the execution page, and there's no mention in the syntax of available distinct Long and Short parameter.


          Same issue for the Short side.

          How do I solve this 3rd issue given that no position direction parameter is available with the OnExecutionUpdate() method syntax?
          What working workaround do you suggest?


          Attached Files

          Comment


            #6
            [10k characters reached]

            I 've checked the Addon page for PositionUpdate, thanks.



            And the developing add on page:



            Apparently it is a script for some extra tab. I do not need an extra tab for the simple purpose of getting the position quantity.

            What simplest way can I achieve the intended result?

            Is it possible to use the Add On code within the strategy script instead of in an extra window?

            I've checked the Ninjascript Editor and there is a New Addon feature available:





            Also checked those addon pages:



            Other Uses for an AddOn
            An AddOn does not require its own window to function. It can instead be used to accomplish non-UI-driven functionality across the platform, such as monitoring market data or accessing account, position, and order information.



            What sample can you provide for an Addon added to a strategy?

            How to correlate it to the Unmanaged order in the strategy code?

            Comment


              #7
              Hi Cormick,

              I found this example indicator that can submit and modify orders:


              The concept of submitting orders through an indicator is an advanced topic of NinjaScript, please make sure you have at least an intermediate to advanced level in NInjaScript programming before doing something like this, otherwise, please use NinjaScript Strategies and manage your orders with the unmanaged approach. If something in your script is not working properly, please use the Print() method to print data from the script for debugging purposes, the support team will not be able to look through your custom code and debug.

              Kind regards,
              -ChrisL

              The NinjaTrader Ecosystem website is for educational and informational purposes only and should not be considered a solicitation to buy or sell a futures contract or make any other type of investment decision. The add-ons listed on this website are not to be considered a recommendation and it is the reader's responsibility to evaluate any product, service, or company. NinjaTrader Ecosystem LLC is not responsible for the accuracy or content of any product, service or company linked to on this website.
              Chris L.NinjaTrader Customer Service

              Comment


                #8
                Hi Chris,

                Thanks for the answer.

                I was aware of the Tick Hunter Bot script:

                The Unmanaged approach is simpler in context— simply getting the position quantity of the manually entered order.


                I studied the suggestions you pointed in post #2:



                You mentioned the OnExecutionUpdate and Addon approaches as valid approaches.
                I found 3 issues with the OnExecutionUpdate that need addressing.

                The 3 issues Summary:

                1st issue:

                How do I use the OnExecutionUpdate without the entryOrder variable?


                2nd Issue:

                There are no string fromEntrySignal parameter with the SubmitOrderUnmanaged() method.
                Therefore I cannot use the "MyEntry" reference as shown in the SampleOnOrderUpdate_NT8.zip script.

                But there's no way to reference/assign it to the manually entered/unmanaged order in this syntax.

                How do I reference/assign it to the manually entered/unmanaged order other than by linking it to the (absent in context) entryOrder/myEntry?


                3rd issue:


                The OnExecutionUpdate() method only checks for status, not position direction.
                Given that no position direction parameter is available with the OnExecutionUpdate() method syntax, how to make is detect Long versus Short orders and assign it the corresponding Stop Order?




                The Addon documentation states no need for an extra window, therefore I won't use the extra tab preferably.

                What sample can you provide for an Addon added to a strategy and not to an extra tab?

                How to correlate it to the Unmanaged order in the strategy code?



                If you don't know the issues' answers or don't find easy ways to work around them, can you please ask a colleague for them?

                It shouldn't be that complicated just detecting the number of contracts of an order, since it does already detect the order itself.

                I think Jim mentioned a different way in a previous post:

                https://ninjatrader.com/support/foru...43#post1164143
                https://ninjatrader.com/support/foru...58#post1165158

                AdoptAccountPositionTestUnmanaged.zip

                Would Position.Quantity work?

                Does Jim know how to adapt it to the current context if it need to be adapted?

                Thank you a lot for your help!

                Comment


                  #9
                  Hi Cormick,

                  If you are using an Account object, you must submit the protective order with the Account.CreateOrder() and Account.Submit(). The best way to have an addon that reacts to manual orders is to add your own custom buttons to the chart (example here). These buttons will enter the market using Account.CreateOrder, which can be given a signal name. Using this signal name you can more easily apply a stop order to this order within OnExecutionUpdate since there is a script-defined signal name for the order rather than the blank name returned by the Chart Trader buttons.

                  Kind regards,
                  -ChrisL


                  Chris L.NinjaTrader Customer Service

                  Comment

                  Latest Posts

                  Collapse

                  Topics Statistics Last Post
                  Started by PaulMohn, Today, 12:36 PM
                  2 responses
                  16 views
                  0 likes
                  Last Post PaulMohn  
                  Started by Conceptzx, 10-11-2022, 06:38 AM
                  2 responses
                  53 views
                  0 likes
                  Last Post PhillT
                  by PhillT
                   
                  Started by Kaledus, Today, 01:29 PM
                  0 responses
                  3 views
                  0 likes
                  Last Post Kaledus
                  by Kaledus
                   
                  Started by yertle, Yesterday, 08:38 AM
                  8 responses
                  37 views
                  0 likes
                  Last Post ryjoga
                  by ryjoga
                   
                  Started by rdtdale, Today, 01:02 PM
                  1 response
                  6 views
                  0 likes
                  Last Post NinjaTrader_LuisH  
                  Working...
                  X