Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Strategy submitting orders on historical bars?

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

    Strategy submitting orders on historical bars?

    I created a very simple strategy class just to test out lifecycle methods and to make sure I understand things properly. The strategy just places a BUYSTOP order 4 ticks above the High of the candle (on NQ) if it is an up candle, or places a SELLSTOP order 4 ticks below the LOW of the candle if this is a down candle. The code for the lifecycle methods is shown below.

    When I run it, it seems to want to launch trades on historical bars. Obviously I don't want that. If it wants to show me the trades that would have occurred, that's fine, but I sure don't want it to try to send actual orders based on historical bars!

    One of the first messages I get in the Output window is this:

    Strategy 'SimpleTestStrategy/207949029': An order has been ignored since the stop price ‘11479.5’ near the bar stamped ‘10/5/2020 3:12:30 PM’ is invalid based on the price range of the bar. This is an invalid order and subsequent orders may also be ignored.

    Then it executes all my Print statements in OnExecutionUpdate and OnPositionUpdate so it seems to be trying to open actual orders. I don't want this!

    Am i misunderstanding what it is doing? How can I see past trades that would have occurred without it trying to send actual live orders?

    PHP Code:
    namespace NinjaTrader.NinjaScript.Strategies
    {
        public class SimpleTestStrategy : Strategy
        {
            SOME PRIVATE VARS HERE
    
            protected override void OnExecutionUpdate(Cbi.Execution execution, string executionId, double price, int quantity,
                         Cbi.MarketPosition marketPosition, string orderId, DateTime time)
            {
                Print("Inside OnExecutionUpdate");
                Print(" price is " + price+", quantity is "+quantity);
                Print(" marketPosition is "+marketPosStr(marketPosition));
                Print(" execution market position is "+marketPosStr(execution.MarketPosition));
                Print(" Order name is "+execution.Order.Name);
            }
    
            protected override void OnOrderUpdate(Cbi.Order order, double limitPrice, double stopPrice,
                      int quantity, int filled, double averageFillPrice,
                      Cbi.OrderState orderState, DateTime time, Cbi.ErrorCode error, string comment)
            {
                // Assign Order objects here
                // 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 == SHORT_ENTRY_NAME)
                    shortEntry = order;
                else if (order.Name == LONG_ENTRY_NAME)
                    longEntry = order;
    
                if (longEntry != null && longEntry == order)
                {
                    // Reset the longEntry object to null if order was cancelled without any fill
                    if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
                    {
                        longEntry = null;
                    }
                }
    
                if (shortEntry != null && shortEntry == order)
                {
                    // Reset the shortTop object to null if order was cancelled without any fill
                    if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
                    {
                        shortEntry = null;
                    }
                }
            }
    
            protected override void OnPositionUpdate(Cbi.Position position, double averagePrice,
                     int quantity, Cbi.MarketPosition marketPosition)
            {
                //
                // If we just opened a position, reset the setup so we can be computing new setups, even while the position is open
                //
                    Print("Inside OnPositionUpdate");
                    this.priorMarketPosition = this.currentMarketPosition;
                    this.currentMarketPosition = position.MarketPosition;
                    if (this.currentMarketPosition != MarketPosition.Flat && this.priorMarketPosition == MarketPosition.Flat) {
                        Print(" Just opened new position");
                    } else if (this.currentMarketPosition == MarketPosition.Flat && this.priorMarketPosition != MarketPosition.Flat) {
                        Print(" Just closed position, now Flat");
                    }
    
            }
    
            protected override void OnBarUpdate()
            {
    
                 if (CurrentBar < BarsRequiredToTrade)
                     return;
    
                computeTradability();
                if (this.canEnterNewTrade) {
                     if (Close[0] > Open[0]) {
                        double entryPriceLong = High[0] + 4*TickSize;
                        enterBuyStop(1, entryPriceLong, 5, 10);
    
                    } else {
                        double entryPriceShort = Low[0] - 4*TickSize;
                        enterSellStop(1, entryPriceShort, 5, 10);
                    }
                 }
            }
    
            // ************************************
            // Order entry and adjustment methods
            // ************************************
            private void enterBuyStop(int quantity, double entryPrice, int stopTicks, int takeProfitTicks) {
                SetStopLoss(LONG_ENTRY_NAME, CalculationMode.Ticks, (double)stopTicks, false);
                SetProfitTarget(LONG_ENTRY_NAME, CalculationMode.Ticks, (double)takeProfitTicks);
                Print("Inside enterBuyStop: current price: "+Close[0]+", entry price: "+entryPrice);
                Print(" : stopTicks: "+stopTicks+", takeProfitTicks: "+takeProfitTicks);
                EnterLongStopMarket(quantity, entryPrice, LONG_ENTRY_NAME);
            }
    
            private void enterSellStop(int quantity, double entryPrice, int stopTicks, int takeProfitTicks) {
                SetStopLoss(SHORT_ENTRY_NAME, CalculationMode.Ticks, (double)stopTicks, false);
                SetProfitTarget(SHORT_ENTRY_NAME, CalculationMode.Ticks, (double)takeProfitTicks);
                Print("Inside enterSellStop: current price: "+Close[0]+", entry price: "+entryPrice);
                Print(" : stopTicks: "+stopTicks+", takeProfitTicks: "+takeProfitTicks);
                EnterShortStopMarket(quantity, entryPrice, SHORT_ENTRY_NAME);
            }
    
            //
            // This method is called at the start of OnBarUpdate. It sets three member variables in OnBarUpdate:
            // canEnterNewTrade: This is true if we are currently Flat
            // longFilledAndClosed: This is true if we are currently Flat AND if we detect that a prior long position was filled and is now closed
            // shortFilledAndClosed: This is true if we are currently Flat AND if we detect that a prior short position was filled and is now closed
            //
            private void computeTradability() {
                this.canEnterNewTrade = false;
                this.longFilledAndClosed=false;
                this.shortFilledAndClosed=false;
                if (this.currentMarketPosition == MarketPosition.Flat) {
                    //
                    // If we are flat then we can enter a new trade if we get a new signal
                    //
                    this.canEnterNewTrade = true;
    
                    if (this.longEntry != null && this.longEntry.OrderState == OrderState.Filled) {
                        this.longFilledAndClosed=true; // prior long entry order was filled but we are now flat, so it was filled and exited
                        this.longEntry=null;
                    } else {
                        this.longFilledAndClosed=false;
                    }
                    if (this.shortEntry != null && this.shortEntry.OrderState == OrderState.Filled) {
                        this.shortFilledAndClosed=true; // prior short entry order was filled but we are now flat, so it was filled and exited
                        this.shortEntry=null;
                    } else {
                         this.shortFilledAndClosed=false;
                    }
                }
            }
        } 
    } 
    


    #2
    Hello westofpluto,

    Thank you for your post.

    In the historical data the conditions in the script will be run as a backtest and have historical results before real-time data processing and real-time order submissions begin.

    Once the strategy has completed historical processing and is running on real time data, only then will live orders be sent to your account.

    You can modify your script so that it only places orders if the data is real-time data. To do this you will need to edit the code of your script directly, as the Historical public variable is not available to the Strategy Builder.

    The code needed would be some thing like:

    if (State != State.Realtime)
    return;

    This condition checks to see if the script is not processing real-time data (meaning it is processing historical data) and if true will stop any code appearing after it in the same method from evaluating.

    This can also be written as:

    if (State == State.Historical)
    return;

    This checks to see if the script is processing historical data and will stop processing if true (which is the same condition and action as above).

    If this logic is placed at the beginning of OnBarUpdate, the strategy will not process until it reaches real-time data and will not calculate historically.
    If this is placed in the conditions for making an order, it will prevent the order from being placed until the strategy reaches real-time data.
    You could also optionally trigger any open position to exit with an exit market order on the last historical bar.

    To find the last historical bar:

    if (State == State.Historical && CurrentBar == Count — 2)

    Below is a link to the help guide on the 'State' NinjaScript property.



    Please let me know if this does not resolve your inquiry.

    Comment

    Latest Posts

    Collapse

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