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

聚宽平台如何实现动态动量周期策略?(根据波动率切换15/25/35日回看窗口)

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

问题描述

聚宽动态动量周期:如何根据市场波动率切换回看窗口?
如何在聚宽策略中用短长期波动率比值识别市场状态,并动态选择 15 日、25 日或 35 日动量周期?

解决方案

在量化投资中,传统的动量策略通常采用固定的回看窗口(如20日或60日)。然而,市场状态在不断变化:在剧烈波动的震荡市中,长周期动量容易滞后,需要缩短窗口以快速反应;在趋势明显的平稳市中,则需要拉长窗口以过滤噪音。本文将教你如何在JoinQuant(聚宽)平台上,通过计算短长期波动率比值来识别市场状态,并动态切换 15日、25日、35日 的动量回看窗口。

一、 核心逻辑设计

  1. 波动率比值(Volatility Ratio)
    • 短期波动率:采用过去 10 个交易日收盘价的标准差(Std)。
    • 长期波动率:采用过去 60 个交易日收盘价的标准差(Std)。
    • 比值 $VR = \frac{Std_{10}}{Std_{60}}$
  2. 市场状态与窗口切换
    • 高波动状态($VR > 1.2$):短期波动剧烈,市场可能面临拐点或极速震荡。此时采用 15日短周期 动量,快速止盈止损。
    • 常态波动状态($0.8 \le VR \le 1.2$):市场处于常规趋势中。采用 25日中周期 动量。
    • 低波动状态($VR < 0.8$):市场极其平稳,趋势缓慢延伸。采用 35日长周期 动量,避免被微小噪音洗出局。
  3. 动量计算
    • 动量值 = $\frac{当前价格 - N日前的价格}{N日前的价格}$,选择动量值最高的标的买入。

二、 聚宽策略源码实现

以下是完整的策略代码,可直接复制到聚宽回测环境中运行:

import numpy as np
import pandas as pd
from jqdata import *

def initialize(context):
    # 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    
    # 股票池:沪深300成分股
    g.security_list = get_index_stocks('000300.XSHG')
    # 持仓目标数量
    g.target_num = 5
    
    # 设定交易税费
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    
    # 每周第一个交易日运行调仓
    run_weekly(my_rebalance, weekday=1, time='09:30')

def my_rebalance(context):
    # 获取股票池
    stocks = g.security_list
    
    # 1. 获取历史价格数据(用于计算波动率和动量)
    # 长期波动率需要60天,35日动量需要35天,因此至少取65天数据
    hist = history(65, unit='1d', field='close', security_list=stocks, df=True)
    
    # 2. 计算每只股票的短长期波动率比值
    # 短期标准差 (10日)
    std_short = hist.iloc[-10:].std()
    # 长期标准差 (60日)
    std_long = hist.iloc[-60:].std()
    # 避免分母为0
    std_long = std_long.replace(0, np.nan)
    vr = std_short / std_long
    
    # 3. 动态计算每只股票的动量值
    momentum_series = pd.Series(index=stocks, dtype=float)
    
    for stock in stocks:
        stock_vr = vr[stock]
        if pd.isna(stock_vr):
            continue
            
        # 根据波动率比值切换回看窗口
        if stock_vr > 1.2:
            lookback = 15  # 高波动,用短周期
        elif stock_vr < 0.8:
            lookback = 35  # 低波动,用长周期
        else:
            lookback = 25  # 常态,用中周期
            
        # 计算动量:(当前价 - N日前价) / N日前价
        current_price = hist[stock].iloc[-1]
        past_price = hist[stock].iloc[-lookback]
        
        if past_price > 0:
            momentum_series[stock] = (current_price - past_price) / past_price
            
    # 4. 筛选出动量最高的前5只股票
    momentum_series = momentum_series.dropna().sort_values(ascending=False)
    buy_list = list(momentum_series.head(g.target_num).index)
    
    # 5. 执行调仓
    # 卖出不在买入名单中的持仓
    for stock in list(context.portfolio.positions.keys()):
        if stock not in buy_list:
            order_target(stock, 0)
            log.info("卖出: %s" % stock)
            
    # 等权重买入目标股票
    if len(buy_list) > 0:
        target_value = context.portfolio.total_value / len(buy_list)
        for stock in buy_list:
            order_target_value(stock, target_value)
            log.info("买入/调仓: %s, 目标价值: %.2f" % (stock, target_value))

三、 关键API与函数解析

  1. history 获取历史数据
    策略中使用 history(65, unit='1d', field='close', ...) 一次性获取了计算波动率(最大60天)和动量(最大35天)所需的全部收盘价,避免了多次调用API,大幅提升了回测速度。
  2. std() 标准差计算
    利用 pandasstd() 函数直接对 DataFrame 的列进行滑动标准差计算,高效获取短期(10日)和长期(60日)的市场波动率。
  3. order_target_value 目标价值下单
    在最终调仓时,使用等权重资金分配。order_target_value(stock, target_value) 会自动计算当前持仓与目标价值的差额并进行补仓或减仓,非常适合多股票组合管理。