我从其他贡献者那里得到了一些使用 numpy 进行蒙特卡罗(随机游走)的优雅代码。然而,目前“vol”(又称标准差)是提供的常数。理想情况下,它应该随着时间的推移而变化。有没有办法修改此代码以使“vol”成为 numpy 索引的函数?我可以使用 for 循环来完成此操作,但出于性能原因,我试图将其保持矢量化。
import numpy as np
def montecarlo_brownian(start_value, T_years, steps, vol, rate = 0, sims = 1000):
""" generate random walks from a starting value for Monte Carlo analysis
Args:
start_value (float): starting value for random walks
T_year (float): number of years in question
steps (int): substeps within each year
vol (float): annualized standard deviation (ie, implied volatility)
rate (float): risk free interest rate
sims (int): number of simulations to execute
Returns:
(np.array) columns of random walks
"""
times = np.linspace(0, T_years, steps+1)
dt = times[1] - times[0]
B = np.random.normal(0, np.sqrt(dt), size=(sims, steps)).T
S = np.exp((rate - vol ** 2/ 2) * dt + vol * B)
S = start_value * S.cumprod(axis=0)
return S
评论者 jared 要求提供 for 循环逻辑的示例。我会定义一个函数
def get_vol(t):
pass
#some function that calculates vol based on how much time is left
然后使用类似的东西:
def monte_carlo_with_changing_vol(S0, r, T, num_sims, num_steps, volatility):
dt = T / num_steps
paths = np.zeros((num_sims, num_steps + 1))
paths[:, 0] = S0
for i in range(num_sims):
for j in range(1, num_steps + 1):
current_vol = vol(j)
paths[i, j] = paths[i, j - 1] * np.exp((r - 0.5 * current_vol ** 2) * dt + current_vol * np.sqrt(dt) * np.random.normal(0, 1))
return paths
@jared 的评论修复了这个问题,用 vol[:,None] 替换 vol 并将 vol 作为适当大小的数组传递