Difference in TickReplay and Real-time backtesting

Hello guys,

For sometime I develop a strategy based on my own imbalance indicator. The indicator compared to the paid indicators on the market is working as expected and there is no differences.

However, I do not have the exact executions on my strategy back-testing.
As Jesse stated in my post on the old forum
https://forum.ninjatrader.com/forum/ninjatrader-8/strategy-development/1342332-visualizing-range-chart-strategy-not-proper#post1342581

there is difference between TickReplay backtesting and realtime startegy performance.

In the NinjaTrader documentation:
https://ninjatrader.com/support/helpGuides/nt8/NT%20HelpGuide%20English.html?developing_for__tick_replay.htm

is stated that the purpose of TickReplay is exactly to reproduce tick-by-tick the historical market events.

Could somebody explain what is the difference between TickReplay and real-time market events because it seems like in the NinjaTrader documentation is not explained very well.

Best wishes.

This is my understanding.

TickReplay uses 1 tick data to build the historical bars and uses the OnMarketData method to do so, which guarantees the data to be in the correct sequence. The OnMarketData method is not called on historical data, but it can be with TickReplay. NinjaTrader only calls the OnBarUpdate once per bar for historical data and does not call the OnMarketData method unless you use TickReplay. With TickReplay enabled, the historical data is replayed tick by tick.

You need to understand how Ninja handles historical fills. It creates three virtual bars to approximate the price movement within the bar. This provides a more realistic intra-bar fill, but it’s really not enough, which is why you are not getting the entries you are expecting.
https://ninjatrader.com/support/helpGuides/nt8/NT%20HelpGuide%20English.html?understanding_historical_fill_.htm

If you continue to read that, you’ll see the option for Order fill resolution. Setting this to High will allow you bring in 1 tick data series for better intra-bar fills. What I usually do is have a 1 tick data series in the strategy and use it for entries. The strategy will be triggered based on the primary data series, but enter where the 1 tick data series is at the time. Even though it’s not going to be exactly the same as if it was live, this provides more accurate backtesting. When running a historical backtest even with the 1 tick data series, Ninja still doesn’t know if your stop or target was touched first in the same bar. For example, using a 1 minute bar, if you enter in at 100 and your target was at 105, but the stop was at 95 and the bar touched both… which came first? Ninja doesn’t know and guesses based on the three virtual bars.

To get the most accurate results, you want to use your strategy in replay mode because Ninja replays the historical data tick by tick in order as if it is happening live.

2 Likes

@ WaleeTheRobot Thank you for your detailed reply.
As you explained, this means that there is no way for having real back-test even with the 1-tick data series. The only way for doing so is market “Playback”. But having in mind that the Playback connection is real-time and the need to do 2-3 months of back-test seems to be unreachable.

Is speeding up the Playback connection giving real-time results? Or it is just skipping the time intervals?

Best wishes

Another option to achieve maximum accuracy in the filleds of the exit orders (takeprofit + stoploss) is to program a multi-timeframe strategy. The second Dataserie would be 1-tick to achieve maximum precision in the filleds. The main dataserie (eg 15min) would be used to detect the input triggers, and the orders (enter & exit) would be sent in the secondary dataserie (which, being in 1-tick they would not have delay).

Speeding up the playback will give you more realistic results. I usually just use around 8 to 10x the speed. You should consider using the replay after you have a profitable strategy from backtest. It’s time consuming, but you’ll start to identify the reasons why your strategy may fail in real-time.

2 Likes

@WhaleeTheRobot Thank you for your reply.
But isn’t this approach of speeding up the Playback leading to slippage? Isn’t it going to skip some executions and not giving a real-time market conditions?

Best wishes

Yes you will see slippage. You can just play it at regular speed if you really want. All it does is replay the day tick by tick based on whatever speed you select.

You should see no difference in slippage between 1x and the highest speed. The same code will be run on every tick at any speed, nothing is being “skipped”.

1 Like

Oh you are right. I guess it makes sense logically that nothing should be skipped. Maybe I noticed it years ago when testing scalping algos for small stops and targets and probably just kept it at a lower speed since. Maybe the there could be timing issues if someone is scalping for smaller targets and stops.

1 Like

Thank you for your support guys and @ WaleeTheRobot
I did a real-time strategy testing and I had a problem.

My strategy generated a huge loss on real-time using my demo account. On this picture you can see the entry price, entry and exit time, the reason for exit (Exit on session close):

My strategy opened a position but neither stop loss, nor take profit were activated.
Only “Exit on session close” saved me from generating additional losses. I lost my original chart view with marked position entries and exits to show you the exact edge case, but here is a representation on the chart and moment that are vital in executing my strategy:

I tried to reproduce the scenario via “Playback” connection to reproduce the most realistic real-time market conditions, but this time the case was not the same. The strategy was executed well enough and there was no problem with executing stop loss and take profit. Even on speed x2 it was executed correcly.

Diving deeper into my previous performance data I found this:


It seemed like the “stop loss” and “take profit” orders were rejected. I think this was not reasonable because as you can see the “Entry Price” is in the middle between “StopLoss” and “TakeProfit” price levels. They were not above/below the entry price level as someone could suggest.

  • What may be the reason for the StopLoss and TakeProfit orders to be Rejected?
  • Why on Playback this is not reproducable?
  • What is the appropriate way to implement some Rejected orders handling or something like FailSafe mechanism?

Best wishes

I think this is happening because in real time there will be slippage, so your entry won’t be activated as nicely as it does in playback, because that’s all historical data. There is no battle to fight for limit orders in playback so fills in playback aren’t necessarily how the trade would play out in real time.

I’m not entirely sure that would be the reason your orders are being rejected though. If you are manually coding and not using strategy builder, you would need to turn traceorders on, and you will get more data regarding the rejections in either the logs, or the output window, I forget which one it goes to.

Once you figure out why they are rejected, you can begin to edit your code to tackle those obstacles.

1 Like

Rockmanx00
Thank you for your answer.

Yes, in that case I turned on the TraceOrders and into the Output logs there was no info about the rejected orders. I also used “RealtimeErrorHandling.IgnoreAllErrors” because the default value for it is “RealtimeErrorHandling.StopCancelClose” - that means closing all orders and positions and stop the strategy. If not willing to stop the strategy but leave it working it is needed to be set
“RealtimeErrorHandling.IgnoreAllErrors” to ignore the errors on order executions and manually handle this rejected orders.

I need to handle them somehow!

I’ve usually seen the reason when I put TraceOrders on, so I’m guessing your lack of information has to do with the RealtimeErrorHandling. Have you tried changing that back to the default just to see if that would show you what rejection errors occurred?

I’ve seen this happen before too, but I never really put in the time to figure out what it was. It only happens maybe once or twice within a 1.5 years or so of backtest data so I wasn’t concerned about it.

Many of the bars in that scenario occur within the same millisecond (you can check this in the DataBox). Most likely, by the time the entry order was filled, the calculated price for the stop loss or take profit had already been exceeded, which caused the rejection. In Playback, the rejection didn’t happen because it doesn’t simulate such fine granularity (1-millisecond).

May be you are running your algo on some slower market with a low volatility!

Thank you.
I was also thinking if it is possible the time stamp to play a key role in this problem. Because I saw that sometimes there are many bars with the same time stamp. The time granularity is not so high and when I need to set an order may be the time stamp is like a reference into the NinjaTrader platform and it not allow for submitting several orders on the same time stamp? Just a guess! Not a 100% sure!