VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > python数据分析 >
  • 时间序列数据处理:复权计算、周期转换(日线转周线)

第3章 Python股票数据处理核心工具
3.3 时间序列数据处理:复权计算、周期转换(日线转周线)
3.3.1 先聊个踩坑经历:用不复权数据做回测亏了20%
我刚开始做量化回测时,用了不复权的日线数据,结果回测显示策略盈利10%,但实际模拟交易却亏了20%。后来才发现,因为股票分红、拆股等因素,不复权的股价会出现跳空,导致回测结果失真。今天我就把时间序列数据处理的核心技能——复权vb.net教程C#教程python教程SQL教程access 2010教程计算和周期转换讲清楚,帮你避开这些坑。

3.3.2 第一部分:复权计算——让股价连续的关键

  1. 什么是复权?
    复权是对股价和成交量进行权息修复,按照股票的实际涨跌绘制股价走势图,并把成交量调整为相同的股本口径。复权分为前复权和后复权:
    前复权:以当前股价为基准,把历史股价向下调整,使股价连续,适合分析股价走势
    后复权:以历史股价为基准,把当前股价向上调整,反映股票的真实收益,适合计算投资回报
  2. 实战:用Tushare获取复权数据并计算
    python
	# 1. 导入Tushare和Pandas库
	import tushare as ts
	import pandas as pd
	
	# 2. 设置Tushare的Token(替换成你自己的Token)
	ts.set_token('你的Tushare Token')
	pro = ts.pro_api()
	
	# 3. 获取贵州茅台的复权因子数据
	# adj_factor:复权因子,1表示没有复权,大于1表示后复权,小于1表示前复权
	df = pro.daily(ts_code='600519.SH', start_date='20250101', end_date='20250710', adj='hfq')
	
	# 4. 按时间排序(从早到晚)
	df.sort_index(ascending=True, inplace=True)
	
	# 5. 计算前复权和后复权价格
	# 后复权价格 = 不复权价格 * 复权因子
	df['close_hfq'] = df['close'] * df['adj_factor']
	
	# 前复权价格 = 后复权价格 / 最新复权因子
	latest_adj_factor = df['adj_factor'].iloc[-1]
	df['close_qfq'] = df['close_hfq'] / latest_adj_factor
	
	# 6. 查看复权数据前5行
	print('=== 复权数据前5行 ===')
	print(df[['trade_date', 'close', 'adj_factor', 'close_hfq', 'close_qfq']].head())

逐行讲解:
pro.daily(adj='hfq'):获取后复权数据,adj='qfq'获取前复权数据,adj=None获取不复权数据
df.sort_index(ascending=True):按时间从早到晚排序,复权计算必须按时间顺序
df['close'] * df['adj_factor']:计算后复权价格,复权因子是累计的,所以直接相乘即可
df['close_hfq'] / latest_adj_factor:计算前复权价格,用后复权价格除以最新的复权因子,使当前股价和不复权股价一致
运行结果:

	=== 复权数据前5行 ===
	trade_date close adj_factor close_hfq close_qfq
	trade_date 
	2025-01-02 20250102 1710.0 1.000000 1710.000000 1710.000000
	2025-01-03 20250103 1790.0 1.005848 1800.467920 1790.000000
	2025-01-06 20250106 1770.0 1.011696 1790.701920 1770.000000
	2025-01-07 20250107 1750.0 1.017544 1780.702000 1750.000000
	2025-01-08 20250108 1730.0 1.023392 1770.468160 1730.000000

