🚀 AI 一键生成 joinquant 策略代码

JoinQuant 平台如何利用 SecurityUnitData 对象计算 VWAP?

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

问题描述

如何获取股票过去3天的成交量加权平均价(VWAP)?

解决方案

在 JoinQuant(聚宽)平台中,获取股票过去 3 天的成交量加权平均价(VWAP)主要有两种方式:一种是直接使用 data 对象自带的便捷方法,另一种是通过获取历史行情数据手动计算。

以下是具体的实现方法和代码示例。

方法一:使用 data 对象的内置方法(推荐)

handle_data 函数中,data 参数(即 SecurityUnitData 对象)提供了一个直接计算 VWAP 的方法 .vwap(days)

  • 语法data[security].vwap(3)
  • 说明:计算过去 3 天(不包含当前分钟/当前天)的加权平均价。

方法二:使用 attribute_history 手动计算

如果你需要在 handle_data 之外的地方(如 before_trading_start)计算,或者需要更灵活的控制,可以使用 attribute_history 获取过去的成交额(money)和成交量(volume)进行计算。

  • 公式:$\text{VWAP} = \frac{\sum(\text{成交额})}{\sum(\text{成交量})}$
  • 代码逻辑
    1. 获取过去 3 天的 moneyvolume 数据。
    2. 将 3 天的 money 求和。
    3. 将 3 天的 volume 求和。
    4. 两者相除得到 VWAP。

完整策略代码示例

以下代码展示了如何在策略中同时使用这两种方法获取 VWAP:

# -*- coding: utf-8 -*-
def initialize(context):
    # 设定要操作的股票,例如平安银行
    g.security = '000001.XSHE'
    # 设定基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    # 按天回测时,每天调用一次 handle_data
    run_daily(handle_data, time='every_bar')

def handle_data(context, data):
    security = g.security
    
    # -------------------------------------------------------
    # 方法一:使用 data 对象内置的 vwap 方法 (最简单)
    # -------------------------------------------------------
    # 获取过去3天的VWAP
    vwap_builtin = data[security].vwap(3)
    
    log.info("内置方法获取的3日VWAP: %.2f" % vwap_builtin)
    
    # -------------------------------------------------------
    # 方法二:使用 attribute_history 手动计算 (更通用)
    # -------------------------------------------------------
    # 获取过去3天的成交额(money)和成交量(volume)
    # 注意:'1d'代表日频数据,skip_paused=True跳过停牌
    his = attribute_history(security, 3, '1d', ['money', 'volume'], skip_paused=True)
    
    # 计算总成交额和总成交量
    total_money = his['money'].sum()
    total_volume = his['volume'].sum()
    
    # 计算 VWAP
    if total_volume > 0:
        vwap_manual = total_money / total_volume
    else:
        vwap_manual = 0
        
    log.info("手动计算获取的3日VWAP: %.2f" % vwap_manual)
    
    # -------------------------------------------------------
    # 验证两者是否一致
    # -------------------------------------------------------
    # 注意:由于浮点数精度问题,可能会有微小差异
    log.info("两者差值: %.6f" % (vwap_builtin - vwap_manual))

关键点说明

  1. 数据包含范围

    • data[security].vwap(3)attribute_history(..., 3, ...) 获取的都是过去 3 个交易日的数据,不包含回测当天的实时数据。
    • 例如,如果在 2023-10-20 日运行策略,获取的是 10-17、10-18、10-19 这三天的数据。
  2. 复权影响

    • 建议在 initialize 中设置 set_option('use_real_price', True)。这样获取到的价格和成交量是真实发生的数据(动态复权),计算出的 VWAP 更符合实际交易逻辑。
  3. 停牌处理

    • attribute_history 默认 skip_paused=True,会自动跳过停牌日期向前查找,确保获取的是有交易的 3 天。
    • 内置的 .vwap() 方法也会自动处理停牌数据。

Q&A

Q: data[security].vwap(n) 包含当天的数据吗?
A: 不包含。在日级回测或分钟级回测中,该函数获取的是过去 n 天的数据。如果需要包含当天的实时 VWAP,需要获取当天的 tick 或分钟数据自行累加计算。

Q: 为什么手动计算的 VWAP 和行情软件上的均价线数值不一样?
A: 可能有两个原因:

  1. 复权问题:聚宽默认提供前复权数据,如果未开启 use_real_price,计算的是复权后的 VWAP。
  2. 时间窗口:行情软件上的均价线通常是指“当日的分时均价”(即当天的 VWAP),而上述代码计算的是“过去 N 天的历史 VWAP”。

Q: 如果过去 3 天内有停牌怎么办?
A: 聚宽的 API(如 attribute_history)通常带有 skip_paused 参数(默认为 True)。如果过去 3 个自然日内有停牌,系统会自动向前寻找最近的有效交易日,凑齐 3 个有交易数据的日子来计算。