Discount Bond Valuation from Forward Rates in an LMM
Summary
The document discusses how to interpret a LIBOR Market Model matrix when constructing discount bond values. It emphasizes that matrix layout must be understood first: under a common convention, columns represent observation times and diagonal entries identify successive forward rates along the relevant term structure.
To value a bond, use the forward rates for each period from the valuation time through maturity, taking the appropriate diagonal entries and combining the period discount factors. The answer does not provide a completed implementation or a precise matrix formula, because the question leaves the row and column meanings unclear. Its useful contribution is the conceptual mapping between an LMM rate matrix and the forward rates needed for discounting; other matrix representations are possible, so the indexing convention must be specified before coding.
Key ideas
- A rate matrix’s row and column meanings must be established before implementing bond valuation.
- Under a common LMM layout, each column represents a time and diagonal entries identify successive forward rates.
- Discounting to a bond’s maturity uses the forward rates for each intervening period.
- Different matrix representations are possible, so the valuation logic depends on the chosen convention.
Tags
Full text
# Finding Discount Bond Matrix in LMM Model C++
# Finding Discount Bond Matrix in LMM Model C++
I am working on a 1 Factor Libor Market Model (LMM) in C++ and I working my implementation of the formula to find my Discount Bond matrix via the following formula:
In the case of my model alpha is constant at .25 and my matrix L is 20 x 20. Here is my code:
```
#include <random>
#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <vector>
#include <cmath>
#include <limits>
#include <cstdlib>
#include <chrono>
#include <iterator>
#include <algorithm>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/kurtosis.hpp>
#include <boost/accumulators/statistics/variance.hpp>
#include <boost/accumulators/statistics/skewness.hpp>
#include <dlib/optimization.h>
#include <dlib/matrix.h>
#include "mleFunctor.h"
#include "mleDerFunctor.h"
using namespace boost::accumulators;
using namespace dlib;
typedef matrix<double, 0, 1> column_vector;
//Generate Gaussian via Box-Muller from Mark Joshi's C++ Design Patterns and Derivatives Pricing
double GetOneGaussianByBoxMuller()
{
double result;
double x;
double y;
double sizeSquared;
do
{
x = 2.0*std::rand() / static_cast<double>(RAND_MAX) - 1;
y = 2.0*std::rand() / static_cast<double>(RAND_MAX) - 1;
sizeSquared = x*x + y*y;
} while (sizeSquared >= 1.0);
result = x*sqrt(-2 * log(sizeSquared) / sizeSquared);
return result;
}
double libSum(matrix<double,20,20> v, matrix<double, 20, 20> lib, int r,int c , double d, int index,std::vector<double> W)
{
double sum = 0.0;
for (auto k = index + 1; k < lib.nr()-1; ++k)
{
sum += ((d*v(k,c-1)*lib(k,c-1))/(1+d*lib(k,c-1)))*v(k,c-1) * lib(r, c-1)*(W[c] - W[c-1]);
}
return sum;
}
matrix<double> findDF(matrix<double> ell)
{
matrix<double,20,20> Df;
set_all_elements(Df, 0);
double prod = 1.0;
//Need to execute the formula in the question
for (auto c = 0;c < ell.nc(); ++c)
{
for (auto r = 0; r < ell.nr(); ++r)
{
//formula for D goes here
}
}
return Df;
}
void lmm()
{
double dt = .25;
std::vector<double> W(20);
std::vector<double> T;
matrix<double, 20, 20> L;
W[0] = 0;
for (auto c = 1; c < W.size(); ++c)
{
W[c] = W[c - 1] + sqrt(dt)*GetOneGaussianByBoxMuller();
}
for (auto i = 0; i < 20; ++i)
{
T.push_back(i*.25);
}
set_all_elements(L, 0);
set_colm(L, 0) = .003641; //3M Libor Rate on November 16,2015
matrix<double,20,20> vol;
set_all_elements(vol,.15);
for (auto c = 1; c < L.nc(); ++c)
{
for (auto r = c; r < L.nc()-1; ++r)
{
L(r, c) = L(r, c-1) - libSum(vol, L,r,c, .25, c,W) + vol(r,c-1) * L(r, c-1 )*(W[c] - W[c-1]);
}
}
for (auto c = 1; c < L.nc(); ++c)
{
L(19, c) = L(19, c - 1) + vol(19, c - 1) * L(19, c - 1)*(W[c] - W[c - 1]);
}
std::ofstream outfile("LMMFlatVol.csv");
outfile << L << std::endl;
matrix<double> df = findDF(L);
}
int main()
{
lmm();
return 0;
}
```
Any help related to building the loop structure in the function findDf() is much appreciated.
## Answer by SmallChess (score 0, accepted)
https://quant.stackexchange.com/a/21817
I have every reason to believe this is a homework so I won't code it for you. In fact, your question is not totally clear, you haven't told us what are the rows and what are the columns. We know it's a 20x20 matrix, but what it's that supposed to be?
A common implementation is illustrated below:
So you can have a diagonal matrix where the columns are the times. Each column specifies a term structure. Note that this is not the only representation, but it makes perfect sense to me.
To price a discounted bond, you would need the forward rates for each successive period up to the maturity of the bond. You will do it by the forward rates in the diagonal of the matrix. For example, L1(T(0)) is the LIBOR spot rate from today to T(1). L2(T(1)) is the LIBOR forward rate from T(1) to T(2).
To do it in C++, you will simply need to iterate the diagonal entries. This shouldn't be a problem for someone learning quantitative finance. Ask stack overflow.com if you're having issues.Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.