🚀 AI 一键生成 joinquant 策略代码
立即体验

如何在聚宽平台编写带财务过滤与涨停风控的小市值轮动策略?

joinquant | 发布时间: 2026/8/5
以下内容由 EasyQuant 生成。

问题描述

聚宽小市值轮动策略:如何结合财务过滤与止盈止损?
如何在聚宽中从中小板指数成分股筛选小市值股票,加入净利润、营业收入、审计意见、空仓月份和涨停风控条件?

解决方案

策略核心逻辑设计

小市值轮动策略在A股历史表现优异,但往往伴随着高波动和垃圾股踩雷风险。为了提升策略的稳健性,本策略在**中小板指数(399005.XSHE)**成分股的基础上,引入了以下多重过滤与风控机制:

  1. 股票池筛选:选取中小板指数成分股,避免全市场选股带来的超大盘或极度流动性不足问题。
  2. 财务指标过滤
    • 净利润:最近一期单季度净利润必须大于0(剔除亏损股)。
    • 营业收入:营业收入同比增长率大于0(确保公司业务处于扩张期)。
  3. 审计意见与ST过滤:利用聚宽 get_current_data() 接口实时剔除ST、*ST、退市整理期及停牌股票。
  4. 空仓月份避险:每年的1月和4月是年报与一季报集中披露期,垃圾股暴雷概率极高。策略在这两个月份选择主动空仓避险。
  5. 涨停风控:在下单交易时,若目标买入股已经封涨停,则放弃买入,避免追高挂单失败。

聚宽 Python 策略源码

请将以下代码复制到聚宽(JoinQuant)策略编辑器的 Python3 环境中运行:

import pandas as pd
from jqdata import *

def initialize(context):
    # 设定沪深300作为基准
    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')
    
    # 策略参数设置
    g.index_code = '399005.XSHE'  # 中小板指
    g.hold_num = 5                # 持股数量
    g.empty_months = [1, 4]       # 空仓避险月份(1月、4月)
    
    # 定时运行:每月第一个交易日开盘进行调仓
    run_monthly(my_rebalance, monthday=1, time='09:30')

def my_rebalance(context):
    current_month = context.current_dt.month
    
    # 1. 空仓月份风控:如果是1月或4月,全仓卖出,保持空仓
    if current_month in g.empty_months:
        log.info(f"当前月份为 {current_month} 月,触发季节性空仓风控,清仓避险。")
        for stock in list(context.portfolio.positions.keys()):
            order_target(stock, 0)
        return
        
    # 2. 获取中小板指数成分股
    index_stocks = get_index_stocks(g.index_code, date=context.current_dt)
    if not index_stocks:
        return
        
    # 3. 财务过滤:查询市值、净利润、营业收入增长率
    # 过滤条件:净利润 > 0 且 营业收入同比增长率 > 0
    q = query(
        valuation.code,
        valuation.market_cap,
        indicator.net_profit_to_total_operate_revenue_ttm, # 辅助参考
        indicator.inc_revenue_year_on_year
    ).filter(
        valuation.code.in_(index_stocks),
        income.net_profit > 0,                       # 净利润大于0
        indicator.inc_revenue_year_on_year > 0       # 营业收入同比增长
    ).order_by(
        valuation.market_cap.asc()                   # 按市值升序排序
    )
    
    df_fundamentals = get_fundamentals(q, date=context.current_dt)
    
    # 4. 过滤ST、停牌、退市股
    current_data = get_current_data()
    valid_stocks = []
    for stock in df_fundamentals['code']:
        if not current_data[stock].is_st and not current_data[stock].paused:
            # 排除名称中含ST或退市字样的股票
            if 'ST' not in current_data[stock].name and '退' not in current_data[stock].name:
                valid_stocks.append(stock)
                if len(valid_stocks) >= g.hold_num * 2: # 适当多取一些备选,防止因涨停无法买入
                    break
                    
    # 确定最终目标持仓列表
    target_list = valid_stocks[:g.hold_num]
    log.info(f"今日目标持仓列表: {target_list}")
    
    # 5. 执行调仓交易
    # 5.1 卖出不在目标持仓中的股票
    for stock in list(context.portfolio.positions.keys()):
        if stock not in target_list:
            order_target(stock, 0)
            log.info(f"卖出股票: {stock}")
            
    # 5.2 买入目标股票(加入涨停风控)
    for stock in target_list:
        # 检查是否封涨停
        stock_data = current_data[stock]
        if stock_data.last_price >= stock_data.high_limit:
            log.warn(f"股票 {stock} 已封涨停,放弃买入以防追高。")
            continue
            
        # 分配资金买入
        position_val = context.portfolio.total_value / g.hold_num
        order_target_value(stock, position_val)
        log.info(f"调仓买入/持有股票: {stock},目标价值: {position_val:.2f}")

关键API及函数解析

  • get_index_stocks:获取指定日期中小板指(399005.XSHE)的成分股列表,确保选股范围合规。
  • get_fundamentals:通过 income.net_profit > 0indicator.inc_revenue_year_on_year > 0 过滤掉基本面恶化、成长性不足的垃圾小市值股票。
  • get_current_data:获取股票的实时快照。通过 is_st 属性过滤ST审计意见异常股,通过 high_limit 限制在开盘即封涨停时进行买入,有效规避通道滑点与追高风险。