Enhance execution realism for gapping bar prices
Bug Report
Expected Behavior
Let's say we have two bars and a trailing stop order. We sell at today's close 100 and tomorrow's open is 200, the trailing stop offset is 5. The execution price of the trailing stop should be 200.
Actual Behavior
It's execution price is recorded as 105.
Steps to Reproduce the Problem
- Create two bars as described.
- Sell at today's close and set a trailing stop
Specifications
- OS platform: Linux
- Python version: 3.12
nautilus_traderversion: 1.211.0
Hi @cenwangumass 😊 , thank you for the report 👍 .
To confirm / accept it, it is practically needed to have MRE = minimalistic reproducible example, that does nothing else, just reproduces the issue), that operates on re
Sending template for MRE in case it would help you:
- https://github.com/nautechsystems/nautilus_trader/tree/develop/examples/other/minimal_reproducible_example
- The MRE already contains some bars (artificially generated, so no need to add your own data)
- Just add your order showcasing invalid behavior and that's all needed (should be easy to reproduce, if you already have your own code) 👍
Hi @cenwangumass
Thanks for the report.
For daily bars and market closes, I think your reasoning makes sense. The current implementation is designed for lower time frames, like 1-minute bars, where traders expect a continuous market simulation—stops trigger at the stop price, not the high/low of the next bar.
With daily bars, though, the session ends at the close, so the price gap to the next open could reasonably determine the stop trigger. We could potentially adjust this behavior just for DAY bars, or add a new bar configuration option. Either would be simpler than adding session times and a trading calendar.
What do you think—would one of these work for your use case?
After considering this issue more thoroughly, I realize the same problem could occur with any time interval - whether minute bars, 15-minute bars, or 1-hour bars. Whenever there's a significant gap between the previous close and the next open price, we'd encounter the same challenge.
This can happen for various reasons:
- Daily trading breaks (1-hour lunch periods)
- Weekend market closures
- Major news announcements causing substantial price gaps
It probably makes sense to develop a generic solution that works across all timeframes when price gaps are too large, regardless of the cause. The core issue isn't specific to daily bars - the same fundamental problem applies conceptually to any timeframe where significant price discontinuities occur.
@cjdsellers @stefansimik Thanks for the response! I'm implementing a strategy on 1-minute bars, where I sell SPY at close when the SMA is below the 200-day and set a trailing stop. With the current implementation, the Sharpe ratio appears >2 because the trailing stop executes at a favorable price, but in reality, the performance is quite poor because of opening gaps. So, I agree with @stefansimik that the issue isn’t specific to daily bars.
We need to develop a comprehensive strategy for handling large price gaps between bars in trading systems. Specifically, we should determine how different order types should be filled when these gaps occur.
Our approach should include:
- Creating a clear framework for the expected behavior of various common order types during price gaps:
- Market orders
- Stop-market orders
- Stop-limit orders
- Limit orders
- Other commonly used order types
- Comparing these expected behaviors with the current implementation
- Recommending appropriate changes based on this analysis
I haven't fully analyzed this issue yet, but wanted to outline the necessary steps toward finding a solution and the work that needs to be completed.
This is great and very useful thing to solve, which will make NT more robust solution, prepared for common issues like this.
I agree with both of you, gaps can occur for more reasons than just market sessions, and the necessary solution is more involved than adding a simple check for day bars.