问题描述
2016-10-18 09:30:00 - WARNING - 已经跌停,市价卖单取消:StockOrder(entrust_id=1629514901 security=300526.XSHE mode=OrderTargetAmount: _amount=0 style=MarketOrderStyle: _limit_price=0.0 side=long action=close margin=False entrust_time=2016-10-18 09:30:00 error=)
试过通过order_target的返回是否为None来判断下单,但是已经跌停的情况好像不会返回None。请问如何获取到已跌停取消卖单的股票代码?
解决方案
在 JoinQuant 聚宽平台中,order_target 等下单函数返回 None 通常是因为订单创建失败(例如:股票停牌、代码错误、退市等)。
而跌停导致市价卖单取消,发生在订单撮合阶段。此时订单已经成功创建,因此 order_target 会返回一个 Order 对象,只是该订单在随后的撮合中因为跌停没有对手盘(市价单机制)而被系统撤销,状态变为了 canceled(已撤销)。
要获取这些被取消的股票代码,您可以通过以下两种方法:
方法一:下单后立即检查订单状态(推荐)
在回测模式下,市价单是同步撮合的。这意味着 order_target 执行完毕后,返回的 Order 对象已经包含了撮合结果。您可以直接检查该对象的 status 属性。
def handle_data(context, data):
security = '300526.XSHE'
# 假设我们要清仓
if context.portfolio.positions[security].closeable_amount > 0:
# 下单并获取返回的 Order 对象
my_order = order_target(security, 0)
# 检查订单是否创建成功且状态为已撤销
if my_order is not None:
# OrderStatus.canceled 的值为 2,也可以转为字符串判断
if str(my_order.status) == 'canceled' and my_order.filled == 0:
log.info(f"股票 {my_order.security} 因跌停或其他原因市价卖单被取消!")
# 在这里记录被取消的股票代码
# canceled_stocks.append(my_order.security)
方法二:使用 get_orders() 批量查询
如果您想在每天收盘后或特定时间点,统一获取当天所有被取消的卖单,可以使用 get_orders() 函数。
def after_trading_end(context):
# 获取当天所有订单
all_orders = get_orders()
canceled_sell_stocks = []
for order_id, order_obj in all_orders.items():
# 筛选条件:
# 1. 状态为已撤销 (canceled)
# 2. 是卖单 (is_buy == False)
# 3. 成交量为 0 (完全没卖出去)
if str(order_obj.status) == 'canceled' and not order_obj.is_buy and order_obj.filled == 0:
canceled_sell_stocks.append(order_obj.security)
if canceled_sell_stocks:
log.info(f"今日被取消的卖单股票有:{canceled_sell_stocks}")
💡 进阶建议:应对跌停的正确姿势
根据 JoinQuant 的撮合规则:跌停时市价卖单会被撤销,但限价单会挂单等待撮合。
如果您希望在跌停板上排队卖出(这在真实交易中是常见的做法),建议在判断股票可能跌停或已经跌停时,改用跌停价下限价单,而不是市价单。
current_data = get_current_data()
low_limit = current_data[security].low_limit # 获取跌停价
# 使用跌停价下限价单,这样订单会保持 open 状态挂单,而不是被直接 canceled
order_target(security, 0, style=LimitOrderStyle(low_limit))