股票拆分是上市公司常见的资本操作,比如1拆2、1拆3等,操作完成后股价会对应下降,成交量会对应上升,若直接使用原始历史数据做分析或回测,会得到完全错误的结果,因此需要用Pandas对历史股价和成交量做拆分调整,还原真实的投资收益和交易规模。

股票拆分调整的核心逻辑
股票拆分调整的核心是计算调整因子,调整因子的计算规则如下:
- 股价调整:拆分后的历史股价 = 拆分前的原始股价 / 拆分比例
- 成交量调整:拆分后的历史成交量 = 拆分前的原始成交量 * 拆分比例
比如某股票进行1拆2操作,拆分比例为2,那么拆分前1天的股价是20元,调整后为10元;拆分前1天的成交量是1000股,调整后为2000股。如果是合并操作,比如2合1,拆分比例为0.5,计算逻辑同理。
用Pandas处理拆分调整的步骤
1. 准备原始数据
首先需要准备两份数据,一份是股票的原始行情数据,包含日期、开盘价、收盘价、最高价、最低价、成交量;另一份是股票的拆分事件数据,包含拆分日期、拆分比例。
我们用Pandas构造示例数据:
import pandas as pd
# 构造原始行情数据
price_data = pd.DataFrame({
"date": pd.date_range("2024-01-01", periods=5),
"open": [10, 11, 12, 13, 14],
"close": [10.5, 11.5, 12.5, 13.5, 14.5],
"high": [11, 12, 13, 14, 15],
"low": [9.5, 10.5, 11.5, 12.5, 13.5],
"volume": [1000, 1100, 1200, 1300, 1400]
})
price_data["date"] = pd.to_datetime(price_data["date"])
# 构造拆分事件数据,假设2024-01-03进行1拆2操作,拆分比例为2
split_data = pd.DataFrame({
"split_date": [pd.Timestamp("2024-01-03")],
"split_ratio": [2]
})
2. 计算累计调整因子
如果股票存在多次拆分操作,需要计算累计调整因子,每次拆分的调整因子相乘得到最终的累计因子,再对历史数据做调整。
首先计算每个拆分日期对应的调整因子,然后按日期排序,计算累计乘积:
# 将拆分日期设为索引,按日期排序
split_data = split_data.sort_values("split_date").set_index("split_date")
# 计算累计调整因子,cumprod是累计乘积函数
split_data["cumulative_ratio"] = split_data["split_ratio"].cumprod()
split_data = split_data.reset_index()
3. 匹配调整因子到行情数据
需要将每个行情日期对应的调整因子匹配上,规则是:行情日期早于拆分日期的,使用拆分对应的累计调整因子;行情日期晚于等于拆分日期的,调整因子为1(不需要调整)。
# 对行情数据每个日期,找到小于等于该日期的最新拆分事件的累计调整因子
def get_adjust_ratio(date):
# 筛选拆分日期小于等于当前行情日期的记录
valid_splits = split_data[split_data["split_date"] <= date]
if valid_splits.empty:
return 1
# 取最新的拆分事件的累计调整因子
return valid_splits.iloc[-1]["cumulative_ratio"]
# 给行情数据添加调整因子列
price_data["adjust_ratio"] = price_data["date"].apply(get_adjust_ratio)
4. 执行股价与成交量调整
根据调整因子对对应的字段做计算,股价类字段除以调整因子,成交量字段乘以调整因子:
# 需要调整的价格类字段
price_cols = ["open", "close", "high", "low"]
# 调整的成交量字段
volume_cols = ["volume"]
# 执行价格调整
for col in price_cols:
price_data[f"{col}_adjusted"] = price_data[col] / price_data["adjust_ratio"]
# 执行成交量调整
for col in volume_cols:
price_data[f"{col}_adjusted"] = price_data[col] * price_data["adjust_ratio"]
# 查看调整后的结果
print(price_data[["date", "close", "close_adjusted", "volume", "volume_adjusted"]])
运行上述代码后可以看到,2024-01-01和2024-01-02的收盘价被除以2,成交量乘以2,2024-01-03及之后的数据因为拆分日期等于或晚于行情日期,调整因子为1,数据保持不变,符合拆分调整的逻辑。
注意事项
- 拆分比例的取值要准确,部分数据源的拆分比例可能是小数形式,比如1拆2会记为0.5,此时股价调整需要乘以比例,成交量调整需要除以比例,要和数据源的说明对应。
- 如果同时有分红、送股等操作,调整逻辑会更复杂,需要结合除权除息的规则计算综合调整因子,核心思路和拆分调整一致。
- 调整完成后建议做校验,比如计算拆分前后的总市值是否一致,拆分前总市值=股价*总股本,拆分后总股本翻倍,股价减半,总市值应该不变,以此验证调整逻辑的正确性。