飓风图代码
import numpy as npimport matplotlib.pyplot as plt
# ============================================================
# 1. 蒙特卡洛模拟函数(备用)
# ============================================================
def monte_carlo_simulation(S0, mu, sigma, T, n_sim=1000, n_steps=252):
"""
几何布朗运动路径模拟。
返回形状 (n_sim, n_steps+1) 的价格矩阵。
"""
dt = T / n_steps
drift = (mu - 0.5 * sigma**2) * dt
vol = sigma * np.sqrt(dt)
Z = np.random.standard_normal((n_sim, n_steps))
log_returns = drift + vol * Z
log_cumsum = np.cumsum(log_returns, axis=1)
paths = np.zeros((n_sim, n_steps + 1))
paths[:, 0] = S0
paths[:, 1:] = S0 * np.exp(log_cumsum)
return paths
# ============================================================
# 2. 目标函数(可替换为任何标量输出)
# ============================================================
def gbm_expected_final_price(params: dict) -> float:
"""
解析计算 GBM 期末价格的数学期望:E = S0 * exp(mu * T)
参数:
params (dict): 包含 'S0', 'mu', 'sigma', 'T' 键的字典。
返回:
float: 期望期末价格。
"""
return params['S0'] * np.exp(params['mu'] * params['T'])
# ---------- 如需模拟版本,取消下面注释即可 ----------
# def gbm_mean_simulation(params: dict, n_sim=2000, n_steps=252) -> float:
# paths = monte_carlo_simulation(params['S0'], params['mu'], params['sigma'],
# params['T'], n_sim, n_steps)
# return paths[:, -1].mean()
# ============================================================
# 3. 飓风图绘制函数
# ============================================================
def plot_tornado(
base_params: dict,
param_ranges: dict,
target_func,
target_label: str = 'Expected Final Price',
figsize=None
):
"""
绘制飓风图,展示各参数独立变化时目标函数相对于基准的变化幅度。
参数:
base_params : dict
基准参数值,如 {'S0':100, 'mu':0.05, 'sigma':0.2, 'T':1.0}
param_ranges : dict
参数变化比例范围,值为 (低值比例, 高值比例)。
例如 {'S0': (-0.1, 0.1)} 表示 S0 在基准的 ±10% 之间变动。
target_func : callable
接收参数字典,返回标量数值。
target_label : str
目标函数的名称,用于轴标签。
figsize : tuple, optional
图形大小,默认自适应。
返回:
fig, ax : matplotlib 对象。
"""
# 计算基准情景输出
base_val = target_func(base_params)
# 收集每个参数的低/高输出变化量
data = []
for param, (low_pct, high_pct) in param_ranges.items():
# 低情景
low_params = base_params.copy()
low_params = base_params * (1 + low_pct)
low_val = target_func(low_params)
low_delta = low_val - base_val
# 高情景
high_params = base_params.copy()
high_params = base_params * (1 + high_pct)
high_val = target_func(high_params)
high_delta = high_val - base_val
data.append((param, low_delta, high_delta))
# 按最大影响宽度排序(降序)
data.sort(key=lambda x: max(abs(x), abs(x)), reverse=True)
# 绘图
if figsize is None:
figsize = (max(8, len(data)*1.5), max(4, len(data)*0.5))
fig, ax = plt.subplots(figsize=figsize)
y_idx = np.arange(len(data))
for i, (param, low_d, high_d) in enumerate(data):
ax.barh(i, high_d - low_d, left=low_d, height=0.5,
color='steelblue', alpha=0.8, edgecolor='black')
# 基准线
ax.axvline(x=0, color='black', linewidth=1)
ax.set_yticks(y_idx)
ax.set_yticklabels( for d in data])
ax.set_xlabel(f'Change in {target_label}')
ax.set_title(f'Sensitivity Tornado Chart\nBase value: {base_val:.2f}')
ax.grid(axis='x', linestyle=':', alpha=0.6)
ax.invert_yaxis()# 最宽的放在最上面
fig.tight_layout()
return fig, ax
# ============================================================
# 4. 主程序:示例运行
# ============================================================
if __name__ == '__main__':
# 基准参数
base = {
'S0': 100.0, # 初始价格
'mu': 0.05, # 预期收益率 5%
'sigma': 0.2, # 波动率 20%
'T': 1.0 # 期限 1 年
}
# 各参数的变化范围(相对于基准的比例)
ranges = {
'S0': (-0.10, 0.10), # S0 在 90 ~ 110
'mu': (-0.50, 0.50), # mu 在 2.5% ~ 7.5% (相对变化 ±50%)
'sigma': (-0.20, 0.20), # sigma 在 0.16 ~ 0.24
'T': (-0.20, 0.20), # T 在 0.8 ~ 1.2 年
}
# 绘制飓风图(使用快速解析期望)
# 若需要基于模拟的期末价格均值,将 target_func 换为 gbm_mean_simulation 即可
fig, ax = plot_tornado(base, ranges, gbm_expected_final_price,
target_label='Expected Final Price')
plt.show()
页:
[1]