4、Python基础回顾:NumPy与Pandas在量化中的应用

说实话,很多刚入行的朋友问我:「学量化交易,Python要学到什么程度?」我的回答很简单——你不需要成为Python专家,但NumPy和Pandas这两把刀,你必须磨利了

为什么?因为量化交易的本质就是处理数据、计算指标、回测策略。而这两件事,恰好是NumPy和Pandas的看家本领。我自己做策略开发这些年,90%的代码时间都在跟这两个库打交道。

核心认知:NumPy负责「算得快」,Pandas负责「管得好」。两者配合,你就能高效处理金融时间序列数据。
量化交易Python核心库 NumPy 高性能数值计算 Pandas 数据清洗与分析 数组运算 数学函数 随机数生成 线性代数 DataFrame 时间序列 数据合并 滚动窗口 应用:策略回测 · 因子计算 · 风险分析

4.1 NumPy:量化计算的「发动机」

NumPy的核心是ndarray,也就是N维数组。你想想看,股票数据是什么?本质上就是一堆数字排成行和列。用Python原生的列表去算,慢得你想哭。用NumPy,同样的运算快几十倍。

我的经验:刚开始做量化时,我用纯Python写了一个移动平均线计算,回测10年的数据跑了快3分钟。换成NumPy后,0.3秒搞定。嗯,这就是差距。

4.1.1 创建数组

import numpy as np

# 从列表创建
prices = np.array([100.5, 101.2, 102.8, 103.1, 102.5])

# 创建全0数组(比如初始化仓位记录)
zeros = np.zeros((5, 3))  # 5行3列

# 创建等差数列(比如模拟时间轴)
time_axis = np.linspace(0, 1, 100)  # 从0到1,均匀取100个点

# 随机数(蒙特卡洛模拟常用)
np.random.seed(42)  # 固定随机种子,保证可复现
random_returns = np.random.randn(1000)  # 生成1000个正态分布随机数

4.1.2 向量化运算

这是NumPy最爽的地方。不用写循环,直接对整个数组做运算。

# 假设这是某股票5天的收盘价
close = np.array([100, 102, 101, 105, 107])

# 计算每日收益率(向量化,一行搞定)
returns = np.diff(close) / close[:-1]
# 结果:array([0.02, -0.0098, 0.0396, 0.019])

# 计算累计收益率
cum_return = np.cumprod(1 + returns) - 1

# 统计指标
mean_return = np.mean(returns)
std_return = np.std(returns)
max_drawdown = np.min(returns)  # 简化版最大回撤
避坑指南:我曾经在计算夏普比率时,直接用np.std()算收益率标准差,结果怎么算都不对。后来才发现——np.std()默认是总体标准差,而金融数据通常用样本标准差。记得加参数ddof=1

4.2 Pandas:量化数据的「瑞士军刀」

如果说NumPy是发动机,那Pandas就是整辆车。它让你能轻松地加载、清洗、分析、可视化金融数据。

4.2.1 DataFrame基础操作

import pandas as pd

# 创建DataFrame(模拟股票数据)
data = {
    '日期': ['2024-01-02', '2024-01-03', '2024-01-04'],
    '开盘': [100.5, 101.2, 102.0],
    '收盘': [101.8, 102.5, 101.3],
    '成交量': [10000, 12000, 9500]
}
df = pd.DataFrame(data)

# 查看数据
print(df.head())      # 前5行
print(df.info())      # 数据类型、缺失值
print(df.describe())  # 统计摘要

4.2.2 时间序列处理

量化交易里,时间就是一切。Pandas的时间序列功能,我用得最多。

# 把日期列设为索引
df['日期'] = pd.to_datetime(df['日期'])
df.set_index('日期', inplace=True)

# 重采样(比如把日线转周线)
weekly = df.resample('W').agg({
    '开盘': 'first',
    '收盘': 'last',
    '成交量': 'sum'
})

# 滚动窗口计算(移动平均线)
df['MA5'] = df['收盘'].rolling(window=5).mean()
df['MA20'] = df['收盘'].rolling(window=20).mean()

# 移位操作(计算前一天的收盘价)
df['前日收盘'] = df['收盘'].shift(1)
个人习惯:我每次拿到新数据,第一件事就是df.isnull().sum()检查缺失值。金融数据经常有停牌、节假日导致的数据缺失,不处理直接跑策略,结果会骗人的。

4.2.3 数据合并与连接

做多因子策略时,经常需要合并不同来源的数据。

# 假设有两个DataFrame
df_stock_a = pd.DataFrame({'收盘': [100, 102]}, index=['2024-01-02', '2024-01-03'])
df_stock_b = pd.DataFrame({'收盘': [50, 51]}, index=['2024-01-02', '2024-01-03'])

# 横向合并(类似Excel的VLOOKUP)
portfolio = pd.concat([df_stock_a, df_stock_b], axis=1, keys=['股票A', '股票B'])

# 按日期合并(处理不同频率的数据)
df_merged = pd.merge(df_daily, df_monthly, left_index=True, right_index=True, how='left')

4.3 实战:计算一个简单的均线策略信号

光说不练假把式。咱们用真实数据走一遍。

import numpy as np
import pandas as pd

# 模拟100天的股价数据(随机游走)
np.random.seed(42)
days = 100
price = 100 * np.cumprod(1 + np.random.randn(days) * 0.01)

# 构建DataFrame
df = pd.DataFrame({
    'close': price,
    'date': pd.date_range('2024-01-01', periods=days)
})
df.set_index('date', inplace=True)

# 计算均线
df['ma5'] = df['close'].rolling(5).mean()
df['ma20'] = df['close'].rolling(20).mean()

# 生成交易信号
df['signal'] = 0
df.loc[df['ma5'] > df['ma20'], 'signal'] = 1   # 金叉,买入
df.loc[df['ma5'] < df['ma20'], 'signal'] = -1  # 死叉,卖出

# 计算策略收益率
df['return'] = df['close'].pct_change()
df['strategy_return'] = df['signal'].shift(1) * df['return']

# 看看结果
print(df[['close', 'ma5', 'ma20', 'signal', 'strategy_return']].head(10))
关键点:注意shift(1)的使用。信号是在当天收盘后生成的,所以实际交易要等到第二天开盘。这个细节,很多新手会忽略,导致回测结果虚高。

4.4 常用量化函数速查表

功能 NumPy实现 Pandas实现
收益率计算 np.diff(prices)/prices[:-1] df['close'].pct_change()
移动平均 需手动实现 df['close'].rolling(20).mean()
标准差 np.std(returns, ddof=1) df['return'].std()
协方差矩阵 np.cov(returns_matrix) df.cov()
相关系数 np.corrcoef(x, y) df.corr()
缺失值处理 np.isnan(arr) df.dropna() / df.fillna()

这张表我建议你收藏。刚开始做策略时,经常要查某个函数怎么写。用多了自然就记住了。

我曾经踩过的坑:pct_change()计算收益率时,如果数据里有0值,会出现inf(无穷大)。比如某天股价为0(除权除息处理不当),收益率就变成无穷大。所以,数据清洗永远要放在第一步

好了,NumPy和Pandas的基础就回顾到这里。说白了,这两个库就是量化交易的「左膀右臂」。你不需要背下所有函数,但一定要理解它们的核心思想:向量化运算数据框操作。后面的章节里,我们会反复用到这些知识。

专注资料整理