3. Python 金融数据处理基础

高频策略的成败,90% 取决于数据质量。本章将系统讲解 Pandas 在金融时间序列中的核心操作,包括数据加载、清洗、重采样以及通过 API 获取实时行情。掌握这些技能后,你就能为任何策略搭建可靠的数据管道。

3.1 Pandas 核心数据结构与金融数据加载

Pandas 的两大核心对象是 Series(一维序列)和 DataFrame(二维表)。金融数据通常以 OHLCV(开盘、最高、最低、收盘、成交量)格式存储,最适合用 DataFrame 表示。

对象 维度 金融应用场景
Series 1D 单只股票的收盘价序列、收益率序列
DataFrame 2D 多只股票的 OHLCV 表、因子矩阵、订单簿快照

从 CSV 加载历史数据的标准写法:

import pandas as pd

# 加载日线数据,指定日期列为索引
df = pd.read_csv('AAPL_daily.csv', parse_dates=['Date'], index_col='Date')
print(df.head())
💡 最佳实践: 始终将时间列设为 DatetimeIndex,这是后续重采样、滑动窗口、时间对齐的前提。使用 parse_dates=True 可自动识别常见日期格式。

3.2 时间序列数据处理

金融时间序列具有高频、非均匀间隔、多层级(tick/分钟/日/月)的特点。Pandas 提供了强大的时间索引操作。

3.2.1 索引与切片

# 按年份切片
df_2023 = df['2023']

# 按月份范围切片
df_jan_feb = df['2024-01':'2024-02']

# 按具体日期精确取值
df_specific = df.loc['2024-03-15']

3.2.2 滚动窗口与滞后

高频策略中,移动平均、滚动波动率、滞后因子是基础算子。

# 20 日滚动均值
df['SMA_20'] = df['Close'].rolling(window=20).mean()

# 5 日滚动标准差(波动率)
df['Volatility_5'] = df['Close'].rolling(window=5).std()

# 滞后 1 期(前一交易日收盘价)
df['Close_Lag1'] = df['Close'].shift(1)
时间序列滚动窗口计算流程 原始收盘价 rolling(20) SMA_20 关键参数说明: • window=20:窗口大小(交易日数) • min_periods:最少有效观测数(默认=window) • center=False:输出对齐到窗口右边界(高频策略常用)

3.3 数据清洗与重采样

真实金融数据常包含缺失值、异常跳空、非交易时段噪音。清洗是策略稳健性的第一道防线。

3.3.1 缺失值处理

方法 适用场景 代码示例
前向填充 非交易时段(周末、节假日) df.fillna(method='ffill')
线性插值 日内 tick 数据短时缺失 df.interpolate(method='linear')
丢弃 缺失比例极低(<1%) df.dropna()

3.3.2 重采样:将高频数据降频

高频策略常需将 tick 数据聚合为分钟线,或将分钟线聚合为日线。

# 将 1 分钟数据重采样为 5 分钟 OHLCV
df_5min = df.resample('5T').agg({
    'Open': 'first',
    'High': 'max',
    'Low': 'min',
    'Close': 'last',
    'Volume': 'sum'
})

# 将日线重采样为周线
df_weekly = df.resample('W').agg({
    'Open': 'first',
    'High': 'max',
    'Low': 'min',
    'Close': 'last',
    'Volume': 'sum'
})
⚠️ 重采样陷阱: 使用 resample('W') 默认以周日为周边界。美股市场应使用 resample('W-FRI') 对齐实际交易周。始终检查重采样后的索引是否包含非交易日。

3.4 金融数据 API 调用(Yahoo Finance)

使用 yfinance 库可以零成本获取全球股票、ETF、指数的历史行情。这是策略回测和实时监控的常用数据源。

3.4.1 安装与基础调用

# 安装:pip install yfinance
import yfinance as yf

# 下载单只股票日线数据
aapl = yf.download('AAPL', start='2023-01-01', end='2024-12-31')
print(aapl.head())

3.4.2 批量下载与多级列索引

# 同时下载多只股票
tickers = ['AAPL', 'MSFT', 'GOOGL']
data = yf.download(tickers, start='2024-01-01', end='2024-06-30')

# 此时 data 为多级列索引:(Open, AAPL), (Open, MSFT), ...
# 提取所有股票的收盘价
close_prices = data['Close']
print(close_prices.head())

3.4.3 实时行情与历史分笔

# 获取当前最新行情(延迟约 15 分钟)
ticker = yf.Ticker('AAPL')
info = ticker.info
print(f"当前价格: {info['currentPrice']}")

# 获取历史分笔数据(最近 7 天)
hist = ticker.history(period='7d', interval='1m')
print(hist.tail())
Yahoo Finance 数据管道架构 Yahoo Finance API yfinance 库 Pandas DataFrame 返回数据结构: • 单只股票:单级列索引 [Open, High, Low, Close, Volume] • 多只股票:多级列索引 (指标, 股票代码) • 索引始终为 DatetimeIndex(时区已对齐)

3.5 综合实战:构建分钟级数据管道

将以上知识点串联,构建一个从 API 获取 → 清洗 → 重采样 → 存储的完整流程。

import yfinance as yf
import pandas as pd

# 1. 获取原始分钟数据
raw = yf.download('AAPL', period='5d', interval='1m')

# 2. 清洗:前向填充缺失值
clean = raw.fillna(method='ffill')

# 3. 重采样为 5 分钟 OHLCV
resampled = clean.resample('5T').agg({
    'Open': 'first',
    'High': 'max',
    'Low': 'min',
    'Close': 'last',
    'Volume': 'sum'
})

# 4. 添加技术指标
resampled['SMA_5'] = resampled['Close'].rolling(5).mean()
resampled['Return'] = resampled['Close'].pct_change()

# 5. 保存到本地
resampled.to_parquet('AAPL_5min.parquet')
print("数据管道执行完成,共 %d 条记录" % len(resampled))
📌 高频策略数据规范:
  • 始终使用 UTC 时间存储,避免时区转换错误
  • 分钟数据至少保留 30 天用于滚动统计量计算
  • 使用 to_parquet() 替代 CSV,压缩率高且读写快 5-10 倍
  • 每次重采样后检查 isna().sum(),确保无意外缺失