跳到正文

NumPy 向量化:编写快 100 倍的量化代码

NumPy 向量化用快速的 C 级数组操作替代 Python 循环。对于量化金融——处理数百万个价格数据点——向量化是代码在秒级 vs 小时级运行的区别。

第 6 篇 · 共 8 篇 约 1 分钟

NumPy 是 Python 数值计算的基础。其核心是 ndarray——多维数组,具有 C 级性能的逐元素操作。对于量化金融——处理数百万价格数据点——NumPy 向量化是必不可少的。

为什么 Python 循环慢

Python 循环是被解释执行的。每个迭代都有 Python 开销。对 100 万元素循环需要秒级。NumPy 操作在 C 中编译并一次对整个数组操作。

# 这个循环:
result = []
for x in a:
    result.append(x * 2 + 1)

# 等价于(但快 50-100 倍):
vectorized = a * 2 + 1

关键原则:数组操作

不要循环遍历元素,而是对整个数组操作:

# 不要这样:
returns = []
for i in range(1, len(prices)):
    returns.append((prices[i] - prices[i-1]) / prices[i-1])

# 这样:
returns = (prices[1:] - prices[:-1]) / prices[:-1]

# 或这样(pandas):
returns = prices.pct_change()

广播:跨不同形状的操作

NumPy 自动将不同形状的数组广播在一起:

# prices: shape (1000, 500) — 1000 天,500 资产
# weights: shape (500,) — 每资产 1 个权重

portfolio_value = prices @ weights  # (1000,) — 每天价格*权重之和

金融特定示例

计算收益矩阵

def compute_returns_matrix(prices):
    """
    prices: DataFrame of shape (n_days, n_assets)
    returns: DataFrame of shape (n_days-1, n_assets)
    """
    return (prices.iloc[1:].values - prices.iloc[:-1].values) / prices.iloc[:-1].values

组合方差

def portfolio_variance(weights, cov_matrix):
    """组合方差: w' * Cov * w"""
    return weights @ cov_matrix @ weights

常见陷阱

形状不匹配。 广播失败时会报难以理解的错误。调试时始终打印 .shape。

大数组的内存。 一个 (10000, 5000) float64 数组是 400 MB。对于大数据集,使用 float32 或分块处理。

参考文献

  • VanderPlas, Python Data Science Handbook, 第 2 章. O’Reilly, 2016. ISBN: 978-1-491-91205-8.
  • Press, Numerical Recipes, 第 2 章. Cambridge, 2007. ISBN: 978-0-521-88068-8.
  • McKinney, Python for Data Analysis, 第 4 章. O’Reilly, 2023. ISBN: 978-1-492-07231-9.