View Full Version : Orders not being canceled
heech
10-19-2010, 04:26 PM
Hi,
I'm really reaching in the dark here, just hoping someone can give me a clue that gives me ideas what to look at.
I have a complicated strategy which breaks down to this very simple behavior (in this case):
- primary bar is 30m, and not really relevant.
- on the last 5m historical bar (before "live" execution begins), I put in a Limit order.
- I note that the limit order does indeed go live (and everything looks normal from TraceOrder point of view).
- on the first LIVE 5m bar, I attempt to cancel this order. TraceOrders suggests I'm doing it right:
Cancelled custom managed order at 10/19/2010 3:22:08 PM: Order='NT-00000/Sim101' Name='ES 12-10|0|LN 9' State=Working Instrument='ES 12-10' Action=Buy Limit price=1155 Stop price=0 Quantity=1 Strategy='ProtectDownMulti' Type=Limit Tif=Day Oco='' Filled=0 Fill price=0 Token='e2477ed214e443e99a4b0dd358054617' Gtd='12/1/2099 12:00:00 AM'
... but, that's it. The order isn't actually canceled, and I don't see any OnOrderUpdate() events. I've confirmed the "token" itself is correct.
If this code is changed so that the first order isn't placed on a historical bar, but rather only from a live bar... then there are no problems. The cancel works perfectly.
I've tried to put together a small toy strategy to test this behavior, but frustratingly... it's working perfectly! Any other suggestions at things to consider?
NinjaTrader_Josh
10-19-2010, 04:36 PM
What version of NT are you on?
NinjaTrader_RyanM
10-19-2010, 04:38 PM
Hi Heech,
Can you let us know which version you're using and how you are cancelling this order?
heech
10-19-2010, 04:43 PM
Hi Heech,
Can you let us know which version you're using and how you are cancelling this order?
I'm on version 6.5.1000.17.
I'm canceling using a call to CancelOrder(IOrder).
heech
10-19-2010, 05:06 PM
I'm not sure what I changed... but now my basic example strategy is breaking as well.
Run on any instrument (I use NQ 12-10 in my test). I do have 'UniqueEntries' set. Note that the instrument then adds ES 12-10, and the trades in question are placed when BarsInProgress == 1.
#region Using declarations
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Data;
using NinjaTrader.Indicator;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Strategy;
#endregion
// This namespace holds all strategies and is required. Do not change it.
namespace NinjaTrader.Strategy
{
/// <summary>
/// Enter the description of your strategy here
/// </summary>
[Description("Enter the description of your strategy here")]
public class HistoricalOrder : Strategy
{
#region Variables
// Wizard generated variables
private int myInput0 = 1; // Default setting for MyInput0
// User defined variables (add any user defined variables below)
IOrder historicalOrder = null;
#endregion
/// <summary>
/// This method is used to configure the strategy and is called once before any strategy method is called.
/// </summary>
protected override void Initialize()
{
CalculateOnBarClose = true;
Add("ES 12-10", PeriodType.Minute, 1);
TraceOrders = true;
}
/// <summary>
/// Called on each bar update event (incoming tick)
/// </summary>
protected override void OnBarUpdate()
{
if (BarsInProgress != 1)
return;
if (Historical && CurrentBar == Count-2)
{
historicalOrder = EnterLongLimit(GetCurrentBid()*0.95);
Print("order0: " + historicalOrder);
return;
}
if (!Historical && historicalOrder != null)
{
Print("canceling orders...");
CancelOrder(historicalOrder);
historicalOrder = null;
}
}
protected override void OnOrderUpdate(IOrder order)
{
Print("OnOrderUpdate: " + order);
}
#region Properties
[Description("")]
[Category("Parameters")]
public int MyInput0
{
get { return myInput0; }
set { myInput0 = Math.Max(1, value); }
}
#endregion
}
}
The resulting output (and the order is NOT actually canceled):
10/19/2010 4:04:00 PM Entered internal PlaceOrder() method at 10/19/2010 4:04:00 PM: Action=Buy OrderType=Limit Quantity=1 LimitPrice=1103.25 StopPrice=0 SignalName='' FromEntrySignal=''
order0: Order='NT-00000/Sim101' Name='Buy' State=PendingSubmit Instrument='ES 12-10' Action=Buy Limit price=1103.1875 Stop price=0 Quantity=1 Strategy='HistoricalOrder' Type=Limit Tif=Gtc Oco='' Filled=0 Fill price=0 Token='7308edce892c421c94094901a45509eb' Gtd='12/1/2099 12:00:00 AM'
OnOrderUpdate: Order='NT-00000/Sim101' Name='Buy' State=PendingSubmit Instrument='ES 12-10' Action=Buy Limit price=1103.1875 Stop price=0 Quantity=1 Strategy='HistoricalOrder' Type=Limit Tif=Gtc Oco='' Filled=0 Fill price=0 Token='7308edce892c421c94094901a45509eb' Gtd='12/1/2099 12:00:00 AM'
OnOrderUpdate: Order='NT-00000/Sim101' Name='Buy' State=Accepted Instrument='ES 12-10' Action=Buy Limit price=1103.1875 Stop price=0 Quantity=1 Strategy='HistoricalOrder' Type=Limit Tif=Gtc Oco='' Filled=0 Fill price=0 Token='7308edce892c421c94094901a45509eb' Gtd='12/1/2099 12:00:00 AM'
OnOrderUpdate: Order='NT-00000/Sim101' Name='Buy' State=Working Instrument='ES 12-10' Action=Buy Limit price=1103.1875 Stop price=0 Quantity=1 Strategy='HistoricalOrder' Type=Limit Tif=Gtc Oco='' Filled=0 Fill price=0 Token='7308edce892c421c94094901a45509eb' Gtd='12/1/2099 12:00:00 AM'
OnOrderUpdate: Order='7308edce892c421c94094901a45509eb/Sim101' Name='Buy' State=PendingSubmit Instrument='ES 12-10' Action=Buy Limit price=1103.25 Stop price=0 Quantity=1' Type=Limit Tif=Gtc Oco='' Filled=0 Fill price=0 Token='7308edce892c421c94094901a45509eb' Gtd='1/1/0001 12:00:00 AM'
OnOrderUpdate: Order='7308edce892c421c94094901a45509eb/Sim101' Name='Buy' State=Accepted Instrument='ES 12-10' Action=Buy Limit price=1103.25 Stop price=0 Quantity=1' Type=Limit Tif=Gtc Oco='' Filled=0 Fill price=0 Token='7308edce892c421c94094901a45509eb' Gtd='1/1/0001 12:00:00 AM'
OnOrderUpdate: Order='7308edce892c421c94094901a45509eb/Sim101' Name='Buy' State=Working Instrument='ES 12-10' Action=Buy Limit price=1103.25 Stop price=0 Quantity=1' Type=Limit Tif=Gtc Oco='' Filled=0 Fill price=0 Token='7308edce892c421c94094901a45509eb' Gtd='1/1/0001 12:00:00 AM'
canceling orders...
heech
10-19-2010, 05:19 PM
If you look at the sequence of OnOrderUpdate messages, you see that the OrderId actually changes (but the token doesn't)... presumably when the order actually goes "live".
Is it possible that CancelOrder is trying to cancel the original (historical) NT-0000... order, instead of the live second version? Am I supposed to.. "capture" the new IOrder object inside OnOrderUpdate() when this happens? I'll give that a try.
NinjaTrader_RyanM
10-19-2010, 05:22 PM
Hi heech,
Thank you for the report and sample code. We will look into this and get back to you tomorrow.
heech
10-19-2010, 05:26 PM
That did it! I updated OnOrderUpdate to do this:
protected override void OnOrderUpdate(IOrder order)
{
Print("OnOrderUpdate: " + order);
if (order.Token == historicalOrder.Token)
{
Print("Resetting historical order... ");
historicalOrder = order;
}
}
This isn't documented, as far as I know. I don't have a problem with doing this (and I've just tried it out in my main code)... but can someone take a look, and please confirm I'm NOT going to be breaking something else by updating my references to the IOrder object every time I go into OnOrderUpdate()?
NinjaTrader_Bertrand
10-20-2010, 06:43 AM
Heech, I believe you're running into a bug here fixed for NT7, the token would be unique in 6.5 while the order ID would not be, correct. Would you mind testing the same strategy that exposed the issue on latest NT7 B22? In addition IOrder handling has been simplified in NT7 in the sense that you can now compare the IOrder objects directly for equality and would not need the tokens anymore.
heech
10-20-2010, 08:21 AM
Bertrand,
It's on my "to do" list to convert over... it's just that I have a long to do list. I'll do my best.
In the mean time, any problems that you can think of in terms of updating the IOrder object inside OnOrderUpdate? I always use the Token for any comparison, so that's not an issue. I just want to make sure any function calls that take IOrder will still function correctly... although I guess CancelOrder is the only one that I can think of which takes IOrder.
NinjaTrader_Bertrand
10-20-2010, 09:24 AM
heech, I hear you - I don't see an issue either with this.
heech
10-20-2010, 10:37 PM
I'm unfortunately coming to the conclusion that I can't trust the functionality, in terms of orders transitioning from "historical" to "live" in the current version.
I've just caught another .. bug? feature? complication?. If you have a limit order which is not legal when the market goes live (for example, an EnterLongLimit where the price is higher than the market)... the order is canceled (as confirmed by the 'log'), but your code is *not* notified via OnOrderUpdate(). And all the internal order handling rules are also broken from that point on.
Is this something that 7 handles better...?
EDIT: My work around is just to set flags historically... and then place actual "live" orders within the first valid OnMarketData event for the instrument.
NinjaTrader_RyanM
10-21-2010, 01:20 PM
Hello Heech,
In this case a long limit order submitted higher than the market results in a fill.