问题描述
解决方案
在聚宽(JoinQuant)中,确实存在一种方法可以在非交易时间下市价单并立即成交。这通常用于模拟交易中的逻辑测试或特殊场景下的策略调试。
您需要使用 set_option 函数开启 always_match_market_order 选项。
核心方法
在 initialize 函数中添加以下代码:
set_option("always_match_market_order", True)
功能说明
- 立即撮合:开启此选项后,系统会总是撮合市价单。即使是在非交易时间(如晚上或周末)下单,系统也会按照最新的数据(通常是上一交易日的收盘价)立即撮合该订单。
- 仅限市价单:此设置仅对市价单(Market Order)有效,限价单仍然遵循标准的撮合逻辑(挂单等待)。
- 适用场景:主要用于策略逻辑的快速验证、模拟盘调试或需要全天候响应信号的特殊测试场景。
策略代码示例
以下是一个完整的策略示例,展示了如何开启该选项并在初始化阶段(通常是非交易时间运行)直接下单测试成交。
# -*- coding: utf-8 -*-
from jqdata import *
def initialize(context):
# 1. 开启实验性设置:允许非交易时间市价单立即成交
# 开启后,市价单将忽略交易时间限制,按最近一个价格立即撮合
set_option("always_match_market_order", True)
# 2. 设置基准和手续费(标准设置)
set_benchmark('000300.XSHG')
set_option('use_real_price', True)
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
# 3. 定义要操作的股票
g.security = '000001.XSHE' # 平安银行
# 4. 为了演示立即成交,我们在 initialize 中直接调用一个测试函数
# 注意:在回测中 initialize 运行在回测开始日期的开盘前;
# 在模拟交易中,如果在非交易时间重启/创建策略,也会运行此函数。
run_daily(test_order_logic, time='09:00') # 即使设定在09:00(开盘前),由于开启了选项,市价单也会成交
def test_order_logic(context):
log.info("--- 开始测试非交易时间下单 ---")
# 获取当前资金
cash = context.portfolio.available_cash
# 下一个市价单 (MarketOrderStyle)
# 注意:必须显式指定 style=MarketOrderStyle() 或使用默认 (默认为市价单)
# 这里买入 100 股
order_id = order(g.security, 100, style=MarketOrderStyle())
if order_id:
log.info(f"已下市价单,订单ID: {order_id}")
# 获取订单状态查看是否成交
# 注意:在回测引擎中,订单状态更新是同步的;但在模拟盘中可能有微小延迟,
# 但开启 always_match_market_order 后,引擎会尽快处理。
o = get_orders(order_id=order_id)[order_id]
log.info(f"订单状态: {o.status} (4代表全部成交/held)")
log.info(f"成交价格: {o.price}")
log.info(f"成交数量: {o.filled}")
else:
log.error("下单失败")
def handle_data(context, data):
pass
注意事项
- 成交价格:在非交易时间成交时,使用的价格通常是上一分钟的收盘价或上一日的收盘价(取决于当前是否有实时数据)。这可能与实际开盘后的价格有巨大差异,因此仅建议用于逻辑测试,不建议用于依赖精确价格的实盘模拟。
- 滑点影响:当开启此设置时,市价单的成交价不会受滑点设置(
set_slippage)的影响。 - 限价单无效:如果您使用的是
LimitOrderStyle(限价单),即使开启了此选项,在非交易时间下单依然会处于挂单状态,直到进入交易时间且价格满足条件才会成交。 - 强制撮合:如果您使用的是限价单但希望强制成交,可以使用另一个实验性选项
set_option("match_by_signal", True),它会对限价单进行强制撮合,不对价格和数量做检查。
Q&A
Q: set_option("always_match_market_order", True) 会影响限价单吗?
A: 不会。该选项仅针对市价单(Market Order)。如果您下的是限价单,在非交易时间仍然会挂单等待。
Q: 这种模式下成交的价格是基于什么确定的?
A: 系统会使用“最新的数据”进行撮合。在非交易时间,这通常意味着使用最近一次收盘的数据(例如昨日收盘价)。
Q: 为什么我在回测日志中看到订单状态是 held (4)?
A: 在聚宽的订单状态定义中,held (值为4) 代表订单已全部成交(All Filled)。这说明您的非交易时间下单测试成功了。
Q: 这个功能可以在实盘或严肃的策略回测中使用吗?
A: 不建议。这是一个实验性功能,主要用于调试代码逻辑或连通性。在严肃的回测中,使用非交易时间的数据进行成交会引入“未来函数”或不切实际的成交价格,导致回测结果失真。