Cox-Ingersoll-Ross (CIR) Process
Table of Contents
Summary
The Cox-Ingersoll-Ross (CIR, 1985) model keeps
Vasicek's mean-reverting
drift shape but replaces its constant volatility with a state-dependent
sigma*sqrt(r) term, which shrinks toward zero as the rate itself
approaches zero and rules out the negative rates
Vasicek and
Hull-White can produce. That
same volatility term is also what breaks the closed-form Gaussian
transition the other two share: a CIR rate's next value follows a
non-central chi-squared distribution, not a Normal one, requiring a
genuinely different simulation technique. ores::analytics::quant::service::cox_ingersoll_ross_process
implements the exact (non-approximated) transition via the standard
Poisson-mixture-of-central-chi-squared construction, not an Euler
discretisation.
Layperson's mental model
Same elastic band as Vasicek, pulling the rate back toward a resting level — but now the jitter added each tick shrinks as the rate gets close to zero, and vanishes entirely exactly at zero. That single change is what keeps the rate from ever crossing into negative territory: right at the boundary, there is no randomness left to push it over, only the band's steady pull back up. The cost is that the maths describing "how big is the next jump" is no longer the plain bell-curve (Normal) distribution Vasicek uses — it becomes a different, more intricate distribution that itself has to be sampled correctly, not approximated.
double cox_ingersoll_ross_process::next_stochastic() { const double decay = std::exp(-kappa_); const double c = sigma_ * sigma_ * (1.0 - decay) / (4.0 * kappa_); const double d = 4.0 * kappa_ * theta_ / (sigma_ * sigma_); const double lambda = rate_ * decay / c; // shrinks toward 0 as rate_ -> 0 // Simplified for clarity: the real code guards this draw for lambda == 0 // (rate_ touching the zero boundary this section discusses), since // std::poisson_distribution asserts on a zero mean. const int n = std::poisson_distribution<int>(lambda / 2.0)(rng_); std::chi_squared_distribution<double> chi2(d + 2.0 * n); return c * chi2(rng_); }
Detail
The SDE
identical to Vasicek's drift, \(\kappa(\theta-r)\), with the volatility term changed from a constant \(\sigma\) to \(\sigma\sqrt{r}\). As \(r \to 0\), the volatility term vanishes too, which is exactly the mechanism keeping \(r\) from crossing zero: the closer the rate gets to zero, the less randomness is left to push it further down, leaving the positive drift term \(\kappa\theta\, dt\) to pull it back up.
The Feller condition
Whether \(r\) can ever touch zero (as opposed to merely staying close to it) depends on the Feller condition: \(2\kappa\theta \ge \sigma^2\). When it holds, \(r\) stays strictly positive for all time; when it does not, \(r\) can touch zero (but never go negative) before being pulled back up by the drift term. This makes CIR's non-negativity guarantee genuinely stronger than Vasicek's total absence of one, but not an unconditional "always strictly positive" guarantee independent of parameter choice — the guarantee's strength depends on which side of the Feller condition the chosen \((\kappa, \theta, \sigma)\) fall on.
The exact transition
Because the SDE above is nonlinear in \(r\) (via \(\sqrt{r}\)), it has no closed-form solution the way Vasicek's linear SDE does — but the exact transition distribution from one tick to the next is still known in closed form, as a Poisson mixture of central chi-squared distributions (Glasserman, 2003, section 3.4):
\begin{align} c &= \frac{\sigma^2 (1 - e^{-\kappa})}{4\kappa} \\ d &= \frac{4\kappa\theta}{\sigma^2} \quad \text{(degrees of freedom)} \\ \lambda &= \frac{r_t e^{-\kappa}}{c} \quad \text{(non-centrality)} \\ N &\sim \mathrm{Poisson}(\lambda/2) \\ r_{t+1} &= c X, \quad X \sim \chi^2(d + 2N) \end{align}
cox_ingersoll_ross_process draws this transition exactly, tick by tick, rather than
approximating it via an Euler scheme (which for CIR specifically can
produce negative simulated rates — the very defect the model was
designed to avoid — unless a more careful discretisation is used; drawing
the exact transition sidesteps that problem entirely). \(\kappa\) must be
strictly positive for this construction (\(c\) above divides by \(\kappa\))
— unlike Vasicek and
Hull-White, which tolerate
\(\kappa \le 0\) as a degenerate driftless case, CIR has no such fallback
since the \(\sqrt{r}\) volatility term makes a non-mean-reverting CIR
process ill-posed. The \(\sigma = 0\) edge case is likewise handled
separately, as the deterministic mean-reversion ODE
\(dr = \kappa(\theta-r)\, dt\), since both the transition formulas above and
the closed-form bond price below divide by \(\sigma\).
The closed-form bond price
CIR also supplies a closed-form affine zero-coupon bond price, derived the same way as Vasicek's — applying Ito's lemma to the SDE above to obtain the bond's own dynamics — despite the SDE itself having no closed-form path solution:
\begin{align} \gamma &= \sqrt{\kappa^2 + 2\sigma^2} \\ B(\tau) &= \frac{2(e^{\gamma\tau} - 1)}{(\gamma+\kappa)(e^{\gamma\tau}-1) + 2\gamma} \\ A(\tau) &= \left[ \frac{2\gamma\, e^{(\kappa+\gamma)\tau/2}} {(\gamma+\kappa)(e^{\gamma\tau}-1) + 2\gamma} \right]^{2\kappa\theta/\sigma^2} \\ P(\tau) &= A(\tau)\, e^{-B(\tau)\, r_t} \end{align}dt: an explicit, separate step-length parameter
As with Vasicek/
Hull-White, \(\kappa\),
\(\theta\), \(\sigma\) are always in the SDE's own (annual) time unit; a
tick's real-world length is a separate, explicit dt — a constructor
parameter defaulting to 1.0. Both the exact transition and the
closed-form bond price need it: decay=/=c=/=lambda in the transition
use \(e^{-\kappa\, dt}\) in place of \(e^{-\kappa}\), and \(\tau\) in the
bond price is \(\text{ticks\_ahead} \times dt\), not the raw tick count.
Because CIR's bond price is already a closed form (no iterative
recursion the way Hull-White's time-varying-\(\theta\) case needs), this
dt fix is a single substitution once dt is threaded through — but
omitting it has the same failure mode as Hull-White's uncorrected
recursion: \(\tau\) used as a raw tick count silently treats each tick as
a full year, over-discounting by a factor of \(1/dt\) at fine tick
granularities (e.g. daily ticks, dt = 1/365). See
the task that found and
fixed this for the concrete numbers, and
Hull-White's own doc for
the cross-check against QuantLib's identical speed=/=dt separation
convention.
See also
- Stochastic Processes — the hub, including the comparison table across all four mean-reverting processes.
- Ornstein-Uhlenbeck Process — the drift shape CIR shares with Vasicek and Hull-White.
- Vasicek Process — the constant-volatility model whose main criticised weakness (negative rates) CIR addresses.
- Ito's Lemma — used to derive the closed-form bond price above.
Further reading
- Cox, J. C., Ingersoll, J. E., & Ross, S. A. (1985). "A Theory of the Term Structure of Interest Rates." Econometrica, 53(2), 385-407. The original paper: the SDE, the Feller condition, and the closed-form affine bond price.
- Feller, W. (1951). "Two Singular Diffusion Problems." Annals of Mathematics, 54(1), 173-182. The earlier, purely mathematical paper establishing the boundary-behaviour condition later named after Feller and applied to the CIR process above.
- Glasserman, P. (2003). Monte Carlo Methods in Financial Engineering.
Springer. Section 3.4 gives the Poisson-mixture-of-chi-squared exact
simulation scheme
cox_ingersoll_ross_processimplements directly. - Wikipedia: Cox-Ingersoll-Ross model.