Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Suffering over RealtimeErrorHandling Stop below Market

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

    Suffering over RealtimeErrorHandling Stop below Market

    I am trying to handle the "Stop Price can't be changed below the market.." but so far I didn't achieve a reliable solution and after spending hours reading many threads I am not convinced a solid solution is being provided. I find pieces of the puzzle but not a solid and general one. Why? I hope this thread may help others through the struggle.

    I need a solution able to handle both Rejection caused by a "managed approach" code or/and an ATM operation controlled by a strategy.
    Should the OnOrderUpdate handle both managed approach or Atm operation behavior?

    As start this is the basic code I have.

    The first questions are:
    (After commenting out the Test_Line which cannot be always effective)
    why OnOrderUpdate doesn't report the rejection?


    The code below is essentially a simple breakeven testing for stop below the close by some margin and the OnOrderUpdate code from https://ninjatrader.com/es/support/h...orhandling.htm

    The core code I am using is:
    Code:
    protected override void OnStateChange()
    {
       if (State == State.SetDefaults) RealtimeErrorHandling = RealtimeErrorHandling.IgnoreAllErrors;
    }    
    
    #region BreakEven for Long Positions
                    this.stopMargin = 3; // 3 ticks margin to prevent stop below price
                    if (High[0] > strat.Position.AveragePrice + be1trigger * tickSize)
                    {
                        double stopPricex = Position.AveragePrice + be1plus * tickSize;
    
                        //Test_Line
                        if (stopPricex > GetCurrentBid()]- this.stopMargin * tickSize) stopPricex = GetCurrentBid() - this.stopMargin * tickSize;
    
                        SetStopLoss(labelLong, CalculationMode.Price, stopPricex, false);
    
                    }
    ​​​#endregion BreakEven
    
    #region Rejection Handling
    
           // Code copied from https://ninjatrader.com/es/support/helpGuides/nt8/?realtimeerrorhandling.htm
    
            protected override void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice,
                                        OrderState orderState, DateTime time, ErrorCode error, string nativeError)
            {
                // Assign stopLossOrder 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
                if (/*order.Name == "1S" && */ orderState == OrderState.Filled)
                {
                    Print(Time[0] + ">   " + order.Name + "    " + order.OrderState + "    " + order.OrderType + "    " + order.AverageFillPrice);
                    this.exec1.stopLossOrder = order;
                }
    
                if (this.exec1.stopLossOrder != null && this.exec1.stopLossOrder == order)
                {
                    // Rejection handling
                    if (order.OrderState == OrderState.Rejected)
                    {
                        Print(Time[0] + "    " + order.Name + "    " + order.OrderState + "    " + order.OrderType + "    " + order.AverageFillPrice);
                        // Stop loss order was rejected !!!!
                        // Do something about it here
                    }
                }
            }
    #endregion Rejection Handling
    The order is being rejected but the rejection doesn't show up in OnOrderUpdate..
    What am I missing?
    Last edited by giogio1; 10-23-2024, 02:53 AM.

    #2
    Hello giogio1,

    "I am trying to handle the "Stop Price can't be changed below the market.." but so far I didn't achieve a reliable solution and after spending hours reading many threads I am not convinced a solid solution is being provided. "

    To prevent a stop order from being rejected due to an invalid order price, ensure the stop price is a valid price just before submitting the order. With Set methods, these have to be reset using CalculationMode.Ticks before placing calling a new entry method and then once the entry is filled, the order price change be changed to a specific price with CalculationMode.Price.

    This forum thread provides sample code.


    In a fast moving market, it is advised to choose a stop price that is a few ticks further from the current ask or bid (depending on the order direction).



    "Should the OnOrderUpdate handle both managed approach or Atm operation behavior?"

    AtmStrategy methods do not update with OnOrderUpdate(), OnExecutionUpdate(), or OnPositionUpdate(), and do not affect the strategy performance.

    "Executions from ATM Strategies will not have an impact on the hosting NinjaScript strategy position and PnL - the NinjaScript strategy hands off the execution aspects to the ATM, thus no monitoring via the regular NinjaScript strategy methods will take place (also applies to strategy performance tracking)"



    "The order is being rejected but the rejection doesn't show up in OnOrderUpdate.."

    Print the order.ToString() as the first line of OnBarUpdate(). This will print all native strategy orders made by the strategy. (This does not include AtmStrategy method orders)
    Chelsea B.NinjaTrader Customer Service

    Comment


      #3
      Thank you Chelsea, i read it carefully. It is helpful. I still have questions and I list them this way just to facilitate.

      - With "AtmStrategy methods do not update with OnOrderUpdate(), OnExecutionUpdate(), or OnPositionUpdate(), and do not affect the strategy performance" is Ninjatrader implying that ATM, even with trailing stop actvated never suffer of stop-below-market-order-rejection ?

      - Is "AtmStrategy methods do not update with OnOrderUpdate(), OnExecutionUpdate(), or OnPositionUpdate(), and do not affect the strategy performance" true also with ATM affected by AtmStrategyChangeStopTarget() ?

      - Do I understand correctly that SetMethods can be thought as internally implemented with isLiveUntilCancelled = true?

      ​Thank you
      Gio
      Last edited by giogio1; 10-23-2024, 04:19 PM.

      Comment


        #4
        (I separated this code problem from the questions above for clarity)

        I wrote the simplest and shorted code I could think to facilitate that works on a 100 bars chart and then pressing the play button in playback.
        The code forces a order with stop below Bid at bar 105 in playback via SetStopLoss() but OnOrderUpdate() doesn't see any rejection even though it is clearly getting rejected. The picture shows everything, output, chart and running code.

        Why Rejection is not detected by OnOrderUpdate ?
        Thank You
        Gio

        Code:
        using System;
        using NinjaTrader.Cbi;
        namespace NinjaTrader.NinjaScript.Strategies
        {
            public class Test_OnOrderUpdate_Reject : Strategy
            {
                int ccc = 0;
        
                protected override void OnStateChange()
                {
                    if (State == State.SetDefaults)
                    {
                        ClearOutputWindow();
                        RealtimeErrorHandling = RealtimeErrorHandling.IgnoreAllErrors;
                        Calculate = Calculate.OnBarClose;
                        EntriesPerDirection = 1;
                        EntryHandling = EntryHandling.UniqueEntries;
                    }
                }
        
                protected override void OnBarUpdate()
                {
                    this.ccc = CurrentBar;
                    if (State == State.Historical)    return;
        
                    if (ccc == 101)
                    {
                        SetStopLoss("LL", CalculationMode.Ticks, (10), false);
                        SetProfitTarget("LL", CalculationMode.Ticks, 10);
                        EnterLong("LL");
                    }
                    if (ccc == 104)
                    {
                        SetStopLoss("LL", CalculationMode.Price, Position.AveragePrice + 10, false);
                    }
                }
        
                protected override void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice,
                                            OrderState orderState, DateTime time, ErrorCode error, string nativeError)
                {
                    Print(Time[0] + "<   " + order.ToString());
                }
            }
        }
        Test_OnOrderUpdate_Reject.cs

        Click image for larger version  Name:	OnOrderUpdate No Rejects.jpg Views:	0 Size:	946.5 KB ID:	1322410
        Last edited by giogio1; 10-23-2024, 04:21 PM.

        Comment


          #5
          I activated TraceOrder and see the Rejection, but only with TraceOrders thus they cannot be handled by OnOrderUpdate().
          Is this correct or is a bug?
          If this is what is supposed to do then I can only rely of a certain number of ticks away from the Bid all the time for high volatiitly situations. But such approach appears to be quite unreliable to me or costly.
          Can you clarify? Thank you.
          Gio


          Click image for larger version

