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

strategies with one market and one stop market entry orders.

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

  • NinjaTrader_BrandonH
    replied
    Hello rtwave,

    Thanks for your note.

    I do not see anything specific in your shared code that would cause an issue. That said, if the expected trade(s) are not appearing, this would indicate that the condition to place the order is not evaluating as true or the order is being ignored for other reasons.

    To understand why the script is behaving as it is, such as placing orders or not placing orders when expected, it is necessary to add prints to the script that print the values used for the logic of the script to understand how the script is evaluating.

    In the strategy add prints (outside of any conditions) that print the values of every variable used in every condition that places an order along with the time of that bar. Prints will appear in the NinjaScript Output window (New > NinjaScript Output window).

    Please see the attached example script, SampleOnOrderUpdateModified, which demonstrates how to submit 2 entry orders and manage the stops and targets of those entry orders by using OnOrderUpdate() and OnExecutionUpdate().

    Also, see the help guide documentation below for more information.
    OnOrderUpdate(): https://ninjatrader.com/support/help...tionupdate.htm
    OnExecutionUpdate(): https://ninjatrader.com/support/help...rderupdate.htm

    Let us know if we may assist further.
    Attached Files

    Leave a comment:


  • rtwave
    replied




    people with nt,



    i have continued to work on this position management code but i haven't been able to get stop orders to perform as intended.


    i have some trend following strategies in nt, the most elementary version does not have any day - time filters and it works correctly. i then created a version that liquidates all positions on friday before the close and restores them on sunday at the open, it also works well. i then created a version that only opens and holds positions during regular session hours and it works correctly. i also have a version that uses a stop loss order and converts it to a breakeven stop and it works acceptably. and this version where i want to open a second position will indeed open secondary positions, but the stop orders that should help manage the positions will not work.


    i want nt support to help me with a sample strategy where two positions in the same direction each include conditional stop loss orders.


    Code:
    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 (orshpoor != null && orshpoor == execution.Order)
    {
    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 && marketPosition == MarketPosition.Short)
    {
    orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Instlonuti * TickSize ), "orstorsp01", "orsp01");
    
    }
    // 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 && marketPosition == MarketPosition.Short)
    {
    // Stop-Loss order for OrderState.Filled
    orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Instlonuti * TickSize ), "orstorsp01", "orsp01");
    
    }
    
    // Resets the orshpoor object and the sumFilled counter to null / 0 after the order has been filled
    if (execution.Order.OrderState != OrderState.PartFilled && sumFilled == execution.Order.Filled)
    {
    orshpoor = null;
    sumFilled = 0;
    }
    }
    }
    
    if (pushpoor != null && pushpoor == execution.Order)
    {
    if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
    {
    sumFilled += execution.Quantity;
    
    if (execution.Order.OrderState == OrderState.PartFilled && marketPosition == MarketPosition.Short)
    {
    pushpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustpusp01", "pusp01");
    orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustorsp01", "orsp01");
    }
    
    else if (execution.Order.OrderState == OrderState.Filled && sumFilled == execution.Order.Filled && marketPosition == MarketPosition.Short)
    {
    pushpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustpusp01", "pusp01");
    orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustorsp01", "orsp01");
    }
    
    if (execution.Order.OrderState != OrderState.PartFilled && sumFilled == execution.Order.Filled)
    {
    pushpoor = null;
    sumFilled = 0;
    }
    }
    }
    
    }

    i think that the problem could be with the arguments for position size and position entry price.


    the stop order for the initial position is expressed like this:

    orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Instlonuti * TickSize ), "orstorsp01", "orsp01");


    execution.Order.Filled and execution.Order.AverageFillPrice correspond to the values for the initial position "orsp01" and all this looks good.


    however, when a conditional secondary pullback position is opened, there should now be two stop orders that i want to manage in parallel at all times.


    pushpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustpusp01", "pusp01");
    orshpostor = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( Costlonuti * TickSize ), "pustorsp01", "orsp01");


    it seems to me like execution.Order.Filled and execution.Order.AverageFillPrice in this second case correspond in both cases to "pusp01" which would not work. the position size for "orsp01" would not necessarily be the same as for "pusp01" and neither of these values would ever be the same as the sum of these two numbers. also, it doesn't seem to me like the values for execution.Order.Filled and execution.Order.AverageFillPrice are updated or reset anywhere when that could be necessary.


    i think that these discrepancies could be the reason why the stop orders won't work as intended when the rest of the code will. if the people with nt can take a look at this and provide a solution and a working sample of a strategy with two positions to be managed simultaneously with order and execution update methods that would be very positive.


    very well, regards.

    Leave a comment:


  • NinjaTrader_BrandonH
    replied
    Hello rtwave,

    Thanks for your note.

    When testing the attached code on our end, I am seeing an entry order and stop order placed. See the attached screenshot.

    If the expected trade(s) are not appearing, this would indicate that the condition to place the order is not evaluating as true or the order is being ignored for other reasons.

    To understand why the script is behaving as it is, such as placing orders or not placing orders when expected, it is necessary to add prints to the script that print the values used for the logic of the script to understand how the script is evaluating.

    In the strategy add prints (outside of any conditions) that print the values of every variable used in every condition that places an order along with the time of that bar. Prints will appear in the NinjaScript Output window (New > NinjaScript Output window).

    Below is a link to a forum post that demonstrates using prints to understand behavior.
    https://ninjatrader.com/support/foru...121#post791121

    Please let me know if I may further assist
    Attached Files

    Leave a comment:


  • rtwave
    replied
    people with nt,



    i am back working with order and execution update methods again.


    in my previous post i included a strategy that would not generate secondary positions which is the entire point for what i am doing. i have now included a 1 minute additional data series and changed entry handling to unique entries and the strategy now does open secondary positions when there is a pullback as intended.


    however, i have not been able to get the stop orders to work at all. not for the initial positions, not for the secondary positions, nothing.


    i have been working on the sample pieces of code for order - execution updates that are available and just replaced some components with my own and made other minor changes to the logic but the strategy will never place exitstopmarket positions as intended.



    please take a look at this strategy, specially the order - execution update methods which are the parts that are not performing as intended. i'm working on m2k 20 minute bars, but the instrument or interval should not make any difference.



    very well, thanks, regards.


    20210630OnOrderUpdatetests.zip

    Leave a comment:


  • NinjaTrader_BrandonH
    replied
    Hello rtwave,

    Thank you for your note.

    I see you are using a BarsInProgress == 1 check in your script but you do not have a secondary data series added. This means that this section of code may not execute since there is not secondary bars object.

    Ultimately, debugging steps should be taken to understand why the script is behaving as it is, such as placing orders or not placing orders when expected, it is necessary to add prints to the script that print the values used for the logic of the script to understand how the script is evaluating.

    In the strategy add prints (outside of any conditions) that print the values of every variable used in every condition that places an order along with the time of that bar. Prints will appear in the NinjaScript Output window (New > NinjaScript Output window).

    Below is a link to a forum post that demonstrates using prints to understand behavior and including a link to a video recorded using the Strategy Builder.
    https://ninjatrader.com/support/foru...121#post791121

    Please let me know if I may further assist

    Leave a comment:


  • rtwave
    replied


    people with nt,



    i have continued to work with these methods.


    i created this strategy that i include as an attachment so that it could be optimized. the initial short and long positions seem to work fine and i have also included all the position management code that i have been able to write to this moment. however, the strategy will never open the pullback positions which are the very reason for all these efforts.


    i have optimized this strategy only on the ema period variable both on the nq and cl contract and there are zero pullback entries ever. i'm not sure that the position management is doing much either.


    ¿could you please take a look at this code? i have described my objectives extensively all throughout this thread.



    OnOrderUpdatetests.zip

    Leave a comment:


  • NinjaTrader_BrandonH
    replied
    Hello rtwave,

    Thank you for your note.

    OnExecutionUpdate() and OnOrderUpdate() can be used to track any number of Order objects.

    You would need to create an order object for each order that you would like to manage in your script. For example, if you have more than one entry order, stop order, and profit target order then you would need to create different variables for these orders. For example:

    Code:
    private Order stopOrder2 = null; // This variable holds an object representing our stop loss order of the second trade
    private Order targetOrder2 = null; // This variable holds an object representing our profit target order of the second trade
    private Order entryOrder2 = null; // This variable holds an object representing our entry of the second trade
    In OnOrderUpdate() you would then check if the entry order.Name is the name of the second entry order, followed by assigning that order to your second entry order variable.

    Code:
    if(order.Name == "pullbackshortposition")
    {
        entryOrder2 = order;
        if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
            {entryOrder2 = null;}
    }
    }
    In OnExecutionUpdate() you would check if the second entry order variable is not null and set your second stop loss order. For example:

    Code:
    if (entryOrder2 != null && entryOrder2 == execution.Order)
    {
        if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled ||
        (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
        {
            stopOrder2 = ExitLongStopMarket(0, true,  execution.Order.Filled, execution.Order.AverageFillPrice + ( 70 * TickSize ), "pullbackshortstop1", "pullbackshortposition");
        }
    }
    In regards to moving a stop loss to breakeven, that would be the correct syntax for modifying the stop loss to breakeven.

    Let us know if we may assist further.

    Leave a comment:


  • rtwave
    replied





    people with nt, NinjaTrader_BrandonH,



    thanks.



    i think i'm doing some progress.


    i have two different short and two long entries. i will concentrate on one side for now, the other side would only need to be inverted.


    i'm thinking i would just have to create this fragment of code in the onorderupdate method for every single different entry in my code:


    else if (order.Name == "ordinaryshortposition/pullbackshortposition and the same for every long position")
    {
    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;
    sumFilled = 0;
    }
    }



    however, i have been taking a look at the onexecutionupdate method and it only deals with a single order for one single position. i would appreciate if the people with nt could help me to code one stop order for ordinaryshortposition and another consolidated or coordinated stop if and when pullbackshortposition is executed.


    for ordinaryshortposition, i think this would achieve what i have in mind:

    stopOrder = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( 100 * TickSize ), "ordinaryshortstop", "ordinaryshortposition");


    and then, if pullbackshortposition happens to be executed i think i would need two stop orders:


    stopOrder = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( 70 * TickSize ), "pullbackshortstop1", "ordinaryshortposition");

    stopOrder = ExitShortStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + ( 70 * TickSize ), "pullbackshortstop2", "pullbackshortposition");


    (i'm not sure about this, the price level is definitely correct and what i have in mind, but i don't know whether it would be possible to use one single order for the consolidated position or two separate orders and where i should place and condition them. also, the sample that nt provides includes a lot of code that would deal with partial fills, i don't think this would be necessary for my strategy (i use market entries for 1 contract each) but i don't think that leaving that code in the strategy would cause any harm and it could eventually be helpful if i work with larger position sizes later.)




    and finally, assuming that both ordinaryshortposition and pullbackshortposition have been executed and that the consolidated position has now been made to move at least 180 ticks in my favor i would want to move the stoporder(s) to breakeven. i understand that would be done on the onbarupdate method i just want to make sure that an structure of this kind would be appropriate.



    if (Position.MarketPosition == MarketPosition.Short && Close[0] <= ( Position.AveragePrice - ( 180 * TickSize ) )
    {
    // Checks to see if our Stop Order has been submitted already
    if (stopOrder != null && stopOrder.StopPrice > Position.AveragePrice)
    {
    // Modifies stop-loss to breakeven
    stopOrder = ExitShortStopMarket(0, true, stopOrder.Quantity ¿?, Position.AveragePrice, "breakevenstop", " ¿1 or 2 orders? ");
    }
    }





    very well, those are the parts that have held me back when trying to use these advanced methods, regards.

    Leave a comment:


  • NinjaTrader_BrandonH
    replied
    Hello rtwave,

    Thank you for your note.

    The SampleOnOrderUpdate script is the additional resources referred to in the OnOrderUpdate() and OnExecutionUpdate() help guide documentations. OnOrderUpdate() and OnExecutionUpdate() would only need to be called once within your strategy. Then, any OnOrderUpdate() logic in your script would be placed in the OnOrderUpdate() method.The same goes for the OnExecutionUpdate() method. OnExecutionUpdate() would only be called once in the script and any OnExecutionUpdate() logic would be placed in that methon.

    I have modified and attached the SampleOnOrderUpdate script to demonstrate using Long and Short orders and managing positions with OnOrderUpdate() and OnExecutionUpdate(). The example script enters Long or Short depending on if the current Close price is greater than or less than an EMA indicator. Then, positions are managed within OnOrderUpdate() and OnExecutionUpdate().

    See the help guide documentation below for more information.
    OnOrderUpdate() - https://ninjatrader.com/support/help...rderupdate.htm
    OnExecutionUpdate() - https://ninjatrader.com/support/help...tionupdate.htm
    SampleOnOrderUpdate - https://ninjatrader.com/support/help...and_onexec.htm

    Let us know if we may assist further.
    Attached Files

    Leave a comment:


  • rtwave
    replied



    these fora would not accept this strategy in the post above as then the site complained that there were too many characters.


    this is a very simple strategy that could nicely serve to exemplify how to use the onbarupdate and onexecutionupdate tools to manage the positions of a long and short strategy.



    Code:
    #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.Gui.Tools;
    using NinjaTrader.Data;
    using NinjaTrader.NinjaScript;
    using NinjaTrader.Core.FloatingPoint;
    using NinjaTrader.NinjaScript.Indicators;
    using NinjaTrader.NinjaScript.DrawingTools;
    #endregion
    
    //This namespace holds Strategies in this folder and is required. Do not change it.
    namespace NinjaTrader.NinjaScript.Strategies
    {
    public class sampleemacrossover : Strategy
    {
    private EMA EMA1;
    
    
    protected override void OnStateChange()
    {
    if (State == State.SetDefaults)
    {
    Description = @"sampleemacrossover";
    Name = "sampleemacrossover";
    Calculate = Calculate.OnBarClose;
    EntriesPerDirection = 1;
    EntryHandling = EntryHandling.UniqueEntries;
    IsExitOnSessionCloseStrategy = false;
    ExitOnSessionCloseSeconds = 10;
    IsFillLimitOnTouch = false;
    MaximumBarsLookBack = MaximumBarsLookBack.Infinite;
    OrderFillResolution = OrderFillResolution.Standard;
    Slippage = 8;
    StartBehavior = StartBehavior.ImmediatelySubmitSynchronizeAccount;
    TimeInForce = TimeInForce.Gtc;
    TraceOrders = true;
    RealtimeErrorHandling = RealtimeErrorHandling.StopCancelCloseIgnoreRejects ;
    StopTargetHandling = StopTargetHandling.PerEntryExecution;
    BarsRequiredToTrade = 10;
    // Disable this property for performance gains in Strategy Analyzer optimizations
    // See the Help Guide for additional information
    IsInstantiatedOnEachOptimizationIteration = true;
    Positionsize = 1;
    Emap = 10;
    
    }
    else if (State == State.Configure)
    {
    }
    else if (State == State.DataLoaded)
    {
    EMA1 = EMA(Close, Convert.ToInt32(Emap));
    }
    }
    
    protected override void OnBarUpdate()
    {
    if (CurrentBars[0] < 1)
    return;
    
    // Set 1
    if (Close[0] < EMA1[0])
    {
    EnterShort(Convert.ToInt32(Positionsize), @"shortposition01");
    }
    
    
    // Set 2
    if (Close[0] > EMA1[0])
    {
    EnterLong(Convert.ToInt32(Positionsize), @"longposition01");
    }
    
    
    }
    
    #region Properties
    [NinjaScriptProperty]
    [Range(1, int.MaxValue)]
    [Display(ResourceType = typeof(Custom.Resource), Name="Emap", Description="ema", Order=1, GroupName="NinjaScriptStrategyParameters")]
    public int Emap
    { get; set; }
    
    [NinjaScriptProperty]
    [Range(1, int.MaxValue)]
    [Display(ResourceType = typeof(Custom.Resource), Name="Positionsize", Description="position size", Order=2, GroupName="NinjaScriptStrategyParameters")]
    public int Positionsize
    { get; set; }
    #endregion
    
    }
    }

    Leave a comment:


  • rtwave
    replied



    people with nt,



    i have been looking at these onorderupdate and onexecutionupdate functionalities. it seems that these are potent tools but it will be quite a challenge for a non-programmer like me to learn to use them.




    now, i have read these entries on the support guide and at the very bottom both promise additional resources that i haven't been able to find anywhere:



    Additional Reference Samples
    Additional reference code samples are available the NinjaScript Educational Resources section of our support forum.


    https://ninjatrader.com/support/help...rderupdate.htm

    https://ninjatrader.com/support/help...tionupdate.htm


    ¿are there really any other resources to learn how to use these functionalities?






    and i have taken a look at the sample strategy that nt makes available:


    Code:
    //
    // Copyright (C) 2019, 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
    
    // 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
    private int sumFilled = 0; // This variable tracks the quantities of each execution making up the entry order
    
    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 = false;
    RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
    StopTargetHandling = StopTargetHandling.ByStrategyPosition;
    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);
    }
    }
    
    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 && Position.MarketPosition == MarketPosition.Flat && CurrentBar > BarsRequiredToTrade)
    {
    /* Enter Long. We will assign the resulting Order object to entryOrder1 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 OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string nativeError)
    {
    // 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;
    sumFilled = 0;
    }
    }
    }
    
    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))
    {
    // 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)
    {
    stopOrder = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - 4 * TickSize, "MyStop", "MyEntry");
    targetOrder = ExitLongLimit(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + 8 * TickSize, "MyTarget", "MyEntry");
    }
    // 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
    stopOrder = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - 4 * TickSize, "MyStop", "MyEntry");
    targetOrder = ExitLongLimit(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + 8 * TickSize, "MyTarget", "MyEntry");
    }
    
    // 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)
    {
    entryOrder = null;
    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)
    {
    stopOrder = null;
    targetOrder = null;
    }
    }
    }
    }
    }



    that sample could not be any more minimal. and it leaves me with a lot of questions about how many override voids, objects and how many units of every different element would be necessary to use these update functionalities if one has multiple different types of entries. so, if nt could provide a working sample of any strategy (preferably the price - ema crossover i will include in the next post) with both short and long positions where all positions are managed with stop loss and profit target orders by making use of these update overrides that would be fantastic.


    (as an aside, i have enabled the sample strategy above in several charts and it will only place 1 or 2 trades and then stop definitely. this makes no sense to me because from what i can see in the code, it should keep making the same entry every single bar if there is no position open.)



    very well, regards.

    Leave a comment:


  • NinjaTrader_BrandonH
    replied
    Hello rtwave,

    Thank you for your note.

    ...and this fragment below makes me think that these advanced methods will not work if one wants to backtest - optimize strategies:

    The SampleOnOrderUpdate example script would be able to be backtested in the Strategy Analyzer. That section of code would only update Historical order references if the State transitions from Historical to Realtime. Since backtests use historical processing, this section of code would not process since the State never transitions from Historical to Realtime. This means the Historical order references would be used in the script.

    ¿is there any more rudimentary way to make sure that the nt platform will be able to manage a position that has been created by two different orders as one, and manage their stop loss price levels also as one?

    Are you referring to scaling into a position and managing the stop loss order with one order as opposed to two? Scaling into a position is controlled with the signal names of your strategy, and the properties EntryHandling and EntriesPerDirection. This reference sample can help with scaling in and out of a strategy.
    https://ninjatrader.com/support/helpGuides/nt8/en-us/scaling_out_of_a_position.htm

    ¿could it be possible to delay 1, 2, 3 seconds after the second entry, the code that would set the second set of stop loss orders so that Position.AveragePrice can be updated and correct?

    This would not be possible in a backtest since backtests are run all at once. If you want to get the Position for the scaled-in position, you should follow my colleague Jim's suggestion in post #8 and look for the second order to execute in OnExecutionUpdate.

    Let us know if we may assist further.

    Leave a comment:


  • rtwave
    replied



    people with nt, NinjaTrader_Jim,


    thanks.


    i have read your comment very carefully.


    these advanced onorder and onexecution update override methods seem fantastic for anyone who wants to manage positions with absolute precision.



    however, i took a look at the one sample i found here:


    https://ninjatrader.com/support/help...Update_NT8.zip


    and this fragment below makes me think that these advanced methods will not work if one wants to backtest - optimize strategies:


    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);
    }



    so, assuming my interpretation of this code above is acceptable and that the advanced methods won't work to backtest - optimize strategies, ¿is there any more rudimentary way to make sure that the nt platform will be able to manage a position that has been created by two different orders as one, and manage their stop loss price levels also as one? from the backtests i have ran it seems that the second entry does work as intended when a defined profit - loss amount is hit, but in the charts there are trades where i see two different exits and two different price levels and this is what i want to avoid. ¿could it be possible to delay 1, 2, 3 seconds after the second entry, the code that would set the second set of stop loss orders so that Position.AveragePrice can be updated and correct? ¿or maybe use a different second profit - loss amount to generate this second set? i'm interested in backtesting whether these additional conditional entries would be profitable and solid position management, so i'm interested in a structure that can be backtested - optimized and there must be ingenious coding solutions to enable the platform to manage positions as i have in mind.



    very well, thanks, regards.

    Leave a comment:


  • NinjaTrader_Jim
    replied
    Hello rtwave,

    The Strategy Position object is based on Executions. Set methods will prep NinjaTrader to submit Target/Stop when the associated Enter order fills. If you would like to update and place your stop losses relative to Position.AveragePrice when that entry order fills/executes, I would suggest then to use OnExecutionUpdate to place/move the stop loss orders because the Position object will be updated with the current position at that point.

    Also to note, because Set methods prep NinjaTrader to submit target/stop orders, they should be submitted before the associated Entrer method, otherwise a previous level may be used. It would not be recommended to use Set methods in OnExecutionUpdate, so you may wish to use Exit methods for your target/stops and use OnExecutionUpdate to submit initial stop losses, and when the second entry fills and is seen in OnExecutionUpdate, to submit the new stop and existing stop to your desired level.

    SampleOnOrderUpdate provides a good demonstration for using OnExecutionUpdate to submit Exit orders for target/stop.

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

    We look forward to assisting.

    Leave a comment:


  • rtwave
    replied



    people with nt,



    i need some help.


    i have been working on these additional conditional orders i'm interested in.


    i have the code below to transform stop loss orders into breakeven stops:



    Code:
    else if(BarsInProgress == 1)
    {
    
    
    
    if (Position.MarketPosition != MarketPosition.Short)
    {
    SetStopLoss(@"shortposition", CalculationMode.Ticks, Numberticks, false);
    Setbreakeven = true;
    }
    else if (Position.MarketPosition == MarketPosition.Short)
    {
    if ( Setbreakeven == true && Close[0] < ( Position.AveragePrice - ( Profit * TickSize ) ) )
    {
    SetStopLoss(@"shortposition", CalculationMode.Price, ( Position.AveragePrice - ( Numberticks * TickSize ) ) , false);
    Setbreakeven= false;
    }
    }
    
    if (Position.MarketPosition != MarketPosition.Long)
    {
    SetStopLoss(@"longposition", CalculationMode.Ticks, Stlonuti, false);
    Setbreakeven= true;
    }
    else if (Position.MarketPosition == MarketPosition.Long)
    {
    if ( Setbreakeven== true && Close[0] > ( Position.AveragePrice + ( Profit * TickSize ) ) )
    {
    SetStopLoss(@"longposition", CalculationMode.Price, ( Position.AveragePrice + ( Numberticks * TickSize ) ), false);
    Setbreakeven= false;
    }
    }

    i have worked the segment below to the following:

    else if (Position.MarketPosition == MarketPosition.Short)
    {
    if ( Pullbackposition == true && High[0] > ( Position.AveragePrice + ( Pullbackticks * TickSize ) ) )
    {
    EnterShort(Convert.ToInt32(Pullbacksize), @"shortpositionpullback");
    SetStopLoss(@"shortpositionpullback", CalculationMode.Price, ( Position.AveragePrice + ( Toslnuti * TickSize ) ) , false);
    SetStopLoss(@"shortposition", CalculationMode.Price, ( Position.AveragePrice + ( Numberticks * TickSize ) ) , false);
    Pullbackposition = false;
    }
    }


    from what i have observed, the fact that the second entry "shortpositionpullback" and the stop loss orders are all sent simultaneously is problematic. i want the second group of stop loss orders to use the Position.AveragePrice for all the positions and all the contracts in my account for the relevant symbol and thus the second stop loss should work globally and be set at one same price level. it seems to me that as i have structured this code so far, the platform cannot have the updated and correct Position.AveragePrice as it is being calculated at the same time a second entry order is being sent.


    if this observation is correct, ¿is there any way to delay the second group of stop loss orders so that they will operate in tandem and manage the strategy's cumulative position as one? or ¿could it be necessary to reformulate these secondary orders significantly to achieve that same objective?



    very well, regards.
    Last edited by rtwave; 03-24-2021, 09:10 AM.

    Leave a comment:

Latest Posts

Collapse

Topics Statistics Last Post
Started by KirkHammett, Today, 03:23 AM
0 responses
2 views
0 likes
Last Post KirkHammett  
Started by eleven, Yesterday, 10:06 PM
0 responses
35 views
0 likes
Last Post eleven
by eleven
 
Started by ezrollin, Yesterday, 08:12 PM
7 responses
72 views
0 likes
Last Post bltdavid  
Started by kyamato, 11-23-2021, 10:51 PM
6 responses
91 views
0 likes
Last Post jeronymite  
Started by fscabrera03, Yesterday, 07:14 PM
0 responses
49 views
0 likes
Last Post fscabrera03  
Working...
X