🚀 AI 一键生成 joinquant 策略代码

JoinQuant 均值回归实战:BIAS 乖离率交易策略(附代码)

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

问题描述

帮我写一个 BIAS 乖离率的均值回归策略

解决方案

这是一个基于 BIAS (乖离率) 指标的均值回归策略。

策略原理

BIAS (乖离率) 是测量股价偏离移动平均线大小程度的指标。

  • 公式:$BIAS(N) = \frac{收盘价 - N日移动平均价}{N日移动平均价} \times 100%$
  • 核心逻辑
    • 当股价严重偏离均线向下(负乖离率过大)时,认为市场超卖,股价有向均线回归的动力,此时买入
    • 当股价严重偏离均线向上(正乖离率过大)时,认为市场超买,股价有回调的风险,此时卖出

策略代码

以下代码可以直接在聚宽(JoinQuant)的回测环境中运行。

# -*- 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')
    
    # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    
    # --- 策略参数设置 ---
    # 操作的标的:这里以平安银行为例,也可以换成ETF如 '510300.XSHG'
    g.security = '000001.XSHE'
    
    # 均线周期 N
    g.N = 20
    
    # 买入阈值:当 BIAS 低于此值(负数)时买入
    g.buy_threshold = -6.0 
    
    # 卖出阈值:当 BIAS 高于此值(正数)时卖出
    g.sell_threshold = 6.0
    
    # 每天开盘时运行
    run_daily(market_open, time='09:30')

def market_open(context):
    """
    每日交易逻辑
    """
    security = g.security
    
    # 获取过去 N 天的收盘价数据
    # 注意:这里取 N 天,包含昨天。我们用昨天收盘价计算 BIAS 信号,今天开盘执行。
    # 这样避免了未来函数(即在收盘前不知道当天的最终收盘价)
    hist_data = attribute_history(security, g.N, '1d', ['close'])
    
    # 如果数据不足 N 天,不进行计算
    if len(hist_data) < g.N:
        return
    
    # 1. 计算 N 日移动平均线 (MA)
    ma_n = hist_data['close'].mean()
    
    # 2. 获取最近一个交易日(昨天)的收盘价
    current_price = hist_data['close'][-1]
    
    # 3. 计算 BIAS 乖离率
    # 公式:(收盘价 - 均线) / 均线 * 100
    bias_value = (current_price - ma_n) / ma_n * 100
    
    # 记录 BIAS 值,可以在回测图表中查看曲线
    record(BIAS=bias_value)
    
    # --- 交易决策 ---
    # 获取当前现金和持仓
    cash = context.portfolio.available_cash
    position = context.portfolio.positions[security].total_amount
    
    # 信号 1: 超卖(BIAS < 买入阈值),且当前无持仓 -> 全仓买入
    if bias_value <= g.buy_threshold and position == 0:
        # 用所有现金买入
        order_value(security, cash)
        log.info("BIAS: %.2f%% 触发超卖信号,买入 %s" % (bias_value, security))
        
    # 信号 2: 超买(BIAS > 卖出阈值),且有持仓 -> 清仓卖出
    elif bias_value >= g.sell_threshold and position > 0:
        # 卖出所有持仓
        order_target(security, 0)
        log.info("BIAS: %.2f%% 触发超买信号,卖出 %s" % (bias_value, security))

代码关键点解析

  1. 参数设置 (g.N, g.buy_threshold, g.sell_threshold):

    • g.N = 20: 使用20日均线(月线)作为基准。
    • g.buy_threshold = -6.0: 当股价低于20日均线6%时,视为超跌,执行买入。
    • g.sell_threshold = 6.0: 当股价高于20日均线6%时,视为超涨,执行卖出。
    • 注:不同波动率的股票适合不同的阈值,大盘股阈值绝对值可以设小一点(如±4%),小盘股或高波动标的可以设大一点(如±8%)。
  2. 数据获取 (attribute_history):

    • 我们获取了过去 g.N 天的数据。
    • 计算逻辑使用的是昨天的收盘价截止到昨天的均线。这是为了在今天开盘(09:30)时能立即下单。如果在盘中实时计算,需要使用分钟级数据或 get_current_data
  3. 交易执行 (order_value, order_target):

    • 策略设计为全仓买卖(All-in/All-out),简单直接。
    • order_value(security, cash): 用当前所有可用资金买入。
    • order_target(security, 0): 将持仓调整为0,即清仓。

优化建议 (Q&A)

Q: 如何让策略更稳健?
A: 单纯的 BIAS 策略在单边下跌趋势中可能会过早抄底导致被套(俗称“接飞刀”)。可以增加一个趋势过滤器,例如:只有当 60日均线向上时,才允许做 BIAS 的超跌反弹。

Q: 可以应用到多只股票吗?
A: 可以。将 g.security 改为一个列表(如 get_index_stocks('000300.XSHG')),然后在 market_open 中使用 for 循环遍历每只股票进行判断即可。

Q: 阈值该如何选择?
A: 建议使用聚宽的研究模块,统计目标股票历史上 BIAS 的分布情况(例如取 5% 和 95% 分位数),以此作为买卖阈值会比凭感觉设定更科学。