3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在量化交易中,小市值策略因其历史超额收益而广受欢迎。然而,在实际交易或高仿真模拟盘中,小市值股票经常出现开盘即一字涨停、无法买入的情况。如果直接忽略,会导致账户出现大量闲置资金,降低整体资金利用率。
为了解决这个问题,我们需要在聚宽(JoinQuant)平台中实现轮循补仓机制:当首选的目标股票因涨停无法买入时,策略自动检测并跳过,将剩余资金依次分配给候选股票池中的后续股票。
get_current_data() 接口获取标的的实时盘面信息。通过 current_data[security].last_price 获取最新价,current_data[security].high_limit 获取涨停价。last_price >= high_limit,说明该股当前已封涨停,此时下单大概率无法成交,应判定为“无法买入”状态。以下是一个完整的小市值轮循补仓策略示例。策略在开盘时获取市值最小的 10 只股票,目标买入前 5 只。若有涨停,则自动用第 6-10 只递补。
import pandas as pd
from jqdata import *
def initialize(context):
# 设定沪深300作为基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 过滤掉比error级别低的log
log.set_level('order', 'error')
# 设定交易税费
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
# 目标持仓股票数量
g.target_num = 5
# 候选股票池大小
g.candidate_num = 15
# 定时运行:每天 09:30 运行
run_daily(market_open, time='09:30')
def market_open(context):
# 1. 获取小市值候选股票池
q = query(
valuation.code
).filter(
valuation.pe_ratio > 0 # 过滤掉亏损股
).order_by(
valuation.market_cap.asc() # 按市值升序
).limit(g.candidate_num)
df = get_fundamentals(q)
candidate_stocks = list(df['code'])
# 2. 卖出不在候选池中的持仓股票
current_positions = list(context.portfolio.positions.keys())
for stock in current_positions:
if stock not in candidate_stocks[:g.target_num]:
order_target(stock, 0)
log.info(f"卖出非目标股: {stock}")
# 3. 轮循买入机制
current_data = get_current_data()
bought_count = 0
for stock in candidate_stocks:
# 如果已经买够了目标数量,停止轮循
if bought_count >= g.target_num:
break
# 获取当前股票的持仓状态
position = context.portfolio.positions[stock]
# 如果已经持有,计入已买入数量,继续轮循
if position.total_amount > 0:
bought_count += 1
continue
# 检测是否涨停
last_price = current_data[stock].last_price
high_limit = current_data[stock].high_limit
paused = current_data[stock].paused
if paused:
log.info(f"股票 {stock} 停牌,跳过")
continue
if last_price >= high_limit:
log.info(f"股票 {stock} 已涨停(当前价 {last_price}),无法买入,自动寻找下一只候选股")
continue
# 计算可用资金并买入
# 将剩余可用资金均分给尚未买够的仓位
remain_slots = g.target_num - bought_count
available_cash = context.portfolio.available_cash
if available_cash > 5000: # 剩余资金大于起投额再操作
value_to_buy = available_cash / remain_slots
order_value(stock, value_to_buy)
log.info(f"成功递补买入: {stock}, 分配金额: {value_to_buy:.2f}元")
bought_count += 1
get_current_data() 的即时性:handle_data 或 run_daily 的 09:30 运行时,get_current_data() 能够获取到当天集合竞价结束后的最新开盘价。如果开盘即一字涨停,last_price >= high_limit 判定成立,完美避开废单。remain_slots:bought_count 增加。计算下一只股票的买入金额时,使用 available_cash / (g.target_num - bought_count),确保资金被精准均分,不会因为前序股票未买入而导致资金闲置。paused == True)也是导致资金闲置的重要原因,代码中一并进行了过滤递补处理。