🚀 AI 一键生成 joinquant 策略代码

如何在 JoinQuant 回测结果中添加自定义的指标图表?

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

问题描述

我想在回测结果里画出我自己计算的MACD指标曲线,怎么做?

解决方案

在聚宽(JoinQuant)中,要在回测结果页面画出自定义的指标曲线(如MACD),核心是使用 record() 函数。

record() 函数可以在每个单位时间(如每天或每分钟)记录数值,回测结束后,系统会自动将这些数值绘制成曲线图,显示在回测结果页面的“收益曲线”下方。

下面是一个完整的策略示例,展示了如何获取历史数据、使用 talib 库计算 MACD 指标,并通过 record() 将 DIF、DEA 和 MACD 柱状值绘制出来。

实现代码

# -*- coding: utf-8 -*-
import jqdata
import talib
import numpy as np

def initialize(context):
    # 设定要操作的股票(以平安银行为例)
    g.security = '000001.XSHE'
    # 设定基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    # 每天运行一次
    run_daily(market_open, time='every_bar')

def market_open(context):
    security = g.security
    
    # 1. 获取历史收盘价数据
    # MACD计算通常需要较长的历史数据以保证EMA的准确性,这里取过去100天
    # 注意:include_now=True 包含当前bar的数据(回测中视频率而定,日频通常指包含当日收盘价)
    # 如果是在盘中运行,attribute_history 取的是前一分钟/前一天的数据,这里我们取过去100天
    h_data = attribute_history(security, 100, '1d', ['close'], skip_paused=True)
    
    # 提取收盘价为numpy数组,用于talib计算
    close_prices = h_data['close'].values
    
    # 2. 计算MACD指标
    # 使用 talib 库计算 MACD
    # 参数说明: close_prices, fastperiod=12, slowperiod=26, signalperiod=9
    # 返回值: dif (快线), dea (慢线), macd (柱状图)
    dif, dea, macd = talib.MACD(close_prices, 
                                fastperiod=12, 
                                slowperiod=26, 
                                signalperiod=9)
    
    # 3. 获取当天的指标值
    # 数组的最后一个元素即为最新的计算结果
    current_dif = dif[-1]
    current_dea = dea[-1]
    # 注意:talib计算出的macd通常是 (dif - dea),而国内看盘软件通常是 (dif - dea) * 2
    # 如果你想和通达信/同花顺对齐,可以将 macd 值乘以 2
    current_macd = macd[-1] * 2 
    
    # 4. 使用 record 函数绘图
    # 这里的参数名(如 My_DIF)将作为图表中曲线的名称
    # 注意:record 不支持绘制列表,只能绘制单个数值
    # 如果计算结果是 NaN (数据不足时),record 会自动处理
    if not np.isnan(current_dif):
        record(My_DIF=current_dif, 
               My_DEA=current_dea, 
               My_MACD=current_macd)
        
    # 简单的交易逻辑示例(仅为了让回测跑起来)
    # 金叉买入
    if current_dif > current_dea and context.portfolio.positions[security].total_amount == 0:
        order_value(security, context.portfolio.available_cash)
    # 死叉卖出
    elif current_dif < current_dea and context.portfolio.positions[security].total_amount > 0:
        order_target(security, 0)

关键点说明

  1. attribute_history:

    • 用于获取计算指标所需的历史数据。
    • MACD 依赖于指数移动平均(EMA),为了让计算结果稳定,建议获取的数据长度(count)要大于 slowperiod(26)的 3-4 倍以上,这里取了 100 天。
  2. talib.MACD:

    • 聚宽环境内置了 talib 库,这是计算技术指标最高效的方法。
    • 它返回三个数组,分别是 DIF、DEA 和 MACD柱。
  3. record(key=value, ...):

    • 这是绘图的核心函数。
    • key 是你在图例中看到的名字(例如代码中的 My_DIF)。
    • value 必须是一个具体的数字(float 或 int),不能是列表或数组。
    • 查看位置:回测完成后,在收益走势图的下方,会多出一个或多个图表区域,显示你记录的数据。
  4. 关于 MACD 的数值差异:

    • 标准的 talib 算法输出的 MACD 柱状值 = DIF - DEA
    • 国内大部分行情软件(如同花顺、通达信)显示的 MACD 柱状值 = (DIF - DEA) * 2
    • 代码中我做了 * 2 处理,以便符合国内习惯。