![]() |
This website will be down for maintenance from Friday May 24th at 6PM MDT until Saturday May 25th at 11AM MDT. We apologize for the inconvenience. If you need assistance during this time, please email sales@ninjatrader.com
|
|||||||
| Strategy Development Support for the development of custom automated trading strategies using NinjaScript. |
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
Senior Member
Join Date: Jul 2008
Posts: 271
Thanks: 4
Thanked 7 times in 7 posts
|
I'm backtesting something using using the unmanaged approach, and I noticed a weird result.
If the next bar after the current bar would fill a limit order, the fill event fires off on the current bar rather than the next bar. In other words, a fill event for a limit order doesn't align with the bar that filled it. This misalignment messes up the logic for adjusting stops and targets on the current bar if the entry order's status has already been set to Filled before it actually happens, resulting in occasional errors in the backtest results. I got around this by delaying stoploss and target processing until the bar following the fill event (which is the bar that actually caused the fill). If others are accounting for this misalignment in their code and NinjaTrader corrects this behavior, it might break some things. -Alex |
|
|
|
|
|
#2 |
|
NinjaTrader Customer Service
Join Date: Sep 2008
Location: Germany
Posts: 22,398
Thanks: 252
Thanked 968 times in 951 posts
|
Thanks for the report Alex, I'm not aware of similiar issues seen sofar so would like to investigate with your help if possible.
Is there any way you could mask your proprietary logic and send me your script for testing to support at ninjatrader dot com Attn Bertrand? Please include datafeed, instrument / expiry and timeframe / chart type as well. Thanks much,
Bertrand
NinjaTrader Customer Service |
|
|
|
|
|
#3 |
|
Senior Member
Join Date: Jul 2008
Posts: 271
Thanks: 4
Thanked 7 times in 7 posts
|
It isn't a problem in my script. This should be easy to duplicate with a simple script. I was on a 2 minute chart of TF using a Zen-Fire data feed through Mirus Futures, with trades executed on a 20-second secondary data series.
-Alex |
|
|
|
|
|
#4 |
|
NinjaTrader Customer Service
Join Date: Sep 2008
Location: Germany
Posts: 22,398
Thanks: 252
Thanked 968 times in 951 posts
|
Alex, thanks - so this would be different for you in a managed script, is this correct?
I would be surprised since accessing bar info in the event order / execution method would not be a valid check for your situation, since the executions in backtesting are proccessed before the bar update events.
Bertrand
NinjaTrader Customer Service |
|
|
|
|
|
#5 | |
|
Senior Member
Join Date: Jul 2008
Posts: 271
Thanks: 4
Thanked 7 times in 7 posts
|
It is no different in a managed script.
Here's an example. TF 09-11 contract loaded from ZenFire, 2-minute bars, Default 24/7 session template, 2 days ending on 7/4/2011.
7/4/2011 8:26:00 Entered internal PlaceOrder() method at 7/4/2011 8:26:00: BarsInProgress=0 Action=SellShort OrderType=Limit Quantity=1 LimitPrice=839.3 StopPrice=0 SignalName='test' FromEntrySignal='' Filled on bar 298 at 839.3 where high=839 and low=838.8 Regardless of whether I use the managed or unmanaged approach, the fill event fires for 1 bar in the future, not on the bar where the order got filled. PHP Code:
Quote:
The problem is that I need to check order states in OnBarUpdate(), so that I can adjust stops and targets for any positions running. The order state is being set to "Filled" and the position is created before the bar that actually fills the entry. -Alex
Last edited by anachronist; 05-21-2012 at 04:54 PM.
|
|
|
|
|
|
|
#6 |
|
NinjaTrader Customer Service
Join Date: Sep 2008
Location: Germany
Posts: 22,398
Thanks: 252
Thanked 968 times in 951 posts
|
Thanks for the clarifications Alex, this would be expected in backtesting and it would not be different for managed vs unmanaged approach how the fill simulation would work - your CurrentBar print comes from the OnOrderUpdate() and it would report the last seen state, at the point your print this CurrentBar would not have advanced as OnBarUpdate() for the next bar has not yet been called. In simulation with CalculateOnBarClose = false this should align as you expext.
For the ExitOnClose issue - so is the position exited or the order expired at session boundary? For order expiration, please try with a TIF of GTC. http://www.ninjatrader.com/support/h...imeinforce.htm
Bertrand
NinjaTrader Customer Service |
|
|
|
|
|
#7 |
|
Senior Member
Join Date: Jul 2008
Posts: 271
Thanks: 4
Thanked 7 times in 7 posts
|
Regarding ExitOnClose, you're right, the order was a day order and had expired.
Indeed, for the managed approach, CalculateOnClose=false aligns the fill with the correct bar. The fact remains, however, that fills are still misaligned with the unmanaged approach regardless of the CalculateOnClose setting. Here's the same example using the unmanaged approach and a secondary series, this time printing out the bar and fill information from OnBarUpdate() instead of OnOrderUpdate(). For some reason the fill is reported two bars early. I have attached a chart showing the problem. PHP Code:
7/4/2011 8:26:00 Entered internal SubmitOrder() method at 7/4/2011 8:26:00: Action=Buy OrderType=Limit Quantity=1 LimitPrice=839.3 StopPrice=0 OcoId='' Name='test' Filled on bar 297 at 839.3 where high=838.9 and low=838.8 The attached picture should make the problem clearer. I am open to suggestions about how to manage exit orders if my fills are occurring too soon. The only approach I have come up with is to record the bar number of the fill and delay any further processing until the next bar -- but here I have a case where the fill is two bars early. -Alex
Last edited by anachronist; 05-22-2012 at 07:14 AM.
|
|
|
|
|
|
#8 |
|
NinjaTrader Customer Service
Join Date: Sep 2008
Location: Germany
Posts: 22,398
Thanks: 252
Thanked 968 times in 951 posts
|
Thanks Alex, let's take it a step back - so this would be a Buy Limit order you place above the market?
If yes, then what you see is expected - as it's a marketable limit order, it would fill immediately here in your case. Basically a limit order says, this 'price or better' > for the buy the lower (current) price is better, so it fills. If you would like to park an entry at this level, please try a StopLimit order type.
Bertrand
NinjaTrader Customer Service |
|
|
|
|
|
#9 |
|
NinjaTrader Customer Service
Join Date: Sep 2008
Location: Germany
Posts: 22,398
Thanks: 252
Thanked 968 times in 951 posts
|
I also just saw: you annotated the chart as Sell Short order, yet the code submits a Buy Limit entry. What's the desired action here for your test case?
Thanks,
Bertrand
NinjaTrader Customer Service |
|
|
|
|
|
#10 |
|
Senior Member
Join Date: Jul 2008
Posts: 271
Thanks: 4
Thanked 7 times in 7 posts
|
Aargh! This is what happens when I'm rushing to write code for this thread before the market opens. I make mistakes that waste your time, and I apologize for that.
You're right, I got confused. It was supposed to be a sell. If I correct the code, everything works properly. The fill event fires before CurrentBar is updated, but if I print things out in OnBarUpdate() the fill shows up on the correct bar. Now my problem is figuring out why, in my more complex strategy, OnBarUpdate() was showing me fills one bar before they actually happen. Even the chart showed this. This is 700 lines of code that attempts to emulate the behavior of ATM strategies in backtesting, so that's a bit much to post here; it's my problem to solve. It helps to know that in backtesting, OnOrderUpdate() occurs before OnBarUpdate(). That should help me figure out what's going on. -Alex |
|
|
|
|
|
#11 |
|
NinjaTrader Customer Service
Join Date: Sep 2008
Location: Germany
Posts: 22,398
Thanks: 252
Thanked 968 times in 951 posts
|
No worries Alex, glad to assist. Recreating the ATM's for backtesting can definitely be a challenging task, if you would like I can give your code a run here on my end to check into and see if anything stands out for you to investigate, no guarantees though - you're right this 700 line script would be involved to debug, but would be happy to offer a second set of eyes here. This is a MultiSeries script as well, correct? If so I would first take out those aspects and let it run as single series script (just for isolating out) - same discrepancy witnessed?
All the best,
Bertrand
NinjaTrader Customer Service |
|
|
|
|
|
#12 |
|
Senior Member
Join Date: Jul 2008
Posts: 271
Thanks: 4
Thanked 7 times in 7 posts
|
Oh, the ATM backtesting recreation is all done. There's just this niggling issue about the bar in which an order is filled. My methods called from OnBarUpdate() and OnOrderUpdate() print out the same values of the CurrentBars[] array after a fill, and these values are always 1 bar before the actual fill on both data series.
Aha. I managed to modify my simple test posted earlier to reproduce the problem. It does seem to be an issue with multiple time frames. I need to know the actual bars of the fill for all data series. Therefore I can't perform the test only when BarsInProgress==0. Initial condition: Zen-fire TF 06-12, 2-minute 24/7 template, 1 day ending 5/14/2012. Order is placed on bar 376. Should get filled on bar 377. Instead it gets filled on 376 (series 0), 631 (series 1) according to the CurrentBars values in OnBarUpdate(). Here's the script. PHP Code:
5/14/2012 6:06:00 Entered internal SubmitOrder() method at 5/14/2012 6:06:00: Action=Buy OrderType=Limit Quantity=1 LimitPrice=780.3 StopPrice=0 OcoId='' Name='test' Buy order filled on bar 376,631 at 780.3 where high=781.2 and low=781 Given the fill price and the high and low reported, it isn't logically possible for that bar. -Alex
Last edited by anachronist; 05-22-2012 at 07:42 PM.
|
|
|
|
|
|
#13 |
|
NinjaTrader Customer Service
Join Date: Sep 2008
Location: Germany
Posts: 22,398
Thanks: 252
Thanked 968 times in 951 posts
|
Thanks Alex, you've limited yourself with the Printed bool, as your code would execute for both BarsInProgress (you don't filter it) yet the only one BIP would print it - if you remove this and print for each call you can see -
5/14/2012 9:08:00 AM BIP 0 Buy order filled on bar 377, 633 at 780.3 where high=781 and low=780 which is the correct BIP 0 (2min frame) bar you submitted to for a fill, this info would only be valid to access in BIP0 which the above print does. From reviewing your code and fill behavior seen I do not see a misreporting.
Bertrand
NinjaTrader Customer Service |
|
|
|
|
|
#14 |
|
Senior Member
Join Date: Jul 2008
Posts: 271
Thanks: 4
Thanked 7 times in 7 posts
|
Aha. I think I get it. CurrentBars[x] isn't valid unless x==BarsInProgress. Right?
In my ATM backtest framework, I need to store the fill bar in each data series. So instead of what I've been doing in OnBarUpdate(): Code:
if (order.OrderState == OrderState.Filled && atm.fillbar[0] == 0) {
// record the bar in each data series on which the order filled
for (i = 0; i < CurrentBars.GetLength(0); ++i)
atm.fillbar[i] = CurrentBars[i];
}
Code:
if (order.OrderState == OrderState.Filled && atm.fillbar[BarsInProgress] == 0) {
// record the order fill bar
atm.fillbar[BarsInProgress] = CurrentBars[BarsInProgress];
}
-Alex
Last edited by anachronist; 05-23-2012 at 08:40 AM.
|
|
|
|
|
|
#15 |
|
Senior Member
Join Date: Jul 2008
Posts: 271
Thanks: 4
Thanked 7 times in 7 posts
|
OK, something is still fishy here. I changed my script to record the fill bar only only when BarsInProgress matches the data series. The fill bar for data series 0 is reported correctly, but the fill bar for data series 1 is still incorrect.
Here's the new test script. Same initial conditions, Zen-Fire TF 06-12, 2 minute data, 24/7 session template, 1 day of data ending 5/14/2012. PHP Code:
5/14/2012 6:06:00 Entered internal SubmitOrder() method at 5/14/2012 6:06:00: Action=Buy OrderType=Limit Quantity=1 LimitPrice=780.3 StopPrice=0 OcoId='' Name='test' Filled at 780.3 on series 0 bar 377 on series 1 bar 631 377 is correct for series 0. However, the fill bar on series 1 should be 632. The bar 631 is nowhere near the limit order price. Any ideas? I really need a consistent way to identify the correct fill bar on all data series. -Alex |
|
|
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Fill trades on currect close in backtesting | freewind | General Programming | 21 | 04-25-2012 08:27 AM |
| ProfitTarget filled on backtesting and did not fill on real scenario | Fabiorp | Strategy Analyzer | 3 | 01-02-2012 11:44 AM |
| backtesting - historical fill processing | adamus | Strategy Development | 5 | 06-21-2010 07:04 AM |
| Backtesting Timestamp/Order Fill Bug | DanielB | Version 7 Beta General Questions & Bug Reports | 12 | 05-28-2010 09:13 PM |
| Fill event notification, choice of ATI interface | sizeup | Automated Trading | 1 | 07-01-2007 04:08 AM |