第二章 Python金融数据分析基础
说实话,很多做量化的人一上来就搞策略、跑回测,结果数据都拿不对,分析也漏洞百出。我见过太多这样的案例了。这一章,咱们就把地基打牢——NumPy、Pandas、Matplotlib,再加上数据获取的实战。这些东西,我几乎每天都在用。
核心要点:金融数据分析的四大支柱——数值计算(NumPy)、表格处理(Pandas)、可视化(Matplotlib)、数据源(Tushare/AkShare)。缺一个,你的量化体系就不完整。
2.1 NumPy基础:量化计算的发动机
NumPy,说白了就是Python里的数学引擎。做量化,你免不了要算收益率、波动率、协方差矩阵,这些全得靠它。
为什么不用Python原生列表? 速度差太多了。我做过测试,同样计算100万条数据的均值,NumPy比原生列表快了将近50倍。你想想看,回测时数据量一上来,这个差距就是天壤之别。
2.1.1 创建数组
import numpy as np
# 从列表创建
prices = np.array([100.5, 101.2, 102.8, 103.1])
print(prices) # [100.5 101.2 102.8 103.1]
# 创建全0数组(比如初始化仓位)
positions = np.zeros(5)
print(positions) # [0. 0. 0. 0. 0.]
# 创建等差数列(比如模拟时间轴)
time_axis = np.linspace(0, 1, 10) # 从0到1,均匀取10个点
print(time_axis)
我的习惯:初始化仓位或资金曲线时,我几乎只用 np.zeros 或 np.full。别用列表推导式,那玩意儿在数据量大时慢得让人抓狂。
2.1.2 向量化运算
这是NumPy最牛的地方。不用写循环,直接对整个数组做运算。
# 计算日收益率
close_prices = np.array([100, 102, 101, 105, 107])
daily_returns = (close_prices[1:] - close_prices[:-1]) / close_prices[:-1]
print(daily_returns) # [0.02 -0.0098 0.0396 0.019 ]
# 计算年化波动率(假设252个交易日)
volatility = np.std(daily_returns) * np.sqrt(252)
print(f"年化波动率: {volatility:.4f}")
你看,三行代码就把收益率和波动率算出来了。要是用循环写,至少得七八行,还容易出错。
2.1.3 常用统计函数
| 函数 | 用途 | 量化场景 |
|---|---|---|
np.mean() |
均值 | 计算平均收益率 |
np.std() |
标准差 | 计算波动率 |
np.corrcoef() |
相关系数 | 分析资产相关性 |
np.percentile() |
百分位数 | 计算VaR(风险价值) |
我曾经踩过的坑:用 np.std() 时,默认是除以 n 而不是 n-1。做样本统计时,记得加上 ddof=1,否则算出来的波动率会偏小。这个错误我犯过一次,回测结果漂亮得不像话,实盘直接打脸。
2.2 Pandas基础:金融数据的瑞士军刀
Pandas,说白了就是Python里的Excel,但比Excel强一百倍。做量化,你80%的时间都在跟DataFrame打交道。
2.2.1 DataFrame与Series
import pandas as pd
# 创建DataFrame(模拟股票数据)
data = {
'日期': ['2024-01-02', '2024-01-03', '2024-01-04'],
'开盘': [100.5, 102.0, 101.5],
'收盘': [102.0, 101.5, 104.0],
'成交量': [10000, 12000, 9500]
}
df = pd.DataFrame(data)
print(df)
我个人习惯:日期列一定要转成 datetime 类型,不然做时间切片时会哭的。
df['日期'] = pd.to_datetime(df['日期'])
df = df.set_index('日期') # 把日期设为索引
print(df.loc['2024-01-03']) # 直接按日期取数据
2.2.2 金融数据常用操作
做量化,这几个操作你必须烂熟于心:
- 数据筛选:
df[df['收盘'] > 102]—— 找出收盘价大于102的交易日 - 缺失值处理:
df.fillna(method='ffill')—— 用前值填充,金融数据常用 - 滚动计算:
df['收盘'].rolling(window=5).mean()—— 5日均线 - 合并数据:
pd.merge(df1, df2, on='日期')—— 合并多只股票数据
# 实战:计算5日均线和20日均线
df['MA5'] = df['收盘'].rolling(window=5).mean()
df['MA20'] = df['收盘'].rolling(window=20).mean()
# 生成交易信号:金叉买入,死叉卖出
df['信号'] = 0
df.loc[df['MA5'] > df['MA20'], '信号'] = 1
df.loc[df['MA5'] < df['MA20'], '信号'] = -1
避坑指南:用 rolling() 时,前几个值会是NaN。我刚开始做策略时没注意这个,结果回测信号全是乱的。记得用 dropna() 清理一下。
2.3 Matplotlib基础:把数据画出来
做量化,光看数字不行,得画图。一张好的K线图,比一堆数字直观得多。
2.3.1 快速画图
import matplotlib.pyplot as plt
# 画收盘价曲线
plt.figure(figsize=(10, 6))
plt.plot(df.index, df['收盘'], label='收盘价', color='blue')
plt.plot(df.index, df['MA5'], label='5日均线', color='red', linestyle='--')
plt.title('股价走势图')
plt.xlabel('日期')
plt.ylabel('价格')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
2.3.2 金融专用图表
我个人最常用的是双轴图——上面画价格,下面画成交量或指标。
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8), sharex=True)
# 上轴:价格
ax1.plot(df.index, df['收盘'], color='black')
ax1.set_ylabel('价格')
ax1.grid(True, alpha=0.3)
# 下轴:成交量
ax2.bar(df.index, df['成交量'], color='gray', alpha=0.6)
ax2.set_ylabel('成交量')
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
注意:Matplotlib默认显示中文会乱码。我一般加这两行代码解决:
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
2.4 金融数据获取:Tushare与AkShare
数据是量化分析的基础。没有数据,再牛的策略也是空中楼阁。
2.4.1 Tushare Pro
Tushare是老牌的数据接口,数据质量高,但需要注册获取token。
import tushare as ts
# 设置token(需要去官网注册)
ts.set_token('你的token')
pro = ts.pro_api()
# 获取股票日线数据
df = pro.daily(ts_code='000001.SZ', start_date='20240101', end_date='20240131')
print(df.head())
2.4.2 AkShare
AkShare是后起之秀,完全免费,数据源覆盖广。我个人现在更常用它。
import akshare as ak
# 获取A股日线数据
df = ak.stock_zh_a_hist(symbol="000001", period="daily",
start_date="20240101", end_date="20240131")
print(df.head())
| 对比项 | Tushare | AkShare |
|---|---|---|
| 费用 | 部分免费,高级功能付费 | 完全免费 |
| 数据质量 | 高,经过清洗 | 较高,偶尔有异常值 |
| 数据范围 | A股、基金、期货等 | A股、港股、美股、期货、外汇等 |
| 上手难度 | 需要注册token | 直接pip安装即可 |
我的建议:初学者先用AkShare,零门槛。等做正式策略了,再考虑Tushare的数据质量优势。两个都装上也不冲突。
本章知识体系
下面这张图,是我梳理的本章核心逻辑。你看一眼,心里就有谱了。
嗯,这一章的内容就到这里。工具是死的,但用法是活的。我建议你打开Jupyter Notebook,把上面的代码挨个跑一遍。光看是学不会的,得动手。