https://ninjatrader.com/support/help...onorderupdate_ and_onexec.htm
//
// 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 ( Position.MarketPosition == MarketPosition.Flat && CurrentBar > BarsRequiredToTrade)
{
/* Enter Long. We will assign the resulting Order object to entryOrder1 in OnOrderUpdate() */
EnterLongStopMarket(0,true, PositionSize, longPrice, "MyEntry");
EnterLongStopMarket(0,true, PositionSizeRunner, longPrice, "MyEntryRunner");
}
/* 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");
[B]stopOrder = ExitLongStopMarket(0, true, stopOrder.Quantity, Position.AveragePrice, "MyStop", "MyEntryRunner");[/B]
}
}
}
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" || order.Name == "MyEntryRunner" || )
{)
{
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");
[B]stopOrder = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - 4 * TickSize, "MyStop", "MyEntryRunner");
targetOrder = ExitLongLimit(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + 20 * TickSize, "MyTarget", "MyEntryRunner");[/B]
}
// 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");
[B]stopOrder = ExitLongStopMarket(0, true, execution.Order.Filled, execution.Order.AverageFillPrice - 4 * TickSize, "MyStop", "MyEntryRunner");
targetOrder = ExitLongLimit(0, true, execution.Order.Filled, execution.Order.AverageFillPrice + 20 * TickSize, "MyTarget", "MyEntryRunner");[/B]
}
// 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;
}
}
}
}
}

rderId='c3d53bf309964120ac5bb4f192754f00' account='Playback101' name='MyEntryLong' orderState=Filled instrument='NQ 09-24' orderAction=Buy orderType='Stop Market' limitPrice=0 stopPrice=20884.5 quantity=1 tif=Gtc oco='' filled=1 averageFillPrice=20884.5 onBehalfOf='' id=182562 time='2024-07-11 07:54:36' gtd='2099-12-01' statementDate='2024-07-11'
Comment