Skip to content

Commit d37e23f

Browse files
committed
feat: implement order replacement for backtesting
1 parent 48506f2 commit d37e23f

File tree

1 file changed

+40
-1
lines changed

1 file changed

+40
-1
lines changed

freqtrade/optimize/backtesting.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,10 @@ def _exit_trade(
831831
amount = amount_to_contract_precision(
832832
amount or trade.amount, trade.amount_precision, self.precision_mode, trade.contract_size
833833
)
834+
835+
if self.handle_similar_order(trade, close_rate, amount, trade.exit_side, exit_candle_time):
836+
return None
837+
834838
order = Order(
835839
id=self.order_id_counter,
836840
ft_trade_id=trade.id,
@@ -1116,6 +1120,10 @@ def _enter_trade(
11161120
orders=[],
11171121
)
11181122
LocalTrade.add_bt_trade(trade)
1123+
elif self.handle_similar_order(
1124+
trade, propose_rate, amount, trade.entry_side, current_time
1125+
):
1126+
return None
11191127

11201128
trade.adjust_stop_loss(trade.open_rate, self.strategy.stoploss, initial=True)
11211129

@@ -1214,6 +1222,37 @@ def manage_open_orders(self, trade: LocalTrade, current_time: datetime, row: tup
12141222
# default maintain trade
12151223
return False
12161224

1225+
def cancel_open_orders(self, trade: LocalTrade, current_time: datetime):
1226+
"""
1227+
Cancel all open orders for the given trade.
1228+
"""
1229+
for order in [o for o in trade.orders if o.ft_is_open]:
1230+
if order.side == trade.entry_side:
1231+
self.canceled_entry_orders += 1
1232+
elif order.side == trade.exit_side:
1233+
self.canceled_exit_orders += 1
1234+
# canceled orders are removed from the trade
1235+
del trade.orders[trade.orders.index(order)]
1236+
1237+
def handle_similar_order(
1238+
self, trade: LocalTrade, price: float, amount: float, side: str, current_time: datetime
1239+
) -> bool:
1240+
"""
1241+
Handle similar order for the given trade.
1242+
"""
1243+
if trade.has_open_orders:
1244+
oo = trade.select_order(side, True)
1245+
if oo:
1246+
if (price == oo.price) and (side == oo.side) and (amount == oo.amount):
1247+
logger.info(
1248+
f"A similar open order was found for {trade.pair}. "
1249+
f"Keeping existing {trade.exit_side} order. {price=}, {amount=}"
1250+
)
1251+
return True
1252+
self.cancel_open_orders(trade, current_time)
1253+
1254+
return False
1255+
12171256
def check_order_cancel(
12181257
self, trade: LocalTrade, order: Order, current_time: datetime
12191258
) -> bool | None:
@@ -1399,7 +1438,7 @@ def backtest_loop_inner(
13991438
self.wallets.update()
14001439

14011440
# 4. Create exit orders (if any)
1402-
if trade.has_open_position or trade.has_open_orders:
1441+
if trade.has_open_position:
14031442
self._check_trade_exit(trade, row, current_time) # Place exit order if necessary
14041443

14051444
# 5. Process exit orders.

0 commit comments

Comments
 (0)