Name:	Order Reject Trace.jpg
Views:	98
Size:	489.9 KB
ID:	1322418

          Comment


            #6
            Hello Gio,

            "is Ninjatrader implying that ATM, even with trailing stop actvated never suffer of stop-below-market-order-rejection ?"

            Unfortunately no, order submission and change rejections can still occur with ATMs, especially if using Price as the mode. If the stop distance is very close to the current bid or ask, and the ask or bid moves very quickly, the ATM order change can be on the other side of the market and result in a rejection.

            Orders submitted with AtmStrategy methods are like using the addon approach and placing the order directly through an account. The NinjaScript strategy doesn't see the order and it doesn't update any of the strategy's order update methods like OnOrderUpdate() or OnExecutionUpdate() and do not change the strategy's position.

            Only orders submitted with native NinjaScript Strategy methods (like EnterLong() / ExitLongStopMarket() / SetStopLoss() / SubmitOrderUnmanaged() etc) and are submitted by that instance of the strategy can be seen by the strategy and update the position and order update methods.

            "true also with ATM affected by AtmStrategyChangeStopTarget()"

            Yes, AtmStrategyChangeStopTarget() changes the stop and target from an entry made with AtmStrategyCreate(). Any orders created with AtmStrategyCreate() or placed manually, or directly through an account are not seen by the NinjaScript Strategy.

            "Do I understand correctly that SetMethods can be thought as internally implemented with isLiveUntilCancelled = true"

            You can think of them that way. They will only automatically cancel if the other order in the OCO pair is filled, rejected, or cancelled, or if the position opened by the same entry is closed with another exit order.

            "Why Rejection is not detected by OnOrderUpdate ?"

            The order change is rejected, but the order itself is not in a rejected state. As the change is rejected, the order continues working at the price it was previously working at with State.Accepted (at the previous price).

            The ErrorCode error parameter will be 'UnableToChangeOrder' and the string comment will be 'Stop price can't be changed above the market'. This is how you can detect an order change was rejected.

            protected override void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string comment)


            Note, once a Set method is called, it cannot be unset. The Set method will continue trying to change the price to the invalid price on every bar update unless you call SetStopLoss() again with a valid price, or using the CalculationMode.Ticks with a positive integer.
            Chelsea B.NinjaTrader Customer Service

            Comment


              #7
              Thank you Chelsea. Your answer have been so clear that much of the fog I had in my brain is gone.

              I am coding via managed approach because I want to be able to backtest but I'd like to see some reliability of the executions.
              So I have a general question left in my mind that has never left me. Hopefully the question makes sense.
              Premised that I am planning to trade using Continuum and Rithmic and initially simply thinking to scale out at two targets plus one runner.
              Which approach one of the three approaches (Managed/UnManaged/ATM) do you think would get me to the best handling of partial fills and failed order/executions. Would the differences among the three methods under the light of the reliability objective be significant ?
              Gio

              Comment


                #8
                Hello Gio,

                A strategy can be backtested using the managed or unmanaged approach, it cannot be backtested with AtmStrategy methods.

                From the help guide:
                "ATM Strategies operate in real-time only and will not execute on historical data thus they can't be backtested"


                Use the managed or unmanaged approach with native strategy methods so the strategy can be backtested. With either approach the logic would need to set the proper quantity for exits after an entry part fills. Or you could wait until the entry order has finished filling to submit the exit orders.

                The difference between the managed and unmanaged approach, is the managed approach will attempt to prevent unwanted positions with internal order handling rules and will manage the position when reversing. The unmanaged approach has no rules and does not try to manage the position, requiring the logic to handle everything.


                Chelsea B.NinjaTrader Customer Service

                Comment


                  #9
                  Thank you Chelsea. In other words I interpret your reply as I can get the same reliability with both managed and unmanaged or ATM in live trading. It just needs to be coded to handle it properly. Do I understand correctly?

                  Comment


                    #10
                    Hello giogio1,

                    I would agree with this sentiment.

                    Different approaches have different considerations, but in the end they all send the same order to the exchange.
                    Chelsea B.NinjaTrader Customer Service

                    Comment

                    Latest Posts

                    Collapse

                    Topics Statistics Last Post
                    Started by NullPointStrategies, Yesterday, 05:17 AM
                    0 responses
                    63 views
                    0 likes
                    Last Post NullPointStrategies  
                    Started by argusthome, 03-08-2026, 10:06 AM
                    0 responses
                    139 views
                    0 likes
                    Last Post argusthome  
                    Started by NabilKhattabi, 03-06-2026, 11:18 AM
                    0 responses
                    75 views
                    0 likes
                    Last Post NabilKhattabi  
                    Started by Deep42, 03-06-2026, 12:28 AM
                    0 responses
                    45 views
                    0 likes
                    Last Post Deep42
                    by Deep42
                     
                    Started by TheRealMorford, 03-05-2026, 06:15 PM
                    0 responses
                    50 views
                    0 likes
                    Last Post TheRealMorford  
                    Working...
                    X