Hey there,
This is a classic hurdle when bridging the gap between NinjaTrader 8 Indicators and automated order execution. Because your logic is running inside an Indicator rather than a Strategy, NT8 doesnât automatically manage the order states for you under the hood.
The issue right now is that Order o is declared locally inside your InvokeAsync block. As soon as that block finishes executing, your indicator loses track of the order, which is why you canât check if it was cancelled.
The easiest and most robust solution is a combination of both of your ideas: keep track of the order globally so you can programmatically cancel it using your timeout flag, AND poll its state to reset your orderPlaced boolean.
Here is how you can wire that up:
Step 1: Promote the Order to a class-level variable At the top of your Indicator class (where your other variables are), add this so the whole script can see the order:
C#private Order myEntryOrder = null;
Step 2: Update your creation logic Assign the newly created order to your new global variable instead of a local one:
`C#if (autoOrderOn == true && orderPlaced == false)
{
ChartControl.Dispatcher.InvokeAsync((Action)(() =>
{
Account a = ChartControl.OwnerChart.ChartTrader.Account;
int qty = ChartControl.OwnerChart.ChartTrader.Quantity;
AtmStrategy atm = ChartControl.OwnerChart.ChartTrader.AtmStrategy;
Instrument instr = ChartControl.OwnerChart.ChartTrader.Instrument;
// Assign to the class-level variable
myEntryOrder = a.CreateOrder(instr, OrderAction.Sell, OrderType.StopMarket, OrderEntry.Automated, TimeInForce.Day, qty, 0, oldBoxLow - RRR, "", "Entry", Core.Globals.MaxDate, null);
NinjaTrader.NinjaScript.AtmStrategy.StartAtmStrategy(atm, myEntryOrder);
}));
orderPlaced = true;
}`
Step 3: Programmatically cancel the order (when your timeout hits) Since you are interacting with the Account object, the cancellation must also be sent through the UI dispatcher. Place this where your timeout flag triggers:
C#if (myEntryOrder != null && (myEntryOrder.OrderState == OrderState.Accepted || myEntryOrder.OrderState == OrderState.Working)) { ChartControl.Dispatcher.InvokeAsync((Action)(() => { myEntryOrder.Account.Cancel(new[] { myEntryOrder }); })); }
Step 4: Safely reset your orderPlaced flag Place this block somewhere that updates frequently (like OnBarUpdate). It will catch the cancellation regardless of whether your code did it, or you manually clicked the âXâ on Chart Trader.
C#if (myEntryOrder != null) { // Check if it was cancelled by the user, by your code, or rejected by the broker if (myEntryOrder.OrderState == OrderState.Cancelled || myEntryOrder.OrderState == OrderState.Rejected) { orderPlaced = false; myEntryOrder = null; // Clean up the reference } }