问题描述
解决方案
在聚宽(JoinQuant)中,限制回测下单量不超过当日成交量一定比例的关键函数是 set_option('order_volume_ratio', value)。
该函数通常在 initialize 中调用。例如,设置 value 为 0.1,则意味着每一笔委托的成交量不会超过该标的当日(或该分钟Bar)总成交量的 10%。如果策略生成的订单数量超过这个限制,系统会自动将成交数量截断至该限制值,剩余部分会自动撤单(市价单)或挂单(限价单)。
以下是一个完整的策略示例:
# -*- coding: utf-8 -*-
import jqdata
def initialize(context):
"""
初始化函数,设定基准、复权模式及成交量限制
"""
# 设定沪深300作为基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 过滤掉order系列API产生的比error级别低的log,避免日志过多
log.set_level('order', 'error')
# ------------------------------------------------------------------
# 【核心设置】设置成交量比例限制
# 这里设置为 0.1 (即 10%)
# 含义:策略下单时,如果下单数量超过了该标的当日(或当前Bar)总成交量的10%,
# 系统会自动限制成交数量为总成交量的10%。
set_option('order_volume_ratio', 0.1)
# ------------------------------------------------------------------
# 定义一个全局变量, 保存要操作的股票 (例如:平安银行)
g.security = '000001.XSHE'
# 每天开盘时运行
run_daily(market_open, time='09:30')
def market_open(context):
"""
每日交易逻辑
"""
security = g.security
# 获取当前现金
cash = context.portfolio.available_cash
# 如果没有持仓,则尝试全仓买入
# 注意:虽然我们下达的是全仓买入指令,但受限于 order_volume_ratio,
# 实际成交量可能远小于全仓资金能购买的数量。
if context.portfolio.positions[security].closeable_amount == 0:
log.info("尝试全仓买入: %s" % security)
order_value(security, cash)
# 如果有持仓,且盈利超过10%,则卖出
elif context.portfolio.positions[security].closeable_amount > 0:
# 获取持仓成本和当前价格
cost = context.portfolio.positions[security].avg_cost
price = context.portfolio.positions[security].price
if price > cost * 1.1:
log.info("盈利超过10%,尝试卖出所有持仓: %s" % security)
order_target(security, 0)
def after_trading_end(context):
"""
收盘后运行,打印当天的成交情况以验证限制是否生效
"""
trades = get_trades()
for trade in trades.values():
log.info("今日成交ID: %s, 标的: %s, 成交数量: %s" % (trade.trade_id, trade.security, trade.amount))
代码解析
-
set_option('order_volume_ratio', 0.1):- 这是实现需求的核心代码。
- 参数
0.1代表 10%。 - 在回测中,如果当天该股票总成交量为 1,000,000 股,而策略试图买入 200,000 股(20%),系统会强制只成交 100,000 股(10%),超出的部分对于市价单会被撤销。
-
应用场景:
- 此设置主要用于模拟资金量较大的策略(如机构资金),防止回测结果因为“冲击成本”或“流动性不足”而失真。
- 如果不设置,默认为
1.0(即允许成交量达到当日总成交量的 100%),这在小资金回测中没问题,但大资金回测时会产生严重的虚假高收益。
Q&A
Q: set_option('order_volume_ratio', value) 中的 value 范围是多少?
A: value 是一个浮点数,通常在 0 到 1 之间。例如 0.05 代表 5%,1.0 代表 100%。
Q: 如果我的下单量被限制了,剩余未成交的部分会怎么样?
A: 这取决于订单类型:
- 市价单:超出限制的部分会被直接撤单。
- 限价单:超出限制的部分会继续挂单,在后续的撮合(如分钟回测的下一分钟)中继续尝试成交,直到订单过期或全部成交。
Q: 这个设置对模拟交易(实盘模拟)生效吗?
A: 生效。在模拟交易中,系统同样会根据实时的市场成交量来限制策略的成交量,以防止模拟盘对流动性预估过于乐观。
Q: 如何在回测中查看是否触发了成交量限制?
A: 可以在回测详情页面的“日志”中查看。如果订单因为流动性限制被部分成交或撤单,系统通常会输出相应的 Warning 日志,或者你可以通过对比 order.amount (下单数量) 和 order.filled (成交数量) 来判断。