feat: implement order replacement for backtesting
This commit is contained in:
@@ -831,6 +831,10 @@ class Backtesting:
|
|||||||
amount = amount_to_contract_precision(
|
amount = amount_to_contract_precision(
|
||||||
amount or trade.amount, trade.amount_precision, self.precision_mode, trade.contract_size
|
amount or trade.amount, trade.amount_precision, self.precision_mode, trade.contract_size
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if self.handle_similar_order(trade, close_rate, amount, trade.exit_side, exit_candle_time):
|
||||||
|
return None
|
||||||
|
|
||||||
order = Order(
|
order = Order(
|
||||||
id=self.order_id_counter,
|
id=self.order_id_counter,
|
||||||
ft_trade_id=trade.id,
|
ft_trade_id=trade.id,
|
||||||
@@ -1116,6 +1120,10 @@ class Backtesting:
|
|||||||
orders=[],
|
orders=[],
|
||||||
)
|
)
|
||||||
LocalTrade.add_bt_trade(trade)
|
LocalTrade.add_bt_trade(trade)
|
||||||
|
elif self.handle_similar_order(
|
||||||
|
trade, propose_rate, amount, trade.entry_side, current_time
|
||||||
|
):
|
||||||
|
return None
|
||||||
|
|
||||||
trade.adjust_stop_loss(trade.open_rate, self.strategy.stoploss, initial=True)
|
trade.adjust_stop_loss(trade.open_rate, self.strategy.stoploss, initial=True)
|
||||||
|
|
||||||
@@ -1214,6 +1222,37 @@ class Backtesting:
|
|||||||
# default maintain trade
|
# default maintain trade
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def cancel_open_orders(self, trade: LocalTrade, current_time: datetime):
|
||||||
|
"""
|
||||||
|
Cancel all open orders for the given trade.
|
||||||
|
"""
|
||||||
|
for order in [o for o in trade.orders if o.ft_is_open]:
|
||||||
|
if order.side == trade.entry_side:
|
||||||
|
self.canceled_entry_orders += 1
|
||||||
|
elif order.side == trade.exit_side:
|
||||||
|
self.canceled_exit_orders += 1
|
||||||
|
# canceled orders are removed from the trade
|
||||||
|
del trade.orders[trade.orders.index(order)]
|
||||||
|
|
||||||
|
def handle_similar_order(
|
||||||
|
self, trade: LocalTrade, price: float, amount: float, side: str, current_time: datetime
|
||||||
|
) -> bool:
|
||||||
|
"""
|
||||||
|
Handle similar order for the given trade.
|
||||||
|
"""
|
||||||
|
if trade.has_open_orders:
|
||||||
|
oo = trade.select_order(side, True)
|
||||||
|
if oo:
|
||||||
|
if (price == oo.price) and (side == oo.side) and (amount == oo.amount):
|
||||||
|
logger.info(
|
||||||
|
f"A similar open order was found for {trade.pair}. "
|
||||||
|
f"Keeping existing {trade.exit_side} order. {price=}, {amount=}"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
self.cancel_open_orders(trade, current_time)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def check_order_cancel(
|
def check_order_cancel(
|
||||||
self, trade: LocalTrade, order: Order, current_time: datetime
|
self, trade: LocalTrade, order: Order, current_time: datetime
|
||||||
) -> bool | None:
|
) -> bool | None:
|
||||||
@@ -1399,7 +1438,7 @@ class Backtesting:
|
|||||||
self.wallets.update()
|
self.wallets.update()
|
||||||
|
|
||||||
# 4. Create exit orders (if any)
|
# 4. Create exit orders (if any)
|
||||||
if trade.has_open_position or trade.has_open_orders:
|
if trade.has_open_position:
|
||||||
self._check_trade_exit(trade, row, current_time) # Place exit order if necessary
|
self._check_trade_exit(trade, row, current_time) # Place exit order if necessary
|
||||||
|
|
||||||
# 5. Process exit orders.
|
# 5. Process exit orders.
|
||||||
|
|||||||
Reference in New Issue
Block a user