🚀 AI 一键生成 joinquant 策略代码

JoinQuant 如何设置 always_match_market_order 在非交易时间撮合?

joinquant | 发布时间: 2025/12/24
以下内容由 EasyQuant 生成。

问题描述

有没有办法在非交易时间下市价单并且立即成交?我想测试一些逻辑。

解决方案

在聚宽(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

注意事项

  1. 成交价格:在非交易时间成交时,使用的价格通常是上一分钟的收盘价上一日的收盘价(取决于当前是否有实时数据)。这可能与实际开盘后的价格有巨大差异,因此仅建议用于逻辑测试,不建议用于依赖精确价格的实盘模拟。
  2. 滑点影响:当开启此设置时,市价单的成交价不会受滑点设置(set_slippage)的影响。
  3. 限价单无效:如果您使用的是 LimitOrderStyle(限价单),即使开启了此选项,在非交易时间下单依然会处于挂单状态,直到进入交易时间且价格满足条件才会成交。
  4. 强制撮合:如果您使用的是限价单但希望强制成交,可以使用另一个实验性选项 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: 不建议。这是一个实验性功能,主要用于调试代码逻辑或连通性。在严肃的回测中,使用非交易时间的数据进行成交会引入“未来函数”或不切实际的成交价格,导致回测结果失真。