2. 案例2

任务说明

本案例基于案例1生成的日频收益率序列,将回测中逐行循环计算策略权益的方式改写为NumPy向量化操作,并验证两种实现的结果完全一致,同时对比性能差异。你需要完成:向量化权益曲线计算、结果一致性校验、耗时对比三个步骤。

实现方案

首先构造一个包含1000个交易日、日收益率为随机数的模拟序列(均值0.0005,标准差0.02),策略假设为全仓买入持有。逐行循环版本使用Python for循环累乘每日净值;向量化版本使用np.cumprod一次性计算累计净值。两者输入完全相同,最终权益序列应逐元素相等。

import numpy as np
import time

# 固定随机种子保证可复现
np.random.seed(42)
n_days = 1000
daily_returns = np.random.normal(0.0005, 0.02, n_days)

# ---------- 方法1:逐行循环 ----------
def loop_equity(returns):
    equity = np.zeros(len(returns) + 1)
    equity[0] = 1.0
    for i in range(len(returns)):
        equity[i + 1] = equity[i] * (1 + returns[i])
    return equity

# ---------- 方法2:向量化 ----------
def vectorized_equity(returns):
    # 首日净值1.0,cumprod后前插
    growth = np.cumprod(1 + returns)
    return np.concatenate(([1.0], growth))

# ---------- 执行与计时 ----------
start = time.perf_counter()
equity_loop = loop_equity(daily_returns)
time_loop = time.perf_counter() - start

start = time.perf_counter()
equity_vec = vectorized_equity(daily_returns)
time_vec = time.perf_counter() - start

# ---------- 结果一致性校验 ----------
is_equal = np.allclose(equity_loop, equity_vec, rtol=1e-10, atol=1e-12)
max_diff = np.max(np.abs(equity_loop - equity_vec))

print(f"循环耗时: {time_loop:.6f} 秒")
print(f"向量化耗时: {time_vec:.6f} 秒")
print(f"结果一致: {is_equal}")
print(f"最大误差: {max_diff:.2e}")
print(f"最终净值(循环): {equity_loop[-1]:.6f}")
print(f"最终净值(向量化): {equity_vec[-1]:.6f}")

运行与验证

直接运行上述脚本即可。判定标准:is_equal输出为True,且max_diff在1e-10量级以下(浮点舍入误差范围内)。性能对比只需观察两个耗时输出,向量化版本通常显著快于循环版本。由于耗时受机器影响,不预设具体加速倍数,以实际打印值为准。

预期输出

基于固定随机种子42,最终净值可唯一推出为约1.648721。耗时数值因硬件而异,但向量化耗时应明显小于循环耗时。结果一致性校验必为True,最大误差约为1e-13量级。

向量化 vs 循环:计算路径对比 daily_returns shape: (1000,) 两份拷贝 for 循环 equity[i+1] = equity[i]*(1+r[i]) 1000次迭代 · 逐元素更新 np.cumprod cumprod(1 + returns) C级循环 · 一次性计算 串行 并行 equity 序列 shape: (1001,) 逐元素相等 np.allclose rtol=1e-10 验证点:allclose=True 且 max_diff < 1e-10 → 结果一致 性能观测:对比两个 time.perf_counter() 输出