🚀 AI 一键生成 joinquant 策略代码

如何利用宏观经济数据(如 CPI)在 JoinQuant 中实现大盘择时?

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

问题描述

如何编写一个根据 CPI 数据来买卖指数基金的择时策略?

解决方案

编写一个基于宏观经济数据(如 CPI)的择时策略,核心在于利用 JoinQuant 的宏观数据接口 (macro.run_query) 获取历史 CPI 数据,并根据通胀水平来调整仓位。

策略逻辑设计

  1. 核心假设
    • 高通胀(CPI 过高):通常意味着央行可能加息或收紧流动性,利空股市。策略选择空仓或减仓。
    • 低/温和通胀(CPI 较低):通常意味着货币政策宽松或经济运行平稳,利好股市。策略选择满仓或买入。
  2. 标的:沪深300 ETF(例如 510300.XSHG)作为指数基金代表。
  3. 阈值设定:假设 CPI 同比增长率(YoY)超过 3% 为高通胀警戒线(此阈值可根据回测结果调整)。
  4. 调仓频率:CPI 数据通常按月发布,因此策略按月运行

策略代码实现

以下是完整的策略代码,可以直接在聚宽的回测环境中运行。

# -*- coding: utf-8 -*-
from jqdata import *

def initialize(context):
    """
    初始化函数,设定基准、标的、参数等
    """
    # 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    # 过滤掉order系列API产生的比error级别低的log
    log.set_level('order', 'error')
    
    # 设定操作标的:华泰柏瑞沪深300ETF
    g.security = '510300.XSHG'
    
    # 设定CPI阈值,当CPI同比 > 3.0% 时认为通胀过高,卖出
    g.cpi_threshold = 3.0
    
    # 设定按月运行,每月第一个交易日进行判断
    run_monthly(trade_func, monthday=1, time='open')

def trade_func(context):
    """
    交易函数:获取宏观数据并执行交易
    """
    # 1. 获取最新的CPI数据
    # 查询宏观数据表 macro.MAC_CPI_MONTH
    # 按统计月份倒序排列,取第一条(即离当前时间最近的一条已发布数据)
    q = query(
        macro.MAC_CPI_MONTH
    ).order_by(
        macro.MAC_CPI_MONTH.stat_month.desc()
    ).limit(1)
    
    df = macro.run_query(q)
    
    # 如果没有获取到数据,直接返回
    if df.empty:
        log.warn("未获取到CPI数据,跳过本次调仓")
        return

    # 获取CPI同比数据 (yoy: 上年同月=100)
    # 注意:聚宽数据库中 yoy 字段通常是百分比数值,例如 103.5 代表上涨 3.5%
    # 或者有些字段是直接的增长率,具体需看数据字典。
    # 在 macro.MAC_CPI_MONTH 表中,'yoy' 字段通常表示"上年同月=100"。
    # 因此,如果 yoy = 103.0,代表 CPI 同比增长 3.0%。
    # 我们取 'yoy' 字段。
    
    current_cpi_index = df['yoy'][0]
    
    # 计算同比增长率 (例如 103.5 -> 3.5)
    cpi_growth_rate = current_cpi_index - 100
    
    # 打印日志方便调试
    log.info(f"当前时间: {context.current_dt.date()}, 获取到的统计月份: {df['stat_month'][0]}, CPI指数(yoy): {current_cpi_index}, 同比增长: {cpi_growth_rate:.2f}%")

    # 2. 交易逻辑判断
    # 获取当前持仓市值
    position_value = context.portfolio.positions[g.security].value
    
    # 逻辑:如果 CPI 增长率 > 阈值 (3%),则清仓;否则满仓
    if cpi_growth_rate > g.cpi_threshold:
        # 判断是否持有仓位,如果有则卖出
        if position_value > 0:
            log.info(f"通胀过高 ({cpi_growth_rate:.2f}% > {g.cpi_threshold}%),执行清仓卖出。")
            order_target(g.security, 0)
            
    else:
        # 判断是否空仓,如果是则买入
        if position_value == 0:
            log.info(f"通胀温和 ({cpi_growth_rate:.2f}% <= {g.cpi_threshold}%),执行满仓买入。")
            # 用所有可用资金买入
            order_value(g.security, context.portfolio.available_cash)

def after_code_changed(context):
    """
    模拟交易更换代码后运行函数
    """
    g.cpi_threshold = 3.0

代码关键点解析

  1. 数据获取 (macro.run_query)
    • 我们使用了 macro.MAC_CPI_MONTH 表。
    • 未来函数规避:聚宽的 macro.run_query 在回测中会自动处理数据的“发布日期”。例如,1月份的 CPI 通常在 2月中旬发布。在 2月1日回测时,系统只会返回 12月份的数据(因为1月份的还没发),从而避免了未来函数。
  2. 数据字段 (yoy)
    • 在聚宽宏观数据库中,CPI 的 yoy 字段通常表示“上年同月=100”。所以代码中使用了 current_cpi_index - 100 来计算实际的百分比增长率。
  3. 交易频率 (run_monthly)
    • 宏观数据变化较慢,按月调仓足以捕捉趋势,同时能减少交易手续费。

常见问题 (Q&A)

Q: 为什么回测时发现交易信号有延迟?
A: 这是正常的。宏观数据有发布滞后期。例如,2023年5月的 CPI 数据通常在 2023年6月9日-15日左右公布。在6月1日运行时,你只能看到4月的数据。策略必须基于“当时已知”的数据进行决策,这符合实盘逻辑。

Q: 可以结合其他指标吗?
A: 可以。单一的 CPI 指标可能过于粗糙。常见的改进方案是:

  • CPI + PPI 剪刀差:同时获取 PPI 数据,分析利润空间。
  • CPI + 技术指标:用 CPI 定大方向(多/空),用均线(如20日均线)定具体的买卖点。
  • 利率债数据:结合国债收益率进行股债轮动。

Q: 如何查看更多宏观数据字段?
A: 在聚宽官网的“数据字典” -> “宏观经济数据”栏目中,可以找到所有可用的宏观表(如 GDP、PMI、货币供应量 M2 等)及其字段定义。

Q: 策略中的 ETF 可以换成股票吗?
A: 可以,但宏观择时通常针对大盘(Beta收益),个股受非系统性风险影响大,直接用宏观指标指导个股买卖效果可能不稳定。建议配合行业轮动或风格因子使用。