
Using the Hull-White model to find the 2026 value in the US bond plot
So, for ease and formatting, I made a quant stackexchange post here but I believe that I was incorrect here?
I wanted to output specifically the 2026 value of $\sim5.01\%$ for 2026, as seen in the above plot?
I believe that I have an error with SDE used $r = 4.65, \theta = 4.2$, and $\sigma = 0.55$, apparently in percentage points. That's internally possible, but then the reported standard deviation calculation is wrong in its interpretation:
$$\sqrt{\frac{(0.55)^2}{2(0.35)}}\approx 0.657$$
meaning $0.657$ percentage points if rates are measured in percentage points?
Also, the Hull–White equation that I derived isn't actually the standard Hull–White specification we're subsequently describing, as derivation starts from
$$dr_t=\kappa(\theta−r_t)dt+\sigma dW_t,$$
where $\theta$ is constant. That's essentially the Vasicek model, but the standard one-factor Hull–White is
$$dr_t=[\theta(t)−ar_t]dt+\sigma dW_t,$$
with a time-dependent drift chosen to fit today's initial yield curve?
My code:
import numpy as np
# Let's run a simulation for CIR (Cox-Ingersoll-Ross) and Hull-White models
np.newaxis
np.random.seed(42)
N = 216 # Monthly steps from 2008 to 2026
dt = 1 / 12
# 1. CIR Model simulation: dr = theta * (mu - r_t)dt + sigma * sqrt(r_t) * dW_t
theta_cir = 0.4
mu_cir = 3.3
sigma_cir = 0.35 # Must satisfy Feller condition: 2 * theta * mu >= sigma^2 to stay positive
r_cir = np.zeros(N)
r_cir[0] = 4.65
for i in range(1, N):
# Ensure non-negative inside sqrt
r_prev = max(0.0, r_cir[i-1])
dr = theta_cir * (mu_cir - r_prev) * dt + sigma_cir * np.sqrt(r_prev) * np.sqrt(dt) * np.random.randn()
r_cir[i] = r_prev + dr
# 2. Hull-White Model (Time-varying mean theta(t) or drift to fit term structure)
# Simplest time-varying mean formulation: theta(t) matches a shifting trend
theta_hw = 0.35
sigma_hw = 0.55
r_hw = np.zeros(N)
r_hw[0] = 4.65
for i in range(1, N):
t_val = 2008 + i * dt
# Let the long-term mean drift higher post-2021 to capture the inflation regime shift
mu_t = 3.0 if t_val < 2021 else 4.2
dr = theta_hw * (mu_t - r_hw[i-1]) * dt + sigma_hw * np.sqrt(dt) * np.random.randn()
r_hw[i] = r_hw[i-1] + dr
print(f"CIR Model 2026 Terminal Value: {r_cir[-1]:.2f}%")
print(f"Hull-White (Regime-Shift) 2026 Terminal Value: {r_hw[-1]:.2f}%")
##CIR Model 2026 Terminal Value: 4.71%
##Hull-White (Regime-Shift) 2026 Terminal Value: 5.01%
Thanks! ❤️