Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Buy stop or buy stop limit orders can't be placed below the market

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

    Buy stop or buy stop limit orders can't be placed below the market

    Hello Team,

    I've been working a problem that has plagued me for some time. I get the following error many times while testing my strategy in Playback/Market Replay.

    Click image for larger version  Name:	Error.png Views:	0 Size:	4.9 KB ID:	1301867

    It doesn't happen for all trades but for the ones it does happen to it's very consistent. I've added many Print() statements to try and find where the problem is. This is what I've come up.

    Here is a snippet of the relevant code:

    In OnBarUpdate():
    Code:
    EnterShort(Convert.ToInt32(DefaultQuantity), "ShortEntry");
    
       Print("\nBefore SetStopLoss, Close[0]("+Close[0]+") + stopLoss("+stopLoss+") = " + (Close[0]+stopLoss));
    SetStopLoss("ShortEntry", CalculationMode.Price, Close[0]+stopLoss, false);
       Print("\nAfter SetStopLoss, Close[0] + stopLoss =" + (Close[0] + stopLoss));
    
    SetProfitTarget("ShortEntry", CalculationMode.Price, Close[0] - takeProfit);
    Print("\nOpen = "+Open[0]+", High = "+High[0]+", Low = "+Low[0]+", Close[0] = "+Close[0]);​
    In OnOrderUpdate():
    Code:
    if (order.OrderState == OrderState.Filled) Print($"\n{Time[0]}: Order Filled: {order.Name} for {order.Quantity} units at {order.AverageFillPrice}\n");
    if (order.OrderState == OrderState.Submitted) Print($"\n{Time[0]}: Order Submitted: {order.Name} for {order.Quantity} units, at {order.LimitPrice}(l)/{order.StopPrice}(s)");​
    This is the Output I see when the error occurs:
    4/26/2024 9:35:30 AM: Order Submitted: ShortEntry for 1 units, at 0(l)/0(s)

    4/26/2024 9:35:30 AM: Order Filled: ShortEntry for 1 units at 17721.75

    4/26/2024 9:35:30 AM: Order Submitted: Stop loss for 1 units, at 0(l)/17721.25(s)
    Strategy 'AS/282061273' submitted an order that generated the following error 'Order rejected'. Strategy has sent cancel requests, attempted to close the position and terminated itself.
    Disabling NinjaScript strategy 'AS/282061273'

    Before SetStopLoss, Close[0](17723.75) + stopLoss(11.9473272927223) = 17735.6973272927

    After SetStopLoss, Close[0] + stopLoss =17735.6973272927

    Open = 17734, High = 17736.25, Low = 17723, Close[0] = 17723.75
    My question is, where does 17721.25 stop loss in the above Output come from? Unless I'm missing something that should not be what the stop is. I see why I get the error, it's certainly below the short Fill (and likely the market). Why is the stop not 17735.75?

    If I change the SetStopLoss and manually write the 'value/price' 17735.75, the error does not occur, as I would expect.
    Code:
    SetStopLoss("ShortEntry", CalculationMode.Price, 17735.75, false);
    4/26/2024 9:35:30 AM: Order Submitted: ShortEntry for 1 units, at 0(l)/0(s)

    4/26/2024 9:35:30 AM: Order Filled: ShortEntry for 1 units at 17721.75

    4/26/2024 9:35:30 AM: Order Submitted: Stop loss for 1 units, at 0(l)/17735.75(s)

    4/26/2024 9:35:30 AM: Order Submitted: Profit target for 1 units, at 17693.25(l)/0(s)

    Before SetStopLoss, Close[0](17723.75) + stopLoss(11.9473272927223) = 17735.6973272927

    After SetStopLoss, Close[0] + stopLoss =17735.6973272927

    Open = 17734, High = 17736.25, Low = 17723, Close[0] = 17723.75​
    I have researched other cases in this forum and these seem to have run across the same error.
    Issue with stop loss
    Error..orders can't be placed below the market

    Reading through them has helped me understand things better and given me some best practices (such as move the EnterShort() below the SetStopLoss() and SetProfitTarget()), but I don't think I see anything that addresses the above behavior specifically.

    Thank you in advance for your help,
    Michael
    Last edited by md4866; 05-06-2024, 10:38 AM.

    #2
    Hello md4866,

    This error may appear when submitting a stop order if the stop price is ahead of the market.

    For a buy stop order, such as when exiting a short position or entering a long position, the stop price must be above the current ask price.
    For a sell stop order, such as when exiting a long position or entering a short position, the stop price must be below the current bid price.

    Order methods that submit / change stop orders where the stop price must be on the correct side of the ask or bid:
    Resolving the error

    There are different approaches to avoiding the invalid order price.

    For the examples below, consider a variable holding your calculated stop price. This could be a price from a custom calculation, or one obtained from an indicator. In these examples 100 will be used as a place holder.
    Code:
    stopPrice = 100; // ← price you have calculated to use as the stop price
    Using Math.Max() / Math.Min() to ensure the calculated stopPrice is above/below the ask/bid:
    Code:
    // ensure sell stop order is below the bid
    stopPrice = Math.Min(stopPrice, GetCurrentBid() - 1 * TickSize);
    ExitLongStopMarket(stopPrice);​
    Code:
    // ensure buy stop order is above the ask
    stopPrice = Math.Max(stopPrice, GetCurrentAsk() + 1 * TickSize);
    ExitShortStopMarket(stopPrice);​
    Using a condition to submit a market order to exit immediately, instead of a stop order, if the stopPrice is ahead of the market:
    Code:
    // if calculated exit sell stopPrice is less than the bid use stopPrice for stop
    // otherwise exit long position immediately with a market order
    if (Position.MarketPosition == MarketPosition.Long)
    {
    // if the stopPrice value is a valid price, use the stopPrice
    if (stopPrice < GetCurrentBid())
    {
    ExitLongStopMarket(stopPrice);
    }
    // otherwise exit immediately with a market order
    else
    {
    ExitLong();
    }
    }
    
    // if calculated exit buy stopPrice is greater than the ask use stopPrice
    // other wise exit short position immediately with a market order
    if (Position.MarketPosition == MarketPosition.Short)
    {
    if (stopPrice > GetCurrentAsk())
    {
    ExitShortStopMarket(stopPrice);
    }
    else
    {
    ExitShort();
    }
    }​
    Set method considerations

    In addition, Set methods cannot be unset and will continue to hold their values for new entry orders.

    This means it is important to reset Set methods using a number of Ticks, Percent, or Currency before placing a new entry (or using a unique signalName for each new entry). (Setting to a specific price may be an invalid price when the entry order fills, especially for entry limit and stop orders)

    The help guide notes:

    “Notes:
    As Set method orders are submitted upon receiving an entry execution, the Set method should be called prior to submitting the associated entry order to ensure an initial level is set.“

    “Tips:
    You may call this method from within the strategy OnBarUpdate() method should you wish to dynamically change the stop loss price while in an open position
    Should you call this method to dynamically change the stop loss price in the strategy OnBarUpdate() method, you should always reset the stop loss price / offset value when your strategy is flat otherwise, the last price/offset value set will be used to generate your stop loss order on your next open position”

    NinjaScript > Language Reference > Strategy > Order Methods > Managed Approach > SetStopLoss()

    Before calling a new entry call the Set methods first using CalculationMode.Ticks, one line above the entry method:
    Code:
    if (Position.MarketPosition == MarketPosition.Flat)
    {
    // call SetStopLoss() with CalculationMode.Ticks one line above calling EnterLong() to reset
    // this ensures the set method is not holding a price value from a previous order which may be invalid when the new entry fills
    SetStopLoss(CalculationMode.Ticks, 20)
    EnterLong();
    }
    
    // after the entry fills, the stop loss can be moved to any desired valid price with CalculationMode.Price
    if (Position.MarketPosition == MarketPosition.Long && Close[0] > Position.AveragePrice + 10 * TickSize)
    {
    // after 10 ticks of profit, set the stop loss to the maximum valid price
    SetStopLoss(CalculationMode.Price, GetCurrentBid() - TickSize);
    }​
    Chelsea B.NinjaTrader Customer Service

    Comment


      #3
      Great! Thank you Chelsea!

      Excellent response. This gives me a lot to work with. I did not realize "Set methods cannot be unset and will continue to hold their values for new entry orders." A very important point. Maybe that can be added to the notes as well. It makes the note "...the Set method should be called prior to submitting the associated entry order..." more paramount.

      I'm not sure why it works when I manually write in the 'value/price', but maybe I missed something. I'll check it out.

      Thank you again,
      Michael

      Comment

      Latest Posts

      Collapse

      Topics Statistics Last Post
      Started by NullPointStrategies, Today, 05:17 AM
      0 responses
      50 views
      0 likes
      Last Post NullPointStrategies  
      Started by argusthome, 03-08-2026, 10:06 AM
      0 responses
      126 views
      0 likes
      Last Post argusthome  
      Started by NabilKhattabi, 03-06-2026, 11:18 AM
      0 responses
      68 views
      0 likes
      Last Post NabilKhattabi  
      Started by Deep42, 03-06-2026, 12:28 AM
      0 responses
      42 views
      0 likes
      Last Post Deep42
      by Deep42
       
      Started by TheRealMorford, 03-05-2026, 06:15 PM
      0 responses
      46 views
      0 likes
      Last Post TheRealMorford  
      Working...
      X