Implementation of common interest rate models and (a few of) their extensions in C++. This project aims to act as an implementation and mathematical reference for interest rate models that build upon the basics (Vasicek, CIR, etc.) via more complex dynamics.
The src folder contains the cpp files with the models.
Vasicek-CIR.cpp contains the basic Vasicek, exponential Vasicek, and CIR implementations.
General-CIR.hpp contains the Stable CIR and
BK.cpp contains the Black-Karasinski implementation.
HW.cpp contains the One-Factor and Two-Factor Hull-White models.
If you are unfamiliar with the classic interest rate models, I recommend reading this book; this text was used for mathematical reference of the classic models. A basic description of the classic models is also given below. If you are familiar with them, skip to the Modern Models subsection.
The Euler-Maruyama method was used for all numerical integration.
Vasicek:
The Vasicek model states that the instantaneous interest rate is derived from the following stochastic differential equation:
where
-
$\kappa > 0$ is the reversion rate (how fast the process reverts to the mean) -
$\theta$ is the long-term mean to which the process reverts -
$\sigma > 0$ is the volatility coefficient -
$W(t)$ is a standard Brownian motion -
$r(t)$ is the short-term interest rate that one aims to solve for
The
One may solve the differential equation conditional on filtration
Given the simplicity of the model, one may derive the price of a pure-discount bond given current time
where
I will defer further mathematical explanation to Section 3.2.1 of the reference book for brevity.
A few issues of the Vasicek model are that it allows for negative interest rates due to the unconstrained movement of the
Cox-Ingress-Ross (CIR):
The CIR model addresses the issue of negative interest rates in the Vasicek model by multiplying the random fluctuation term by
This prevents negative interest rates since the steps become infinitesimally small when
All other variables in the CIR model are defined similarly to the Vasicek model. Although slightly more complex, the CIR model is still simple enough to derive the expected rate, variance, and price of a pure-discount bond analytically:
where
I will defer to Section 3.2.3 of the reference book for further explanation.
The CIR model suffers from issues similar to those of the Vasicek model, apart from negative rates. Extreme movements influence real-life financial data to observe distributions with fatter tails than the normal distribution, implying models such as the CIR model underestimate risk. The Stable CIR model will address this issue by basing the movement term on a Levy alpha-stable distribution instead of the normal distribution.
Exponential Vasicek (EV):
The EV model assumes the short rate follows a lognormal distribution instead of a normal distribution as the Vasicek model does. Suppose that
By Ito's Lemma, the SDE for
The explicit definition of the expectation and variance of
There are no explicit formulas for pure-discount bonds; they can be solved numerically instead.
The EV model suffers from an infinite expected value of the money-market account regardless of maturity as
Black-Karasinski (BK)
The BK model is an extension of the EV model where the mean
No analytic formulas for discount bonds or option bonds exist, similar to the EV model, although they may be simulated with a trinomial tree.
Similar to the EV model, the expected money-market account value is infinite regardless of maturity since it is assumed that
One-Factor Hull-White (HW1)
The HW1 model is an extension of the Vasicek model as it allows the long-term mean
This model assumes
Although more complex than the Vasicek model, HW1 is still too simple to capture the intricacies of the entire yield curve given interest rate movements typically depend on multiple sources of risk (multiple Brownian motions). Extensions of the HW1 model, such as the Two-Factor Hull-White model or Multi-Factor Hull-White models were developed to address this issue. The following section will detail the Two-Factor Hull-White model.
Two-Factor Hull-White (HW2)
As mentioned in the previous section, HW2 extends HW1 by adding a second risk (stochastic factor, Brownian motion in this case) to provide additional flexibility to the term structure. The SDEs that define this model are the following:
HW2 is equivalent to the G2++ model; G2++ is typically used in practice as its implementation is simpler than HW2. I will leave further mathematical explanation to section 4.2 of the reference book.
The mathematics of the Stable CIR and
Stable CIR:
As mentioned in the CIR subsection, the Stable CIR model aims to enhance the classic CIR model by basing the motion on fatter-tailed distributions as real data tends to show larger aberrations than that of idealized models using the normal distribution via Brownian motion. This paper gives more mathematical background to WHY we want a fatter-tailed distribution; I encourage you to read this for more background, but I will be omitting the explanation and will move on to the HOW of the problem.
First, I must define the Levy alpha-stable distribution class. Four parameters define said class of distributions: the stability parameter
- Distributions with
$\alpha = 2$ are normal - Distributions with
$\alpha = 1$ are Cauchy - Distributions with
$\alpha < 2$ have undefined second and higher moments (variance and higher moments) - Distributions with
$\alpha \leq 1$ have undefined first and higher moments (mean and higher moments)
Given this information, one must limit the distributions to
where
The characteristic function is not particularly useful for this application; it is provided for context and your general enlightenment.
Thus, the inverse transform method cannot be used since the cumulative distribution function (cdf) cannot be derived. Instead, the inverse cdf can be estimated with the stochastic model from this paper. Said paper did not hypothesize the model but proved its correctness. The model is defined as follows (VERY nested, but it is relatively straightforward):
given
where
and
given random variables
The uniform and exponential distribution generators in C++ simulated these random variables. This is known as the Chamber-Mallows-Stuck method.
Most of the legwork is done defining the distribution; the model is straightforward in comparison. The stochastic differential equation is defined as follows:
where
This is essentially the same as the CIR model except the random walk is based on an alpha-stable distribution instead of a normal distribution. The
The SDE of this process is defined as follows:
given indices
The summation term represents multiple independent sources of stochastic noise that scale based on the current interest rate, each process with a unique distribution. The
In short, one may control the
This model may be improved by removing the assumption of independence between risks as real-life risks are seldom independent.
Loop-blocking
Also known as loop-tiling, this improves computation speed by breaking down large blocks/loops into smaller blocks/tiles that fit into various levels of cache more efficiently. Smaller blocks of data allow the data to stay in the smaller, faster caches (L1 or L2) and reduce cache misses since there are fewer evictions. This allows for multi-level cache utilization that can be tuned using programs such as Intel VTune. One may adjust the block size constant for optimal efficiency.
The goal of this project was to refresh and expand my knowledge of interest rate models, create reference material for those interested in the basics of modeling interest rate SDEs, and further improve my C++ knowledge/OOP organization.
Although this repo mainly contains well-studied interest rate SDEs, this will act as the basis for more nuanced implementations moving forward. I will come back to this project later to add additional modern academic techniques; admittedly, I did not get to as much of this content as I would have liked. Plans for the future of this (or a tangential) project include focusing on extensions of multi-factor models such as the Longstaff-Schwartz, Chen, Heath-Jarrow-Merton family (HJM), and LIBOR models (a commonly used subset of the HJM framework).
A significant amount of time was spent reading C++ documentation to ensure the code reached an adequate standard of efficiency and formatting. The standards/guidelines I followed were the CppCoreGuidelines and muOS++. Effective C++ was used supplementally for code design. That being said, there is room for improvement. If you are experienced with C++ and would like to leave some comments or do a code review, please contact me on LinkedIn.
The descriptions came out much longer than I intended, but I figured I would make it detailed since my only other life responsibility while completing the bulk of this project was playing Elden Ring. At the time of this writing, I have a level 200+ Dex build using the Backhand Blade. Edit: I had to change back to my heavy affinity Greatsword build for Consort Radahn; it was quite difficult.
If you are interested in more of the project details or my Elden Ring build, please contact me via LinkedIn.