Search code examples
c++loopsmatrixnested-loops

Increase number of columns filled in as row number increases


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.


Solution

  • 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]);
        }
    }