Syntax to scan for cancelled order?

Hello!

I have an Indicator with the following code that creates an order based on an ATM strategy.

					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;
							Order o = 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, o);	
						}));
						
						orderPlaced		= true;
					}

It works great, but I manually the cancel the order if it doesn’t trigger after a certain amount of time, and I don’t know how to set orderPlaced back to false when that happens.

Is there a way to check when the order has been cancelled? Or would it be easier to just automate cancelling the order, because I already have code in the Indicator that flags me when it’s time to cancel it.

This code that I am using to create the orders was borrowed from someone, so I don’t know how to write the code for cancelling the order.

Thank you in advance!

If the only thing for you to do is cancel the order once it notifies you, then I would just automate that part as well. No reason to wait and manually do it.

I’m not sure if that’s something that would require you to use a strategy instead of an indicator. I haven’t worked much on creating orders using indicators. I usually just deal with strategies.

1 Like

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

In my other thread, I am working on an Indicator that creates AND modifies orders. Like you, I have no prior experience working with Indicators that create orders, but at least I have experience with Indicators. I have no experience whatsoever with Strategies, so that’s why I’m going this route.

I agree that full automation does sound like the way to go, so I’m going to continue to pursue that.

Thanks for contributing!

1 Like

Yes!! This was the piece I needed!

I had just figured everything else that you said, but this was the bit I couldn’t figure out. After creating the global order variable, I was trying to figure out how to tell the dispatcher that it was supposed to cancel an order, but the standard “CancelOrder” wasn’t working.

Thank you so much!

1 Like

Okay, so now the question becomes: What happens when the order does get filled, and then I exit the position and am ready to start looking for the next entry? orderPlaced needs to be reset under those conditions, as well.

So, what is the Dispatcher-friendly way of checking for MarketPosition.Flat?

I’ve tried this:

			private Order order = null;
			private Position posit = null;

			if (order != null)
			{   
				Print("Order " + order.Name.ToString() + " = " + order.OrderState.ToString());
				// Check if it was cancelled by the user, by your code, or rejected by the broker
				if (order.OrderState == OrderState.Cancelled || order.OrderState == OrderState.Rejected)
				{
					orderPlaced = false;
					// Clean up the reference
					order = null;
				}
				if (posit != null)
				{
					Print("Position = " + posit.MarketPosition.ToString());
					if (order.OrderState == OrderState.Filled && posit.MarketPosition == MarketPosition.Flat)
					{
						orderPlaced = false;
						order = null;
					}
				}
			}

But, it doesn’t work. Apparently, posit is staying “null.”

How do I get posit to return the actual state of the Position?

The issue is that posit is declared as null and never assigned — you need to use NinjaTrader’s built-in Position property instead of maintaining your own reference.

Replace your posit check with the built-in:

if (order.OrderState == OrderState.Filled && Position.MarketPosition == MarketPosition.Flat)
{
    orderPlaced = false;
    order = null;
}

Position is a live property on your strategy that always reflects the current state for the primary instrument — no need to instantiate or track it yourself. If you’re working with multiple instruments, use Positions[BarsInProgress] instead.

So, then I get this:

An object reference is required for the non-static field, method or property ‘Position.MarketPosition’

I figured it out.

What I ended up doing was creating a global Account variable, and then, in the order creation algorithm, I used the global variable instead of the local Account variable.

Then, in my order management section, I subscribed to OnPositionUpdate. (And, yes, I put an unsubscribe in State.Terminated.)

			if (order != null)
			{   
				if (theAccount != null && subbed == false)
				{
					theAccount.PositionUpdate += OnPositionUpdate;
					subbed	= true;
				}
			
				Print("Order " + order.Name.ToString() + " = " + order.OrderState.ToString());
				// Check if it was cancelled by the user, by your code, or rejected by the broker
				if (order.OrderState == OrderState.Cancelled || order.OrderState == OrderState.Rejected)
				{
					orderPlaced = false;
					// Clean up the reference
					order = null;
				}
				if (posit != null)
				{
					Print("Position = " + posit);
					if (order.OrderState == OrderState.Filled && posit == "Flat")
					{
						orderPlaced = false;
						order = null;
						posit = null;
					}
				}
			}

posit is now just a string variable, which gets assigned to the proper values in OnPositionUpdate. (posit is set to null in State.Defaults.)

			private void OnPositionUpdate(object sender, PositionEventArgs e)
			{
				if (e.MarketPosition == MarketPosition.Flat)
				{ 
					Print("No open positions.");
					posit = "Flat";
				}
				else if (posit == null)
				{	posit = e.Position.ToString();  }
				
			}

And, that’s it. It works perfectly!

Thank you, everyone, for all of your help! :blush:

1 Like