I have a Strategy that subscribes to OnOrderUpdate for a given Live account. When an order fills, I see the “Order” category in the Log, but it is not firing the OnOrderUpdate event. When I switch to my Sim account, for the exact same scenario, the event successfully fires.
The Order lines in the Log show the platform received the fill, so the question is whether your code is attached to it. Two different things are called OnOrderUpdate in NinjaScript, and they behave differently.
The strategy method, protected override void OnOrderUpdate(Order order, ...). The help guide says only orders submitted and managed by the strategy call it. A fill on an order placed from Chart Trader, the SuperDOM, an ATM or another strategy never reaches it, on Sim or on live. So if your Sim test fills an order the strategy sent and your live test fills one placed another way, that is the whole difference.
The account event, account.OrderUpdate += handler. This one reports every order on that account, whoever placed it, and “subscribes for a given account” sounds like this one. When it fires for Sim101 and stays silent for a live account, the first thing to rule out is that the handler was never attached to the live account: the lookup in Account.All returned null, and the if (account != null) check from NinjaTrader’s example skips the subscription without a word. Two usual reasons:
- The name. The lookup compares
Namecharacter for character. “Sim101” is hard to get wrong; a live account name set by the broker is not. - The moment. A live account is only in
Account.Allwhile its connection is connected. A lookup that runs once while the live connection is down keeps null for good. NinjaTrader’s Account class example does the lookup in State.SetDefaults, but SetDefaults also runs each time a window lists your strategies, and the best-practices page asks to keep it lean and leave object references to later states.
This version looks the account up when the strategy starts, prints what it found and prints every update it receives, so the Output window tells you which case you are in:
private Account watched;
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Name = "WatchLiveOrders"; // defaults only here, no account lookup
}
else if (State == State.DataLoaded)
{
lock (Account.All)
{
foreach (Account a in Account.All)
Print("Available: [" + a.Name + "]");
watched = Account.All.FirstOrDefault(a => a.Name == "YOUR EXACT LIVE ACCOUNT NAME");
}
if (watched == null)
Print("Live account NOT found, nothing subscribed");
else
{
watched.OrderUpdate += OnAccountOrderUpdate;
Print("Subscribed to [" + watched.Name + "]");
}
}
else if (State == State.Terminated)
{
if (watched != null)
watched.OrderUpdate -= OnAccountOrderUpdate;
}
}
private void OnAccountOrderUpdate(object sender, OrderEventArgs e)
{
Print(string.Format("{0} {1} {2}", e.Order.Account.Name, e.Order.Name, e.OrderState));
}
Put the name in, enable the strategy with the live connection up, and open the Output window (Control Center, New > NinjaScript Output) first. If “NOT found” prints, copy the name from the Available lines; the brackets show every character. If your strategy can start before the live connection is up, look the account up again when it connects, from the Account.AccountStatusUpdate event.
Two smaller points:
- Inside a strategy, give the handler its own name, as above. A handler called OnOrderUpdate compiles next to the strategy’s own OnOrderUpdate, and it gets easy to read the wrong one.
- If what you act on is the fill, the account’s ExecutionUpdate event reports each execution. For a strategy’s own orders, the help guide recommends OnExecutionUpdate over OnOrderUpdate for fill logic.
If “Subscribed” prints and a live fill still prints nothing, post those Output lines and the part of your code that looks up the account and subscribes, and I will look at them.
Check the corresponding trace file (in “My Documents\NinjaTrader 8\trace”).
I discovered the issue. There were multiple Accounts in Account.All with the same Name. The orders submitted from the Chart Trader were not being captured by the assigned Event Handler in the Strategy, because the Strategy was grabbing the incorrect Account object. I made sure when I subscribed to the Event Handler in the Strategy, I chose the correct Account from Account.All by adding additional search criteria rather than searching on just Name only.
Thank you @ScorpioEdge and @sam028 for your assistance.
There’s an account “Name” and an account “Display Name”, which can be different, this can be confusing.
The “Name” and “Display Name” were the same across both accounts. The differentiator was “Connection”. The two accounts had the same names, but a different “Connection”. I selected from Account.All using Name and Connection, and that was the resolution.