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

在JoinQuant回测图表中添加多只股票同期复权收益率曲线的实现方法

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

问题描述

怎样在策略回策的图表下面,加上多个股票同期的收益率曲线?

策略是很简单的,就是在某个时间买入股票后一直持有。

回策的主图有 策略和基准的收益率真曲线的。现在我想在下图中加上其它一个或多个股票同期价格变化率 %

下图红框中,绿线是有除权的,这不准确。

怎么实际按复权来显示?请教高手这代码怎么写呢?谢谢。

解决方案

在JoinQuant(聚宽)平台中,要在回测图表下方添加自定义的曲线,可以使用 record() 函数。

关于你提到的**“绿线有除权,不准确”**的问题,这是因为在开启了真实价格模式(use_real_price=True)后,直接使用收盘价计算收益率会受到分红派息(除权除息)的影响,导致曲线出现向下的跳空缺口。

为了画出准确的复权收益率曲线,最巧妙且高效的方法是:利用每天的真实涨跌幅进行累乘。在聚宽的 data 对象中,data[stock].returns 直接提供了该股票当天的相对收益比例 (close - pre_close) / pre_close,这个值平台底层已经做好了复权处理,不会受到除权除息的影响。

以下是完整的策略代码示例,实现了买入持有,并在附图中绘制多只股票的同期复权收益率曲线:

# 导入聚宽函数库
import jqdata

def initialize(context):
    # 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格),实盘和回测强烈建议开启
    set_option('use_real_price', True)
    
    # 定义策略要买入持有的目标股票(例如:平安银行)
    g.target_stock = '000001.XSHE'
    
    # 定义你想在附图中对比收益率的其他股票列表
    # 例如:万科A, 贵州茅台
    g.compare_stocks = ['000002.XSHE', '600519.XSHG']
    
    # 初始化一个字典,用于记录对比股票的累计净值(初始为1.0)
    g.cum_returns = {stock: 1.0 for stock in g.compare_stocks}

def handle_data(context, data):
    # 1. 简单的买入持有策略逻辑
    if context.portfolio.positions[g.target_stock].total_amount == 0:
        # 如果没有持仓,则全仓买入
        order_value(g.target_stock, context.portfolio.available_cash)
        log.info("买入持有: %s" % g.target_stock)
        
    # 2. 计算并绘制对比股票的同期复权收益率曲线
    record_dict = {}
    for stock in g.compare_stocks:
        # 确保股票当天没有退市或未上市
        if not data[stock].isnan():
            # data[stock].returns 是当天的涨跌幅,平台已处理好复权
            daily_return = data[stock].returns
            
            # 累乘计算累计净值
            g.cum_returns[stock] *= (1 + daily_return)
            
            # 转换为百分比收益率,例如 1.05 -> 5.0
            pct_return = (g.cum_returns[stock] - 1) * 100
            
            # 将股票名称作为曲线的图例名称
            # 为了图例好看,可以获取股票的中文名
            stock_name = get_security_info(stock).display_name
            record_dict[stock_name] = pct_return
            
    # 使用 record 函数将数据画到图表上
    # record 函数接受 key=value 形式的参数,这里使用 ** 解包字典
    if record_dict:
        record(**record_dict)

代码原理解析:

  1. g.cum_returns 字典:在 initialize 中初始化为 1.0,代表本金净值。
  2. data[stock].returns:这是聚宽 API 提供的一个非常方便的属性,它等于 (close - pre_close) / pre_close。即使当天发生了分红送股,pre_close 也是调整后的前收盘价,因此算出来的 returns 是完全真实的单日涨跌幅。
  3. 累乘逻辑g.cum_returns[stock] *= (1 + daily_return),每天将当天的涨跌幅乘到累计净值上,完美避开了跨期复权因子计算的复杂性。
  4. record(**record_dict):将计算好的百分比收益率动态传入 record 函数,回测完成后,图表下方就会自动生成这几只股票平滑、准确的复权收益率曲线。