🚀 AI 一键生成 qmt 策略代码

get_history_data 复权参数详解:前复权 vs 后复权 vs 不复权

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

问题描述

获取历史数据时 dividend_type 应该填什么?复权对策略有什么影响?

解决方案

在 QMT 量化交易平台中,dividend_type 参数用于控制获取行情数据时的复权方式。复权处理对于消除因分红、送股、配股等造成的股价“缺口”至关重要。

以下是关于 dividend_type 的详细参数说明及其对策略的具体影响。

1. dividend_type 参数填什么?

QMT 中有两个主要获取历史数据的接口,它们对 dividend_type 的参数要求不同,请根据你使用的函数选择:

A. 使用 ContextInfo.get_market_data_ex() (推荐接口)

该接口使用字符串来指定复权方式:

参数值 (String) 含义 说明
'none' 不复权 原始的交易所撮合价格,包含除权除息缺口。
'front' 前复权 (最常用) 以当前价格为基准,向下调整历史价格。保持最新价与实盘一致。
'back' 后复权 以历史上市价为基准,向上调整当前价格。适合计算长期累计收益。
'follow' 跟随主图 (默认) 跟随当前策略运行界面(或回测设置)中主图的复权设置。
'front_ratio' 等比前复权 相比普通前复权(等差),更能保持涨跌幅比例的一致性。
'back_ratio' 等比后复权 相比普通后复权(等差),更能保持涨跌幅比例的一致性。

B. 使用 ContextInfo.get_history_data() (旧版接口)

该接口使用整数 (int) 来指定复权方式:

参数值 (Int) 含义
0 不复权 (默认)
1 前复权
2 后复权
3 等比前复权
4 等比后复权

2. 复权对策略有什么影响?

复权的核心目的是保持价格走势的连续性。如果不进行复权,股票在发生“高送转”或“分红”时,股价会突然大幅下跌(例如 10 送 10,股价会腰斩),这种非市场交易导致的下跌会对策略产生严重误导。

(1) 对技术指标策略的影响 (MA, MACD, RSI 等)

  • 不复权的影响:如果股票发生除权(如股价从 20 元变成 10 元),均线系统会瞬间死叉,MACD 翻绿,RSI 暴跌。策略会误判为“暴跌”从而触发止损或卖出信号。
  • 正确做法必须使用前复权 (front)。前复权修复了缺口,使得技术指标能真实反映趋势。

(2) 对价格触发类策略的影响 (如:价格 > 100 买入)

  • 后复权的影响:后复权会将现在的价格根据历史分红不断向上调整,导致现在的“后复权价”可能远高于实际盘面价格(例如某股票现价 10 元,后复权价可能是 500 元)。如果策略逻辑包含具体的绝对价格判断(如 close > 20),使用后复权会导致逻辑失效。
  • 正确做法使用前复权 (front)。前复权保证了当天的收盘价与投资者在交易软件上看到的现价一致,便于逻辑判断。

(3) 对回测收益计算的影响

  • 不复权的影响:回测时如果在除权日持有股票,账户市值会突然缩水,导致回测收益率大幅低于真实水平。
  • 正确做法:QMT 的回测引擎通常会自动处理分红派息的资金回补,但在编写策略逻辑获取历史数据计算信号时,依然建议使用前复权以保证信号生成的准确性。

3. 最佳实践代码示例

在绝大多数趋势跟踪、均线交叉或机器学习策略中,建议统一使用 前复权 (front)

# -*- coding: gbk -*-

def init(ContextInfo):
    # 设置股票池
    ContextInfo.set_universe(['600519.SH']) 

def handlebar(ContextInfo):
    # 获取当前主图代码
    stock_code = ContextInfo.stockcode
    
    # 【推荐】使用 get_market_data_ex 获取前复权数据
    # 这样计算出来的 MA 均线才是平滑的,不会受分红除权影响
    data = ContextInfo.get_market_data_ex(
        fields=['close'], 
        stock_code=[stock_code], 
        period='1d', 
        count=100, 
        dividend_type='front'  # 显式指定前复权
    )
    
    if stock_code in data:
        df = data[stock_code]
        # 计算均线
        ma5 = df['close'].rolling(5).mean().iloc[-1]
        ma20 = df['close'].rolling(20).mean().iloc[-1]
        
        print(f"代码: {stock_code}, 最新价: {df['close'].iloc[-1]}, MA5: {ma5}, MA20: {ma20}")

Q&A

Q: 为什么实盘交易时有时候用“不复权”?
A: 在实盘交易的瞬间,交易所推送的 Tick 数据(分笔数据)是不复权的真实成交价。如果你的策略是基于盘口挂单价格(Order Book)或高频撮合逻辑,必须使用不复权数据。但在计算历史指标(如过去 5 天的均线)作为参考时,历史部分仍需复权。

Q: frontfront_ratio (等比前复权) 有什么区别?
A: 普通前复权通常是基于价格差额(等差)进行调整,可能会在极长的时间跨度下改变涨跌幅比例(例如 10 年前涨停板是 10%,复权后算出来可能不是 10%)。front_ratio(等比)通过乘法因子调整,能严格保持历史 K 线的涨跌幅百分比不变。对于对收益率敏感的模型(如机器学习训练),推荐使用 front_ratio

Q: 如果我不填 dividend_type 会怎样?
A: get_market_data_ex 默认是 'follow',即取决于你在 QMT 界面上右键点击 K 线图时选择的复权方式。为了防止策略在不同电脑或不同设置下表现不一致,强烈建议在代码中显式指定(如 'front')。