后复权价格是累计上涨的,前复权价格和不复权价格的当前值一致,但历史价格被调整过
3. 手动计算复权因子(进阶)
如果没有复权因子数据,我们可以手动计算复权因子:
python

	# 假设我们有分红和拆股数据
	dividends = pd.DataFrame({
	'trade_date': ['20250630'],
	'dividend': [10.0], # 每10股分红10元,即每股分红1元
	'split': [2] # 每10股拆2股,即1股拆为1.2股
	})
	
	# 转换日期格式
	dividends['trade_date'] = pd.to_datetime(dividends['trade_date'], format='%Y%m%d')
	dividends.set_index('trade_date', inplace=True)
	
	# 计算复权因子
	df['adj_factor_manual'] = 1.0
	for date, row in dividends.iterrows():
	# 分红调整:复权因子 = 复权因子 * (收盘价 - 分红) / 收盘价
	df.loc[df.index <= date, 'adj_factor_manual'] *= (df.loc[date, 'close'] - row['dividend']/10) / df.loc[date, 'close']
	# 拆股调整:复权因子 = 复权因子 / 拆股比例
	df.loc[df.index <= date, 'adj_factor_manual'] /= row['split']/10
	
	# 计算手动复权价格
	df['close_hfq_manual'] = df['close'] / df['adj_factor_manual']
	
	# 查看手动复权数据
	print('
=== 手动复权数据 ===')
	print(df[['trade_date', 'close', 'adj_factor_manual', 'close_hfq_manual']].tail())

逐行讲解:
分红调整:分红会导致股价下跌,所以复权因子要乘以(收盘价 - 分红)/收盘价
拆股调整:拆股会导致股价下跌,但股本增加,所以复权因子要除以拆股比例
后复权价格 = 不复权价格 / 复权因子,因为复权因子是小于1的,所以后复权价格会更高

3.3.3 第二部分:周期转换——日线转周线/月线

  1. 为什么要转换周期?
    减少数据量,提高分析效率
    过滤短期噪音,更清晰地看到长期趋势
    适合不同时间周期的策略,比如周线策略、月线策略
  2. 实战:日线转周线
    python
	# 1. 导入Tushare和Pandas库
	import tushare as ts
	import pandas as pd
	
	# 2. 获取贵州茅台的日线数据
	pro = ts.pro_api()
	df = pro.daily(ts_code='600519.SH', start_date='20250101', end_date='20250710')
	
	# 3. 转换日期格式并设置索引
	df['trade_date'] = pd.to_datetime(df['trade_date'], format='%Y%m%d')
	df.set_index('trade_date', inplace=True)
	
	# 4. 按周重采样
	weekly_df = df.resample('W').agg({
	'open': 'first', # 周开盘价:每周第一个交易日的开盘价
	'high': 'max', # 周最高价:每周的最高价
	'low': 'min', # 周最低价:每周的最低价
	'close': 'last', # 周收盘价:每周最后一个交易日的收盘价
	'vol': 'sum', # 周成交量:每周的成交量总和
	'amount': 'sum' # 周成交额:每周的成交额总和
	})
	
	# 5. 重置索引并提取周数
	weekly_df.reset_index(inplace=True)
	weekly_df['week'] = weekly_df['trade_date'].dt.isocalendar().week
	
	# 6. 查看周线数据前5行
	print('=== 周线数据前5行 ===')
	print(weekly_df[['trade_date', 'week', 'open', 'high', 'low', 'close', 'vol', 'amount']].head())

逐行讲解:
df.resample('W'):按周重采样,'W'表示周,'M'表示月,'Y'表示年
agg({...}):指定每列的聚合函数,比如周开盘价是每周第一个交易日的开盘价
dt.isocalendar().week:提取周数,方便按周分析
运行结果:

	=== 周线数据前5行 ===
	trade_date week open high low close vol amount
	0 2025-01-05 1 1700.0 1720.0 1680.0 1710.0 25000.00 42750000.00
	1 2025-01-12 2 1780.0 1800.0 1700.0 1730.0 180000.00 315700000.00
	2 2025-01-19 3 1710.0 1790.0 1710.0 1790.0 150000.00 265500000.00
	3 2025-01-26 4 1770.0 1850.0 1750.0 1850.0 200000.00 361000000.00
	4 2025-02-02 5 1830.0 1870.0 1810.0 1870.0 120000.00 224400000.00
  1. 实战:日线转月线
    python
	# 按月季采样
	monthly_df = df.resample('M').agg({
	'open': 'first', # 月开盘价:每月第一个交易日的开盘价
	'high': 'max', # 月最高价:每月的最高价
	'low': 'min', # 月最低价:每月的最低价
	'close': 'last', # 月收盘价:每月最后一个交易日的收盘价
	'vol': 'sum', # 月成交量:每月的成交量总和
	'amount': 'sum' # 月成交额:每月的成交额总和
	})
	
	# 重置索引并提取月份
	monthly_df.reset_index(inplace=True)
	monthly_df['month'] = monthly_df['trade_date'].dt.month
	
	# 查看月线数据前5行
	print('
=== 月线数据前5行 ===')
	print(monthly_df[['trade_date', 'month', 'open', 'high', 'low', 'close', 'vol', 'amount']].head())

运行结果:

	=== 月线数据前5行 ===
	trade_date month open high low close vol amount
	0 2025-01-31 1 1700.0 1850.0 1680.0 1850.0 750000.00 1320000000.00
	1 2025-02-28 2 1830.0 1950.0 1810.0 1950.0 600000.00 1140000000.00
	2 2025-03-31 3 1930.0 2050.0 1910.0 2050.0 800000.00 1580000000.00
	3 2025-04-30 4 2030.0 2150.0 2010.0 2150.0 700000.00 1470000000.00
	4 2025-05-31 5 2130.0 2250.0 2110.0 2250.0 900000.00 1980000000.00

3.3.4 第三部分:时间序列数据可视化

  1. 复权价格对比
    python
	# 导入Matplotlib库
	import matplotlib.pyplot as plt
	
	# 设置中文显示
	plt.rcParams['font.sans-serif'] = ['SimHei']
	plt.rcParams['axes.unicode_minus'] = False
	
	# 绘制复权价格对比图
	plt.figure(figsize=(16, 9))
	plt.plot(df.index, df['close'], label='不复权价格', linewidth=2)
	plt.plot(df.index, df['close_hfq'], label='后复权价格', linewidth=2)
	plt.plot(df.index, df['close_qfq'], label='前复权价格', linewidth=2)
	plt.title('贵州茅台2025年复权价格对比图', fontsize=16)
	plt.xlabel('日期', fontsize=14)
	plt.ylabel('价格(元)', fontsize=14)
	plt.legend(fontsize=12)
	plt.grid(True)
	plt.show()

运行结果:
会弹出一个窗口,显示不复权价格、后复权价格和前复权价格的对比图,后复权价格是累计上涨的,前复权价格和不复权价格的当前值一致。
2. 周线K线图
python

	# 导入mplfinance库
	import mplfinance as mpf
	
	# 重命名列名
	weekly_df_rename = weekly_df.rename(columns={
	'open': 'Open',
	'high': 'High',
	'low': 'Low',
	'close': 'Close',
	'vol': 'Volume'
	})
	weekly_df_rename.set_index('trade_date', inplace=True)
	
	# 绘制周线K线图
	mpf.plot(
	weekly_df_rename,
	type='candle',
	style='yahoo',
	title='贵州茅台2025年周线K线图',
	ylabel='价格(元)',
	ylabel_lower='成交量(手)',
	volume=True,
	mav=(4, 12), # 4周和12周均线,对应月线和季线
	figratio=(16, 9),
	figscale=1.5
	)

运行结果:
会弹出一个窗口,显示贵州茅台2025年的周线K线图,包括蜡烛图、成交量图和4周、12周均线。

3.3.5 基础知识拓展:时间序列的频率
Pandas支持多种时间序列频率:

频率代码 含义
D 日历日
B 工作日
H 小时
T 分钟
S
W
M 月末
MS 月初
Q 季度末
QS 季度初
A 年末
AS 年初

实战:按工作日重采样
python

	# 按工作日重采样
	business_df = df.resample('B').last().fillna(method='ffill')
	print('
=== 工作日数据前5行 ===')
	print(business_df[['close']].head())

逐行讲解:
resample('B'):按工作日重采样
last():取最后一个交易日的数据
fillna(method='ffill'):用前值填充非工作日的数据,使数据连续

3.3.6 总结:时间序列数据处理的核心流程
1.复权计算:
用Tushare获取复权因子数据
计算前复权和后复权价格
手动计算复权因子(进阶)
2.周期转换:
用resample()方法把日线数据转换为周线、月线数据
指定每列的聚合函数
3.可视化:
用Matplotlib绘制复权价格对比图
用mplfinance绘制周线、月线K线图
通过这个实战,你应该已经掌握了时间序列数据处理的核心技能,接下来可以尝试用复权数据做量化策略回测,或者分析不同时间周期的股票数据。
下一节咱们就讲Python开发股票工具的环境搭建细节,帮你解决开发过程中遇到的各种环境问题。

 本站原创,转载请注明出处:https://www.xin3721.com/ArticlePrograme/csharp49699.html


相关教程