67 lines
1.2 KiB
Python
67 lines
1.2 KiB
Python
import QuantLib as ql
|
|
|
|
|
|
def build_calibrated_hw(
|
|
curve_handle,
|
|
swaption_helpers,
|
|
a_init=0.05,
|
|
sigma_init=0.01
|
|
):
|
|
hw = ql.HullWhite(curve_handle, a_init, sigma_init)
|
|
|
|
optimizer = ql.LevenbergMarquardt()
|
|
end_criteria = ql.EndCriteria(1000, 500, 1e-8, 1e-8, 1e-8)
|
|
|
|
hw.calibrate(swaption_helpers, optimizer, end_criteria)
|
|
|
|
return hw
|
|
|
|
import numpy as np
|
|
|
|
|
|
def simulate_hw_state(
|
|
hw: ql.HullWhite,
|
|
curve_handle,
|
|
time_grid,
|
|
n_paths,
|
|
seed=42
|
|
):
|
|
a, sigma = hw.params()
|
|
|
|
dt = np.diff(time_grid)
|
|
n_steps = len(time_grid)
|
|
|
|
np.random.seed(seed)
|
|
x = np.zeros((n_paths, n_steps))
|
|
|
|
for i in range(1, n_steps):
|
|
decay = np.exp(-a * dt[i-1])
|
|
vol = sigma * np.sqrt((1 - np.exp(-2 * a * dt[i-1])) / (2 * a))
|
|
z = np.random.normal(size=n_paths)
|
|
|
|
x[:, i] = x[:, i-1] * decay + vol * z
|
|
|
|
return x
|
|
|
|
|
|
def swap_npv_from_state(
|
|
swap,
|
|
hw,
|
|
curve_handle,
|
|
t,
|
|
x_t,
|
|
today
|
|
):
|
|
ql.Settings.instance().evaluationDate = today + int(t * 365)
|
|
|
|
hw.setState(x_t)
|
|
|
|
engine = ql.DiscountingSwapEngine(
|
|
curve_handle,
|
|
False,
|
|
hw
|
|
)
|
|
|
|
swap.setPricingEngine(engine)
|
|
return swap.NPV()
|