• If this is your first visit, you will have to register before you can post. To view messages, please scroll below and select the forum that you would like to visits. Questions? Be sure to check out the Forum FAQ.


No announcement yet.

Partner 728x90


Exit Methods Instead of Set Methods for Stop Loss and Profit Target

  • Filter
  • Time
  • Show
Clear All
new posts

  • NinjaTrader_Jim
    Hello shadowfax,

    Unless you are using Interactive Brokers or Rithmic, I would expect a strategy that follows the SampleOnOrderUpdate approach (use OnOrderUpdate and OnExecutionUpdate to submit stop/target with Exit methods) to behave consistently between Sim accounts and your live account.

    The rejections may be something we could give more insight on, but we would need your log and trace files. I'd also like to see the strategy code. If it is not too complex and close enough to our example code, I could give some insight into behaviors or possibly provide some recommendation.

    Could you write in with the strategy's source code and your log and trace files? Please email platformsupport [at] ninjatrader [dot] com with the text "Attn Jim 2167087" and please include the log and trace files and the strategy source code. Finally, I'll need order ID's and rejection times for the orders that have gotten rejected so I may review.

    Attaching Log and Trace files

    Please follow the steps below to manually attach your log and trace files to your response so I may investigate this matter further.
    • Open your NinjaTrader folder under My Documents.
    • Right click on the 'log' and 'trace' folders and select Send To> Compressed (zipped) Folder.
    • Send the 2 compressed folders as attachments to us at platformsupport [at] ninjatrader [dot] com.
    • Once complete, you can delete these compressed folders.
    Export as source code - https://ninjatrader.com/support/help...tAsSourceFiles

    I look forward to assisting.

    Leave a comment:

  • shadowfax
    Hi Jim - i wanted to ask you if there might be another example of using ExitLongStopMarket, ExitLongLimit (and short equivalent) that might have some more complex use cases. I am trying to manage brackets (up to 3) that have different targets, but same stop. My code works just fine when using Sim, but i consistently get errors when switching to broker account. E.g. Order rejected due to reprice, etc. I just switched from using SetStopLoss and SetProfitTarget because i was seeing some anomalies there too (stop getting double entered - but only occassionally).

    Any additional examples would be greatly appreciated.


    Leave a comment:

  • NinjaTrader_Jim
    Thanks for sharing interest caveat_lector,

    Your vote has been added.

    Leave a comment:

  • caveat_lector
    Please add my vote for feature request ticket ID SFT-2778.

    Leave a comment:

  • NinjaTrader_Jim
    Hello Steve,

    Thanks for the reply.

    A ticket was submitted previously on this behavior and our Development team is aware of this limitation with standard fill and orders filling on the same bar.

    We are tracking impact to consider improving this with the feature request ticket ID SFT-2778. I have added a vote on your behalf.

    We cannot guarantee any timeframe or promise fulfillment, but your impact and interest is tracked.

    Let me know if there is anything else I can do here.

    Leave a comment:

  • Steve L
    Thanks, Jim.

    OK. That makes sense. I can see now that the pattern where this occurs is on bars where both the stop and the target are triggered.

    I can also confirm that using Historical Order Fill Processing = High (HOFP=High) with some multiple of minute bars bypasses the problem.

    I'm good to go and can work around this in a number of ways, but are you submitting a ticket on this?

    Obviously, with HOFP=Standard, the backtest should not halt. The fill engine should be able to choose either the target or the stop and proceed.

    HOFP=Standard is a useful part of a strategy development methodology because of it's speed. It's a good first pass giving ball-park performance numbers which can later be refined using additional, more time consuming, methods.

    Thanks for your assistance,

    Leave a comment:

  • NinjaTrader_Jim
    Hello Steve,

    Thanks for your patience.

    This comes down to the backtest coming across an over fill scenario on both exits. Since the bar's data points are used to simulate the order fill without actual price action, a scenario where both the target and stop fill on the same bar can be encountered. This creates an overfill which then prevents the next entry order from reaching a Filled state from a Working state.

    To workaround this, you can use High Order Fill Resolution, or you can add a single tick data series to the script and submit orders to the single tick data series.

    High Order Fill Resolution - https://ninjatrader.com/support/help...FillResolution

    Backtesting with Intrabar granularity - https://ninjatrader.com/support/help...ipt_strate.htm

    Please let me know if there is anything else I can do to assist.

    Leave a comment:

  • Steve L
    There appears to be a pattern when the trading halts. By changing the start date of my ES ##-## Day bars series, I can get the halt date to occur on different days.

    I'm using slightly different code than the code posted above, but the basics are the same. You can observe similar patterns with the posted code by changing the date range. I'm still using Exit methods, not Set methods.

    Not sure if these patterns are significant, but
    • The last active bar is always an up bar with a long lower shadow
    • The three bars (the last active bar, the one preceding it, and the one following it) are always trending up.

    Click image for larger version  Name:	Halt_2018_2019-05-28_17-15-11.png Views:	1 Size:	13.4 KB ID:	1059083

    Click image for larger version  Name:	Halt_2016_2019-05-28_17-13-46.png Views:	1 Size:	15.5 KB ID:	1059084

    Click image for larger version  Name:	Halt_2015_2019-05-28_17-12-28.png Views:	1 Size:	12.8 KB ID:	1059085

    Click image for larger version  Name:	Halt_2011_2019-05-28_17-10-21.png Views:	1 Size:	15.3 KB ID:	1059086

    Click image for larger version  Name:	Halt_2008_2019-05-28_17-06-20.png Views:	1 Size:	19.1 KB ID:	1059087

    Last edited by Steve L; 05-28-2019, 05:07 PM.

    Leave a comment:

  • NinjaTrader_Jim
    Hello Steve,

    Thanks for providing a scenario for us to test.

    I have seen this behavior when combining Set and Exit methods, but I am looking into what is happening further in this case.

    I will follow up after I have been able to fully analyze.

    Leave a comment:

  • Steve L
    Thanks, Jim.

    So, using the sample code, I'm still running into an anomaly I saw previously.

    I've taken the exact strategy code from the example and just changed the size of the stop loss and profit target.

    My data series is ES ##-## daily bars from 1/1/2018 to 1/1/2019. Kinetick data.

    If I run the strategy code (included below) on my chart, it makes a few trades, then halts.

    Click image for larger version  Name:	2019-05-27_9-51-24.png Views:	1 Size:	20.6 KB ID:	1058895

    The last order is a market long entry on 2/14/2018. It is submitted, accepted, then working, but it never fills.

    Click image for larger version  Name:	2019-05-27_9-54-05.png Views:	1 Size:	41.2 KB ID:	1058896

    If I change the stop and target size to say, 120, instead of 100 ticks, then it just moves the date where the halt occurs to 4/4/2018 I believe.

    Can you help me understand what is happening here?

    // Copyright (C) 2015, NinjaTrader LLC <www.ninjatrader.com>.
    // NinjaTrader reserves the right to modify or overwrite this NinjaScript component with each release.
    #region Using declarations
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Xml.Serialization;
    using NinjaTrader.Cbi;
    using NinjaTrader.Gui;
    using NinjaTrader.Gui.Chart;
    using NinjaTrader.Gui.SuperDom;
    using NinjaTrader.Data;
    using NinjaTrader.NinjaScript;
    using NinjaTrader.Core.FloatingPoint;
    using NinjaTrader.NinjaScript.Indicators;
    using NinjaTrader.NinjaScript.DrawingTools;
    #endregion Using declarations
    // This namespace holds all strategies and is required. Do not change it.
    namespace NinjaTrader.NinjaScript.Strategies
        public class SampleOnOrderUpdate : Strategy
            private Order entryOrder = null; // This variable holds an object representing our entry order
            private Order stopOrder = null; // This variable holds an object representing our stop loss order
            private Order targetOrder = null; // This variable holds an object representing our profit target order
            protected override void OnBarUpdate()
                // Submit an entry market order if we currently don't have an entry
                // order open and are past the BarsRequiredToTrade bars amount
                if (entryOrder == null && Close[0] > Open[0] && CurrentBar > BarsRequiredToTrade)
                    // Enter Long. We will assign the resulting Order object to
                    // entryOrder in OnOrderUpdate()
                    EnterLong(1, "MyEntry");
                // If we have a long position and the current price is 4 ticks in
                // profit, raise the stop-loss order to breakeven. We use (7 *
                // (TickSize / 2)) to denote 4 ticks because of potential precision
                // issues with doubles. Under certain conditions (4 * TickSize) could
                // end up being 3.9999 instead of 4 if the TickSize was 1. Using our
                // method of determining 4 ticks helps cope with the precision issue
                // if it does arise.
                //if (Position.MarketPosition == MarketPosition.Long && Close[0] >= Position.AveragePrice + (7 * (TickSize / 2)))
                //    // Checks to see if our Stop Order has been submitted already
                //    if (stopOrder != null && stopOrder.StopPrice < Position.AveragePrice)
                //    {
                //        // Modifies stop-loss to breakeven
                //        stopOrder = ExitLongStopMarket(0, true, stopOrder.Quantity, Position.AveragePrice, "MyStop", "MyEntry");
                //    }
            protected override void OnExecutionUpdate(Execution execution, string executionId, double price, int quantity, MarketPosition marketPosition, string orderId, DateTime time)
                // We advise monitoring OnExecution to trigger submission of
                // stop/target orders instead of OnOrderUpdate() since OnExecution()
                // is called after OnOrderUpdate() which ensures your strategy has
                // received the execution which is used for internal signal tracking.
                if (entryOrder != null && entryOrder == execution.Order)
                    if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
                        int ticks = 100;
                        // Stop-Loss order 4 ticks below our entry price
                        stopOrder = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - ticks * TickSize, "MyStop", "MyEntry");
                        // Target order 8 ticks above our entry price
                        targetOrder = ExitLongLimit(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ticks * TickSize, "MyTarget", "MyEntry");
                        // Resets the entryOrder object to null after the order has been filled
                        if (execution.Order.OrderState != OrderState.PartFilled)
                            entryOrder = null;
                // Reset our stop order and target orders' Order objects after our position is closed.
                if ((stopOrder != null && stopOrder == execution.Order) || (targetOrder != null && targetOrder == execution.Order))
                    if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled)
                        stopOrder = null;
                        targetOrder = null;
            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.ToString() + " -- " + order.ToString());
                // Handle entry orders here. The entryOrder object allows us to
                // identify that the order that is calling the OnOrderUpdate() method
                // is the entry order. 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
                // gauranteed to be complete if it is referenced immediately after
                // submitting
                if (order.Name == "MyEntry")
                    entryOrder = order;
                    // Reset the entryOrder object to null if order was cancelled
                    // without any fill
                    if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
                        entryOrder = null;
            protected override void OnPositionUpdate(Position position, double averagePrice, int quantity, MarketPosition marketPosition)
                // Print our current position to the lower right hand corner of the chart
                Draw.TextFixed(this, "MyTag", position.ToString(), TextPosition.BottomRight, false, "");
            protected override void OnStateChange()
                if (State == State.SetDefaults)
                    Description = @"Sample Using OnOrderUpdate() and OnExecution() methods to submit protective orders";
                    Name = "SampleOnOrderUpdate";
                    Calculate = Calculate.OnBarClose;
                    EntriesPerDirection = 1;
                    EntryHandling = EntryHandling.AllEntries;
                    IsExitOnSessionCloseStrategy = true;
                    ExitOnSessionCloseSeconds = 30;
                    IsFillLimitOnTouch = false;
                    MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
                    OrderFillResolution = OrderFillResolution.Standard;
                    Slippage = 0;
                    StartBehavior = StartBehavior.WaitUntilFlat;
                    TimeInForce = TimeInForce.Gtc;
                    TraceOrders = true;
                    RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
                    StopTargetHandling = StopTargetHandling.PerEntryExecution;
                    BarsRequiredToTrade = 20;
                else if (State == State.Realtime)
                    // one time only, as we transition from historical
                    // convert any old historical order object references
                    // to the new live order submitted to the real-time account
                    if (entryOrder != null)
                        entryOrder = GetRealtimeOrder(entryOrder);
                    if (stopOrder != null)
                        stopOrder = GetRealtimeOrder(stopOrder);
                    if (targetOrder != null)
                        targetOrder = GetRealtimeOrder(targetOrder);

    Leave a comment:

  • NinjaTrader_Jim
    Hello Steve,

    Thanks for your post.

    The SampleOnOrderUpdate strategy demonstrates how this can be done. We typically advise using OnOrderUpdate to assign orders to Order objects, and then to submit Exit orders from OnExecutionUpdate. It is permissible to assign Order objects directly from Exit methods in OnExecutionUpdate.

    I highly recommend this framework for robust strategies. Please also see the documentation linked with the sample.

    SampleOnOrderUpdate - https://ninjatrader.com/support/help...and_onexec.htm

    Let us know if you have any questions and we will be happy to assist further.

    Leave a comment:

  • Exit Methods Instead of Set Methods for Stop Loss and Profit Target

    Do you have a good example of how to properly use Exit methods to set both a stop loss and profit target when entering a new position?

    In the OnOrderUpdate method I create both an ExitLongLimit and an ExitLongStopMarket (Let's just talk about long positions for the sake of simplicity.)

    Then I resubmit those with each OnBarUpdate to keep them alive during the life of the position.

    This is sort of working, but I keep running into various issues and I'd just like to make sure I'm following the recommended pattern.

Latest Posts


Topics Statistics Last Post
Started by kylef, Today, 11:36 AM
2 responses
Last Post NT-Roland  
Started by ivan2007007, Today, 12:55 PM
1 response
Last Post ivan2007007  
Started by lazerpd, Today, 12:45 PM
0 responses
Last Post lazerpd
by lazerpd
Started by UncleRyan, Today, 12:45 PM
0 responses
Last Post UncleRyan  
Started by kattiehowe, Today, 09:01 AM
1 response
Last Post MojoJojo