3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在量化交易与回测中,股票除权除息(如送股、配股、分红)会导致价格出现不连续的缺口。为了准确计算真实的收益率和技术指标,我们需要对历史价格进行前复权(Forward Adjustment)或后复权(Backward Adjustment)。
PTrade 提供了 get_stock_exrights 接口,可以直接获取除权除息数据以及预计算好的复权因子。本文将详细介绍复权因子的计算公式,并提供完整的 Python 源码。
PTrade 的 get_stock_exrights(stock_code, date=None) 函数返回一个 DataFrame,其中包含四核心复权因子:
exer_forward_a: 前复权除权因子 Aexer_forward_b: 前复权除权因子 Bexer_backward_a: 后复权除权因子 Aexer_backward_b: 后复权除权因子 B$$\text{复权价格} = A \times \text{原始不复权价格} + B$$
exer_forward_a * price + exer_forward_bexer_backward_a * price + exer_backward_b以下策略代码示范了如何在 PTrade 中获取不复权历史价格,并结合 get_stock_exrights 获取的因子自定义计算前复权和后复权价格:
import pandas as pd
def initialize(context):
g.security = '600570.SS' # 恒生电子
set_universe(g.security)
def handle_data(context, data):
security = g.security
# 1. 获取不复权的历史日线数据 (fq=None)
df_price = get_history(20, '1d', field=['open', 'close'], security_list=security, fq=None)
if df_price is None or df_price.empty:
return
# 2. 获取股票的历史除权除息信息
exrights_df = get_stock_exrights(security)
if exrights_df is not None and not exrights_df.empty:
# 将交易日期的 index 或列统一格式以便对齐匹配
# 假设 df_price 的 index 为 datetime,转换成 YYYYMMDD 格式整数或字符串
df_price['date_int'] = [int(dt.strftime('%Y%m%d')) for dt in df_price.index]
# 按日期合并价格数据与除权数据
merged = pd.merge(df_price, exrights_df, left_on='date_int', right_index=True, how='left')global
# 向前填充复权因子(若当日无除权事件,延续上一次的因子)
merged['exer_forward_a'].fillna(method='ffill', inplace=True)
merged['exer_forward_b'].fillna(method='ffill', inplace=True)
merged['exer_backward_a'].fillna(method='ffill', inplace=True)
merged['exer_backward_b'].fillna(method='ffill', inplace=True)
# 缺省因子处理(如果历史早期无除权记录,A默认为1.0,B默认为0.0)
merged['exer_forward_a'].fillna(1.0, inplace=True)
merged['exer_forward_b'].fillna(0.0, inplace=True)
merged['exer_backward_a'].fillna(1.0, inplace=True)
merged['exer_backward_b'].fillna(0.0, inplace=True)
# 3. 使用公式计算自定义的前复权和后复权收盘价
merged['close_forward'] = merged['exer_forward_a'] * merged['close'] + merged['exer_forward_b']
merged['close_backward'] = merged['exer_backward_a'] * merged['close'] + merged['exer_backward_b']
log.info("自定义复权计算结果示例:")
log.info(merged[['close', 'close_forward', 'close_backward']].tail())
else:
log.info("未获取到除权除息数据,价格无需调整。")
get_history 或 get_price 中设置 fq='pre'(前复权)或 fq='post'(后复权)。自定义计算主要适用于需要精确调控因子或处理特殊除权逻辑的场景。exrights_df 仅包含发生除权除息的日期。在与日常价格序列匹配时,需使用 fillna(method='ffill') 进行填充。round() 进行精度处理。