3、Pandas金融数据处理基础:Series与DataFrame、时间索引创建、数据读取与写入(CSV/Excel)、数据清洗与缺失值处理
做量化金融,说白了就是跟数据打交道。你策略再牛,模型再花哨,数据一塌糊涂,全白搭。我入行那会儿,第一个项目就是处理一堆从Wind导出的日频数据,格式乱得让人头皮发麻。那时候我就明白了一个道理:数据清洗占掉你80%的时间,剩下20%才是建模。所以这一章,咱们把Pandas这个吃饭的家伙彻底搞透。
3.1 Series与DataFrame:金融数据的左膀右臂
Pandas里就两个核心数据结构:Series和DataFrame。Series就是一列带标签的数据,你可以把它想象成Excel里的一列,但比那玩意儿灵活多了。DataFrame呢,就是多列Series拼起来的表格,金融数据基本都是这格式。
先看Series怎么用。我习惯把Series叫做“带索引的一维数组”。
import pandas as pd
import numpy as np
# 创建一个收盘价序列
close_prices = pd.Series([100.5, 102.3, 101.8, 103.6, 105.2],
index=['2024-01-02', '2024-01-03', '2024-01-04', '2024-01-05', '2024-01-08'],
name='close')
print(close_prices)
你看,索引和值是一一对应的。你想想看,如果只用Python列表,你得自己维护一个日期列表和一个价格列表,多麻烦。Series把这事儿给你封装好了。
DataFrame就更常用了。我处理股票数据时,通常会把开盘价、收盘价、最高价、最低价、成交量都塞进一个DataFrame里。
# 创建一个简单的OHLCV DataFrame
data = {
'open': [100.0, 102.0, 101.5, 103.0, 104.8],
'high': [101.2, 103.5, 102.8, 104.2, 106.0],
'low': [99.8, 101.5, 100.9, 102.5, 103.9],
'close':[100.5, 102.3, 101.8, 103.6, 105.2],
'volume':[10000, 12000, 11000, 13000, 15000]
}
df = pd.DataFrame(data, index=['2024-01-02', '2024-01-03', '2024-01-04', '2024-01-05', '2024-01-08'])
print(df)
3.2 时间索引创建:金融数据的灵魂
金融数据跟时间绑定的。没有时间戳的数据,就像没有坐标的地图,毫无意义。Pandas处理时间序列的能力,说实话,是我见过所有Python库里最强的。
我个人最常用的是pd.to_datetime()和pd.date_range()。前者把字符串转成时间对象,后者批量生成时间序列。
# 把字符串索引转成时间索引
df.index = pd.to_datetime(df.index)
print(df.index)
# 输出:DatetimeIndex(['2024-01-02', '2024-01-03', '2024-01-04', '2024-01-05', '2024-01-08'], dtype='datetime64[ns]', freq=None)
# 批量生成交易日序列(跳过周末)
trade_dates = pd.date_range(start='2024-01-02', end='2024-01-31', freq='B') # 'B'代表工作日
print(trade_dates[:10])
嗯,这里要注意:freq='B'只跳过周六周日,不处理法定节假日。如果你做A股回测,得用pd.offsets.CustomBusinessDay配合节假日日历。我曾经因为这个疏忽,回测结果差了3个点,找bug找了一整天。
pd.offsets.CustomBusinessDay(calendar=ChinaCalendar)才搞定。A股交易日历一定要自己维护一份。
3.3 数据读取与写入:CSV和Excel
实际工作中,数据来源五花八门。最常见的就是CSV和Excel。Pandas的read_csv和read_excel功能强大,但参数多到让人眼花。我挑几个最常用的说说。
先看CSV读取。我处理过的金融数据CSV,十有八九第一列是日期。
# 读取CSV文件,指定日期列为索引
df = pd.read_csv('stock_data.csv',
index_col=0, # 第一列作为索引
parse_dates=True, # 自动解析日期
encoding='utf-8') # 防止中文乱码
print(df.head())
Excel读取也类似,但要注意sheet名。
# 读取Excel文件
df = pd.read_excel('stock_data.xlsx',
sheet_name='Sheet1',
index_col=0,
parse_dates=True)
写入数据时,我习惯把时间索引先转成字符串再存,这样其他软件打开时不会乱。
# 写入CSV
df.to_csv('cleaned_data.csv', encoding='utf-8-sig') # utf-8-sig防止Excel打开乱码
# 写入Excel
df.to_excel('cleaned_data.xlsx', sheet_name='cleaned')
encoding='utf-8-sig',这样Excel打开中文不会乱码。我刚开始用utf-8,发给同事后他说全是乱码,尴尬得很。
3.4 数据清洗与缺失值处理:脏活累活我来干
真实世界的金融数据,没有一份是干净的。缺失值、异常值、重复值,应有尽有。数据清洗占掉我80%的时间,这话一点不夸张。
先看缺失值。Pandas里用NaN表示缺失。处理方式就三种:删除、填充、插值。
# 检查缺失值
print(df.isnull().sum()) # 每列缺失值数量
# 方法一:删除缺失值
df_drop = df.dropna() # 删除任何包含NaN的行
df_drop_col = df.dropna(axis=1) # 删除任何包含NaN的列
# 方法二:填充缺失值
df_fill = df.fillna(method='ffill') # 用前一个值填充(前向填充)
df_fill_bfill = df.fillna(method='bfill') # 用后一个值填充(后向填充)
# 方法三:插值(更平滑)
df_interp = df.interpolate(method='linear') # 线性插值
你想想看,股票停牌时,那几天的数据全是NaN。直接删掉?不行,会破坏时间序列的连续性。我一般用前向填充,因为停牌期间价格不变,用前一个交易日的数据最合理。
但如果是分钟数据,某个时刻缺失了,线性插值可能更合适。这得看具体情况。
dropna(),结果把停牌日全删了。回测曲线漂亮得很,实盘一跑就崩。后来才发现,停牌日的数据不能删,得用前向填充。记住:金融数据的时间连续性比数据完整性更重要。
除了缺失值,重复值也得处理。有时候数据源会重复推送同一时刻的数据。
# 检查重复值
print(df.duplicated().sum())
# 删除重复值(保留第一个)
df_unique = df.drop_duplicates(keep='first')
异常值处理更考验经验。我一般用Z-score或者IQR方法。
# 用Z-score检测异常值(假设数据服从正态分布)
from scipy import stats
z_scores = np.abs(stats.zscore(df['close']))
df_no_outlier = df[(z_scores < 3)] # 保留Z-score小于3的数据
# 用IQR方法(更稳健)
Q1 = df['close'].quantile(0.25)
Q3 = df['close'].quantile(0.75)
IQR = Q3 - Q1
df_no_outlier_iqr = df[(df['close'] >= Q1 - 1.5*IQR) & (df['close'] <= Q3 + 1.5*IQR)]
我个人更偏爱IQR方法,因为它不受极端值影响。Z-score对极端值太敏感,有时候会把正常波动误判为异常。
3.5 本章知识体系总览
下面这张图,把本章的核心知识点串起来了。你可以把它当作一个速查地图,以后遇到数据处理问题,先看这张图找思路。
这一章的内容,说白了就是让你学会跟数据“对话”。你掌握了Series和DataFrame,就等于有了工具箱;学会了时间索引,就等于有了指南针;会读写数据,就等于有了原材料;能清洗数据,就等于有了打磨工具。四者缺一不可。
我见过太多人,模型写得花里胡哨,结果数据预处理一塌糊涂。记住:垃圾进,垃圾出。金融时序预测,数据质量永远是第一位的。
- Series是一维带标签数组,DataFrame是二维表格,金融数据首选DataFrame
- 时间索引用
pd.to_datetime()和pd.date_range()创建,注意节假日处理 - CSV读写用
read_csv/to_csv,Excel用read_excel/to_excel,编码用utf-8-sig - 缺失值处理:金融数据优先用前向填充(ffill),保持时间连续性
- 异常值检测:IQR方法比Z-score更稳健,适合金融数据