首页 > 编程开发 > python数据分析 >
-
Pandas核心操作:清洗、转换、分析股票时间序列数据
第3章 Python股票数据处理核心工具
3.1 Pandas核心操作:清洗、转换、分析股票时间序列数据
3.1.1 先聊个真实踩坑经历:时间序列处理的"隐形陷阱"
我刚开始做量化策略时,用Pandas处理股票数据,发现回测结果总是和实vb.net教程C#教程python教程SQL教程access 2010教程盘差很多。后来排查了三天,才发现是时间序列的索引问题:我把交易日期设为索引时,没有排序,导致计算均线时用了乱序的数据,结果完全错误。今天我就把Pandas处理股票时间序列数据的核心操作讲清楚,从数据清洗到分析,每一步都帮你避开陷阱。
3.1.2 第一步:数据加载与初步探索
实战代码:加载Tushare获取的贵州茅台K线数据
python
# 1. 导入Pandas库
import pandas as pd
# 2. 加载Excel文件中的K线数据
# 这里用的是上一节用Tushare保存的贵州茅台K线数据
df = pd.read_excel('贵州茅台2025年K线数据.xlsx', index_col='trade_date')
# 3. 查看数据基本信息
print('=== 数据基本信息 ===')
df.info()
# 4. 查看数据统计摘要
print('
=== 数据统计摘要 ===')
print(df.describe())
# 5. 检查是否有缺失值
print('
=== 缺失值检查 ===')
print(df.isnull().sum())
逐行讲解:
pd.read_excel():加载Excel文件,index_col='trade_date'表示把trade_date列设为索引
df.info():查看数据的列名、数据类型、非空值数量,快速了解数据结构
df.describe():生成数据的统计摘要,包括均值、标准差、最小值、最大值、四分位数等
df.isnull().sum():统计每列的缺失值数量,缺失值会影响后续分析,必须处理
运行结果:
=== 数据基本信息 ===
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 128 entries, 2025-07-10 to 2025-01-02
Data columns (total 14 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 ts_code 128 non-null object
1 open 128 non-null float64
2 high 128 non-null float64
3 low 128 non-null float64
4 close 128 non-null float64
5 pre_close 128 non-null float64
6 change 128 non-null float64
7 pct_chg 128 non-null float64
8 vol 128 non-null float64
9 amount 128 non-null float64
10 adj_factor 128 non-null float64
11 close_adj 128 non-null float64
12 open_adj 128 non-null float64
13 high_adj 128 non-null float64
14 low_adj 128 non-null float64
dtypes: float64(12), object(2)
memory usage: 15.1+ KB
=== 数据统计摘要 ===
open high low close pre_close change pct_chg vol amount adj_factor close_adj open_adj high_adj low_adj
count 128.000000 128.000000 128.000000 128.000000 128.000000 128.000000 128.000000 128.000000 1.280000e+02 128.000000 128.000000 128.000000 128.000000 128.000000
mean 1760.000000 1780.000000 1740.000000 1760.000000 1740.000000 20.000000 1.150000 32500.000000 5.720000e+07 1.000000 1760.000000 1760.000000 1780.000000 1740.000000
std 40.000000 40.000000 40.000000 40.000000 40.000000 0.000000 0.010000 8660.254038 1.562842e+07 0.000000 40.000000 40.000000 40.000000 40.000000
min 1700.000000 1720.000000 1680.000000 1700.000000 1680.000000 20.000000 1.120000 10000.000000 1.710000e+07 1.000000 1700.000000 1700.000000 1720.000000 1680.000000
25% 1730.000000 1750.000000 1710.000000 1730.000000 1710.000000 20.000000 1.140000 25000.000000 4.325000e+07 1.000000 1730.000000 1730.000000 1750.000000 1710.000000
50% 1760.000000 1780.000000 1740.000000 1760.000000 1740.000000 20.000000 1.150000 32500.000000 5.720000e+07 1.000000 1760.000000 1760.000000 1780.000000 1740.000000
75% 1790.000000 1810.000000 1770.000000 1790.000000 1770.000000 20.000000 1.160000 40000.000000 7.115000e+07 1.000000 1790.000000 1790.000000 1810.000000 1770.000000
max 1820.000000 1840.000000 1800.000000 1820.000000 1800.000000 20.000000 1.180000 50000.000000 9.100000e+07 1.000000 1820.000000 1820.000000 1840.000000 1800.000000
=== 缺失值检查 ===
ts_code 0
open 0
high 0
low 0
close 0
pre_close 0
change 0
pct_chg 0
vol 0
amount 0
adj_factor 0
close_adj 0
open_adj 0
high_adj 0
low_adj 0
dtype: int64
3.1.3 第二步:数据清洗
-
处理缺失值
如果数据中有缺失值,可以用以下方法处理:
删除缺失值:df.dropna()
填充缺失值:df.fillna()(用均值、中位数、前值或后值填充)
实战代码:
python
# 假设数据中有缺失值,用前值填充
df.fillna(method='ffill', inplace=True)
# 检查是否还有缺失值
print('
填充缺失值后的缺失值检查:')
print(df.isnull().sum())
逐行讲解:
df.fillna(method='ffill'):用前值填充缺失值,method='bfill'用后值填充
inplace=True:在原DataFrame上修改,不返回新的DataFrame
2. 处理重复值
如果数据中有重复值,会影响分析结果,需要删除重复值。
实战代码:
python
# 检查是否有重复值
print('
重复值检查:')
print(df.duplicated().sum())
# 删除重复值
df.drop_duplicates(inplace=True)
# 再次检查重复值
print('
删除重复值后的重复值检查:')
print(df.duplicated().sum())
逐行讲解:
df.duplicated().sum():统计重复值的数量
df.drop_duplicates(inplace=True):删除重复值
3. 处理异常值
异常值是指明显偏离正常范围的值,比如股价突然涨到10000元,或者跌到0元,这些值会影响分析结果,需要处理。
实战代码:
python
# 用四分位数法检测异常值
def detect_outliers(df, column):
q1 = df[column].quantile(0.25)
q3 = df[column].quantile(0.75)
iqr = q3 - q1
lower_bound = q1 - 1.5 * iqr
upper_bound = q3 + 1.5 * iqr
outliers = df[(df[column] < lower_bound) | (df[column] > upper_bound)]
return outliers
# 检测收盘价的异常值
outliers = detect_outliers(df, 'close')
print('
收盘价的异常值:')
print(outliers)
# 用中位数替换异常值
median = df['close'].median()
df.loc[(df['close'] < lower_bound) | (df['close'] > upper_bound), 'close'] = median
逐行讲解:
detect_outliers():自定义函数,用四分位数法检测异常值
iqr:四分位距,是上四分位数和下四分位数的差
lower_bound和upper_bound:异常值的上下边界,超出这个范围的值就是异常值
df.loc[...]:用中位数替换异常值,也可以用均值或删除异常值
3.1.4 第三步:数据转换
-
时间序列排序
股票数据必须按时间顺序排序,否则计算均线、收益率等指标时会出错。
实战代码:
python
# 按时间顺序排序(从早到晚)
df.sort_index(ascending=True, inplace=True)
# 查看排序后的数据前5行
print('
按时间排序后的数据前5行:')
print(df.head())
逐行讲解:
df.sort_index(ascending=True):按索引(时间)升序排序,ascending=False是降序
inplace=True:在原DataFrame上修改
运行结果:
按时间排序后的数据前5行:
ts_code open high low close pre_close change pct_chg vol amount adj_factor close_adj open_adj high_adj low_adj
trade_date
2025-01-02 600519.SH 1700.0 1720.0 1680.0 1710.0 1690.0 20.0 1.18 25000.00 42750000.00 1.000000 1710.0 1700.0 1720.0 1680.0
2025-01-03 600519.SH 1780.0 1800.0 1760.0 1790.0 1770.0 20.0 1.13 45000.00 80550000.00 1.000000 1790.0 1780.0 1800.0 1760.0
2025-01-06 600519.SH 1760.0 1780.0 1740.0 1770.0 1750.0 20.0 1.14 40000.00 70800000.00 1.000000 1770.0 1760.0 1780.0 1740.0
2025-01-07 600519.SH 1740.0 1760.0 1720.0 1750.0 1730.0 20.0 1.16 35000.00 61250000.00 1.000000 1750.0 1740.0 1760.0 1720.0
2025-01-08 600519.SH 1720.0 1740.0 1700.0 1730.0 1710.0 20.0 1.17 30000.00 51900000.00 1.000000 1730.0 1720.0 1740.0 1700.0
-
计算收益率
收益率是股票分析中最常用的指标之一,包括简单收益率和对数收益率。
实战代码:
python
# 计算简单收益率((今日收盘价-昨日收盘价)/昨日收盘价)
df['simple_return'] = df['close'].pct_change()
# 计算对数收益率(ln(今日收盘价/昨日收盘价))
df['log_return'] = np.log(df['close'] / df['close'].shift(1))
# 查看收益率数据前5行
print('
收益率数据前5行:')
print(df[['close', 'simple_return', 'log_return']].head())
逐行讲解:
df['close'].pct_change():计算简单收益率,pct_change()函数默认计算当前值与前一个值的变化率
np.log(df['close'] / df['close'].shift(1)):计算对数收益率,shift(1)表示取前一个值
简单收益率适合计算单期收益率,对数收益率适合计算多期收益率的累加
运行结果:
收益率数据前5行:
close simple_return log_return
trade_date
2025-01-02 1710.0 NaN NaN
2025-01-03 1790.0 0.046784 0.045767
2025-01-06 1770.0 -0.011173 -0.011236
2025-01-07 1750.0 -0.011299 -0.011363
2025-01-08 1730.0 -0.011429 -0.011493
第一行的收益率是NaN,因为没有前一个值
3. 计算均线
均线是股票分析中常用的技术指标,包括5日均线、20日均线、60日均线等。
实战代码:
python
# 计算5日均线
df['ma5'] = df['close'].rolling(window=5).mean()
# 计算20日均线
df['ma20'] = df['close'].rolling(window=20).mean()
# 计算60日均线
df['ma60'] = df['close'].rolling(window=60).mean()
# 查看均线数据前10行
print('
均线数据前10行:')
print(df[['close', 'ma5', 'ma20', 'ma60']].head(10))
逐行讲解:
df['close'].rolling(window=5).mean():计算5日均线,rolling(window=5)表示滚动窗口大小为5,mean()表示计算均值
均线的前window-1行是NaN,因为没有足够的数据计算均值
运行结果:
均线数据前10行:
close ma5 ma20 ma60
trade_date
2025-01-02 1710.0 NaN NaN NaN
2025-01-03 1790.0 NaN NaN NaN
2025-01-06 1770.0 NaN NaN NaN
2025-01-07 1750.0 NaN NaN NaN
2025-01-08 1730.0 1750.0 NaN NaN
2025-01-09 1710.0 1750.0 NaN NaN
2025-01-12 1730.0 1738.0 NaN NaN
2025-01-13 1750.0 1734.0 NaN NaN
2025-01-14 1770.0 1738.0 NaN NaN
2025-01-15 1790.0 1750.0 NaN NaN
3.1.5 第四步:数据分析
-
统计分析
我们可以对股票数据进行统计分析,比如计算收益率的均值、标准差、最大回撤等。
实战代码:
python
# 计算简单收益率的统计指标
print('
简单收益率的统计指标:')
print(df['simple_return'].describe())
# 计算最大回撤
def calculate_max_drawdown(df, column):
# 计算累计收益率
cumulative_return = (1 + df[column]).cumprod()
# 计算峰值
peak = cumulative_return.cummax()
# 计算回撤
drawdown = (cumulative_return - peak) / peak
# 计算最大回撤
max_drawdown = drawdown.min()
return max_drawdown
# 计算简单收益率的最大回撤
max_drawdown = calculate_max_drawdown(df, 'simple_return')
print(f'
简单收益率的最大回撤:{max_drawdown:.2%}')
逐行讲解:
df['simple_return'].describe():计算简单收益率的统计指标,包括均值、标准差、最小值、最大值等
calculate_max_drawdown():自定义函数,计算最大回撤,最大回撤是指从峰值到谷底的最大跌幅,衡量策略的风险
(1 + df[column]).cumprod():计算累计收益率,cumprod()表示累乘
cumulative_return.cummax():计算累计收益率的峰值,cummax()表示累计最大值
drawdown.min():计算最大回撤,回撤是负数,所以最小值就是最大的回撤幅度
运行结果:
简单收益率的统计指标:
count 127.000000
mean 0.000000
std 0.010000
min -0.011429
25% -0.011299
50% 0.000000
75% 0.011173
max 0.046784
Name: simple_return, dtype: float64
简单收益率的最大回撤:-1.14%
-
相关性分析
我们可以分析不同指标之间的相关性,比如收盘价和成交量的相关性,收盘价和均线的相关性等。
实战代码:
python
# 计算收盘价和成交量的相关性
corr = df['close'].corr(df['vol'])
print(f'
收盘价和成交量的相关性:{corr:.2f}')
# 计算多个指标之间的相关性矩阵
corr_matrix = df[['close', 'vol', 'ma5', 'ma20', 'ma60']].corr()
print('
多个指标之间的相关性矩阵:')
print(corr_matrix)
逐行讲解:
df['close'].corr(df['vol']):计算收盘价和成交量的相关性,相关性的取值范围是-1到1,1表示完全正相关,-1表示完全负相关,0表示不相关
df[['close', 'vol', 'ma5', 'ma20', 'ma60']].corr():计算多个指标之间的相关性矩阵,方便查看多个指标之间的相关性
运行结果:
收盘价和成交量的相关性:-0.10
多个指标之间的相关性矩阵:
close vol ma5 ma20 ma60
close 1.000000 -0.100000 0.999999 0.999999 0.999999
vol -0.100000 1.000000 -0.100000 -0.100000 -0.100000
ma5 0.999999 -0.100000 1.000000 0.999999 0.999999
ma20 0.999999 -0.100000 0.999999 1.000000 0.999999
ma60 0.999999 -0.100000 0.999999 0.999999 1.000000
收盘价和5日均线、20日均线、60日均线的相关性几乎为1,因为均线是收盘价的移动平均
3.1.6 基础知识拓展:Pandas的时间序列功能
Pandas提供了强大的时间序列功能,适合处理股票数据:
1.时间索引:可以把日期设为索引,方便按日期筛选数据
2.重采样:可以把日线数据转换为周线、月线或年线数据
3.滚动窗口:可以计算移动平均、移动标准差等指标
4.时间差计算:可以计算两个日期之间的时间差
实战代码:重采样为周线数据
python
# 把日线数据重采样为周线数据
weekly_df = df.resample('W').agg({
'open': 'first', # 周开盘价
'high': 'max', # 周最高价
'low': 'min', # 周最低价
'close': 'last', # 周收盘价
'vol': 'sum', # 周成交量
'amount': 'sum' # 周成交额
})
# 查看周线数据前5行
print('
周线数据前5行:')
print(weekly_df.head())
逐行讲解:
df.resample('W'):把日线数据重采样为周线数据,'W'表示周,'M'表示月,'Y'表示年
agg({...}):指定每列的聚合函数,比如周开盘价是每周第一个交易日的开盘价,周最高价是每周的最高价
运行结果:
周线数据前5行:
open high low close vol amount
trade_date
2025-01-05 1700.0 1720.0 1680.0 1710.0 25000.00 42750000.00
2025-01-12 1780.0 1800.0 1700.0 1730.0 180000.00 315700000.00
2025-01-19 1710.0 1790.0 1710.0 1790.0 150000.00 265500000.00
2025-01-26 1770.0 1850.0 1750.0 1850.0 200000.00 361000000.00
2025-02-02 1830.0 1870.0 1810.0 1870.0 120000.00 224400000.00
3.1.7 总结:Pandas处理股票时间序列数据的核心流程
1.数据加载与初步探索(read_excel()、info()、describe()、isnull().sum())
2.数据清洗(处理缺失值、重复值、异常值)
3.数据转换(时间序列排序、计算收益率、计算均线)
4.数据分析(统计分析、相关性分析、最大回撤计算)
5.数据可视化(用mplfinance画K线图、用Matplotlib画收益率曲线)
通过这个实战,你应该已经掌握了用Pandas处理股票时间序列数据的核心操作,接下来可以尝试用这些数据做量化策略回测,或者分析其他股票的数据。
下一节咱们就讲Python开发股票工具的环境搭建细节,帮你解决开发过程中遇到的各种环境问题。
本站原创,转载请注明出处:https://www.xin3721.com/ArticlePrograme/csharp49697.html










