Avoid opening position that gaps down with limit order
- Dominant language
- Python
- Stars
- 9k
- Forks
- 1.5k
- PR merge metrics
- No merged PRs in 30d
Description
I think it could be useful to have an option that control how we handle gaps down with limit orders. So this could be an enhancement.
### Expected Behavior
Let's say I am trade_on_close and set a buy limit order with a TP and SL attached. The order gets recorded on the close but won't fill until next candle (if price decline enough to match my limit order).
Then, the next day the stock gaps down past my buy limit and also past my stop loss, so the open will already be below my stop loss.
In that scenario, it could be useful to have an option that removes that order before it gets triggered to avoid getting into the position at the open in an awkward situation (with SL > buy price)
### Actual Behavior
Currently, in the above scenario, the stock is bought at the open and sold on the next day close (if trade_on_close) because the library doesn't allow to buy and sell on the same candle, (see https://github.com/kernc/backtesting.py/issues/119#issuecomment-2016788300), so it would be bought on the open on day 1 and sold at the close price on day 2. I think it would close on the day 2 open if trade_on_close = False, but haven't tested that).
So you are in a stock for whole 2 days without your SL getting triggered, although it should have triggered on the very same moment you entered the position.
### Suggestion
My suggestion would be to include something like
```python
# if open <= SL (being long) we don't even open the position
if order.limit:
if (order.is_long and price <= order.sl) or (order.is_short and price >= order.sl):
print("*** Open past SL => Order Removed ***")
self.orders.remove(order)
continue
```
just before calling `self._open_trade()` under the `_process_orders()` method. This would simply remove the order before we even enter the position.
Another option would be to control this behaviour through an additional variable, as I reckon this proposed behaviour makes more sense if we are backtesting on the daily timeframe (as by the open we would know AH/premarket prices and we could act on that new information), but it is probably less relevant or even cheating if we are thinking on intraday trading (as this will lead to some mixed behaviour were we are now both trading_on_close and also kind of trade_on_open because we are using 'future' open info to place or remove the order.
Contributor guide
Research direction
Start in the order-processing path at `_process_orders()`, especially the point before `_open_trade()`, and review the linked discussion in issue #119 for the same-candle constraint. Determine how a gap past an attached stop-loss should affect limit orders and whether the behavior needs an option for daily versus intraday backtests; done means the selected behavior is applied consistently without opening the position.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- fintech-quant
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100