Backtrader中关联父买入订单的止盈止损订单无法执行问题
Backtrader中关联父买入订单的止盈止损订单无法执行问题
看起来你遇到了Backtrader里用父订单关联止盈止损时的执行瓶颈,我来帮你拆解问题原因和解决办法:
问题核心分析
你当前的代码里,止盈止损订单绑定了self.order作为父订单,但这里很可能存在父订单引用错误的问题——self.order未必指向刚成交的那笔买入订单:
- 如果你在
next()里下单时没有正确把买入订单赋值给self.order,或者后续的操作覆盖了self.order的内容,那子订单的父关联就失效了,自然不会被触发执行。 - 另外,Backtrader的父子订单逻辑是:父订单完全成交后,子订单才会被提交到市场,错误的父引用会直接导致子订单“躺平”不生效。
修正方案
1. 修正父订单引用
把止盈止损订单的parent参数从self.order改成当前完成的order对象(也就是刚成交的买入订单),这样能确保子订单关联的是正确的父订单:
# 原代码 self.profit_order[instrument_name] = self.sell(size=order.executed.size, exectype=bt.Order.Limit, data = order.data, price=tpslData[1], parent = self.order) self.loss_order[instrument_name] = self.sell(size=order.executed.size, price=tpslData[0], data = order.data, exectype=bt.Order.Stop, parent = self.order) # 修改后 self.profit_order[instrument_name] = self.sell(size=order.executed.size, exectype=bt.Order.Limit, data=order.data, price=tpslData[1], parent=order) self.loss_order[instrument_name] = self.sell(size=order.executed.size, price=tpslData[0], data=order.data, exectype=bt.Order.Stop, parent=order)
2. 去掉手动取消子订单的逻辑
当使用父子订单关联后,Backtrader会自动处理“互斥触发”:只要其中一个子订单(止盈/止损)成交,另一个子订单会被系统自动取消,不需要你手动判断取消。可以删掉elif order.issell()里的取消代码,避免逻辑冲突。
修正后的完整notify_order代码
def notify_order(self, order): """ This method is used to monitor the status of an order. """ if order.status in [order.Submitted, order.Accepted]: # Order is in progress return instrument_name = order.data._name if order.status in [order.Completed]: if order.isbuy(): logging.info(f"BUY EXECUTED at price: {order.executed.price} for {instrument_name} with size {order.executed.size} ") # calculating profit and loss values tpslData = self.calculateTpSl(self.tpsl['long_pos'], order.executed.price, order.executed.size, True) # 关联当前成交的买入订单作为父订单 self.profit_order[instrument_name] = self.sell(size=order.executed.size, exectype=bt.Order.Limit, data=order.data, price=tpslData[1], parent=order) self.loss_order[instrument_name] = self.sell(size=order.executed.size, price=tpslData[0], data=order.data, exectype=bt.Order.Stop, parent=order) elif order.issell(): logging.info(f"SELL EXECUTED at price: {order.executed.price} for {instrument_name} with size {order.executed.size}") # 无需手动取消另一个子订单,Backtrader会自动处理 else: logging.error(f"Not a expected order type {order.executed.value}") elif order.status in [order.Canceled, order.Margin, order.Rejected]: logging.info(f"order status is {order.status} at price: {order.executed.price}")
额外注意点
- 检查
calculateTpSl返回的价格是否合理:多单的止盈价格要高于买入价,止损价格要低于买入价,否则子订单会因价格不符合成交逻辑而无法触发。 - 可以在
notify_order的Submitted/Accepted分支里添加日志,确认子订单是否被正常提交,方便排查问题。
备注:内容来源于stack exchange,提问作者Pritam Jinal
相关产品推荐
相关产品推荐

