在 TargetPosTemplate
中,trade
函数的设计是为了确保在调整目标仓位时,先撤销未完成的旧订单,然后再发送新订单。你提到的在 cancel_old_order
之后立刻调用 send_new_order
的想法是可行的,但需要谨慎处理,以避免潜在的问题。
1. 能否在 cancel_old_order
之后立刻调用 send_new_order
?
是的,可以在 cancel_old_order
之后立刻调用 send_new_order
,以达到撤单后立刻重新挂单的效果。例如:
def trade(self) -> None:
"""执行交易逻辑"""
if not self.check_order_finished():
self.cancel_old_order()
self.send_new_order() # 撤单后立刻重新挂单
else:
self.send_new_order()
2. 为什么原函数没有这么写?
原函数没有在 cancel_old_order
之后立刻调用 send_new_order
,主要是为了避免以下潜在问题:
1) 撤单和挂单的异步性
在实盘中,撤单和挂单是异步操作。撤单请求发出后,交易所可能需要一定时间才能处理完成。如果在撤单未完成时立刻挂单,可能会导致以下问题:
- 撤单未完成,新订单可能无法成功挂出。
- 如果撤单和新订单同时存在,可能会导致仓位管理混乱。
2) 死循环风险
如果在 cancel_old_order
之后立刻调用 send_new_order
,而新订单又因为某些原因(如价格波动)无法立即成交,可能会导致策略不断撤单和挂单,陷入死循环。这种情况会显著增加交易成本和系统负载。
3) 交易所限制
某些交易所对撤单和挂单的频率有限制。频繁的撤单和挂单可能会触发交易所的风控机制,导致账户被限制交易。
3. 如何安全地实现撤单后立刻挂单?
如果你确实需要在撤单后立刻挂单,可以通过以下方式实现:
1) 等待撤单完成
在 cancel_old_order
之后,等待撤单完成后再调用 send_new_order
。可以通过 on_order
回调函数监听撤单状态:
def on_order(self, order: OrderData) -> None:
"""委托单更新回调"""
if order.status == Status.ALLTRADED or order.status == Status.CANCELLED:
self.send_new_order() # 撤单完成后重新挂单
2) 增加延迟
在 cancel_old_order
之后,增加一个短暂的延迟(如 1 秒),再调用 send_new_order
,以避免撤单和挂单的冲突:
import time
def trade(self) -> None:
"""执行交易逻辑"""
if not self.check_order_finished():
self.cancel_old_order()
time.sleep(1) # 增加延迟
self.send_new_order()
else:
self.send_new_order()
3) 限制撤单和挂单频率
通过计数器或时间戳限制撤单和挂单的频率,避免频繁操作:
def trade(self) -> None:
"""执行交易逻辑"""
if not self.check_order_finished():
self.cancel_old_order()
if self.can_send_new_order(): # 检查是否满足挂单条件
self.send_new_order()
else:
self.send_new_order()
4. 总结
- 在
cancel_old_order
之后立刻调用 send_new_order
是可行的,但需要谨慎处理异步性和死循环风险。
- 原函数没有这么写,主要是为了避免撤单和挂单的冲突、死循环风险以及交易所限制。
- 如果需要实现撤单后立刻挂单,可以通过等待撤单完成、增加延迟或限制频率等方式来确保安全。
希望以上解答对你有帮助!如果还有其他问题,欢迎继续讨论。
基于RAG技术开发的VeighNa AI助手,你的个人专属 Desk Quant