I am writing a program to fill in a matrix (I use the dlib library but not relevant to the question. In the following my goal is for rows 1-19 (row indices 0-18) for one additional column to fill in with my formula. For example row 1 has the first column filled in, row 2 has the first two columns filled in. The first column for every row is preset to my initial value as required. What can I do to the nested for loops indicated by comment my lmm() function to get my desired output?
#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;
//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;
}
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);
//Loop that should fill in one more column each (ie 0 indexed row has one column filled in,
//row index 1 should have 2 columns filled in etc
for (auto c = 1; c < L.nc(); ++c)
{
for (auto r = 1; r < c; ++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]);
}
}
std::ofstream outfile("LMMFlatVol.csv");
outfile << L << std :: endl;
}
int main()
{
lmm();
return 0;
}
As of right now my output is just the preset first columns with the rest of the matrix zeroes as I initialized.
Your primary problem seems to be your loop condition. Note that the inner for loop should start at the first active row. For example, in the third column (c==2) the first time you calculate a value is row three (r==2). After that all rows until the bottom of the matrix have a calculated value.
Your previous logic did not even calculate any value for the second column (c==1) because r was set to 1 and (r < c) evaluated to false!
for (auto c = 1; c < L.nc(); ++c)
{
for (auto r = c; r < L.nc(); ++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]);
}
}