0
$\begingroup$

I am using this matrix class here to assist me in converting this Least Squares algorithm that prices American options that is written in Matlab in C++. My question is pretty simple. I want to pass in a vector into a function but it has to be with this matrix class. For some reason, I get an error stating:

  cannot convert 'QSMatrix<double>' to 'double' for argument '2' to 
'QSMatrix<double> randn_vec2(int, double)'

My code has many comments in it so it should be rather easy to follow. I am using the matrix class linked in the above so I will just post my main file for sake of completion. Any comments or suggestions are greatly appreciated.

 #include <iostream>
#include <cmath>
#include <limits>
#include <algorithm>
#include "matrix.h"

using namespace std;


double LaguerreExplicit(int R, double x); // Generates the (weighted) laguerre value
double payoff_Call(double S, double K); // Pay off of a call option
double LSM(int T, double r, double sigma , double K, double S0, int N, int M, int R);
double generateGaussianNoise(double mu, double sigma); // Generates Normally distributed random numbers
// Notation:
// T        expiration time
// r        riskless interest rate
// sigma    volatility
// K        strike price
// S0       initial asset price
// N        number of time steps
// M        number of paths
// R        number of basis functions
QSMatrix<double> randn_vec(int n, int M);
QSMatrix<double> range(double min, double max, double N); // Creates a vector of evenly spaced numbers
QSMatrix<double> rand_vec(int n, int k); // k = 1 to make this into a vector
QSMatrix<double> randn_vec2(int n, int M); // this is to replace the compand [z;z] in Matlab

int main(){
    int M = 4;
    QSMatrix<double> z = randn_vec2(M/2,1);
    z.print();

    QSMatrix<double> B = range(0,1,6);
    //B.print();

    LSM(1, .06, .25 , 10.5, 12.5, 2, 4, 4);



      return 0;
}


double payoff_Call(double S, double K){
    double payoff;
    if((S - K) > 0)
    {
        payoff = S - K;
    }else
    {
        payoff = 0.0;
    }
    return payoff;
}

double LaguerreExplicit(int R, double x){
    double value;
    if(R==0)
    {
        value = 1;
    }
    else if(R==1)
    {
        value = 0.5*(pow(x,2) - 4.0*x + 2);
    }
    else if(R==3)
    {
        value = (1.0/6.0)*(-1*pow(x,3) + 9*pow(x,2) - 18*x + 6);
    }
    else if(R==4)
    {
        value = (1.0/24.0)*(pow(x,4) - 16*pow(x,3) + 72*pow(x,2) - 96*x + 24);
    }
    else if(R==5)
    {
        value = (1.0/120.0)*(-1*pow(x,5) + 25*pow(x,4) - 200*pow(x,3) + 600*pow(x,2) - 600*x + 120);
    }
    else if (R==6)
    {
        value = (1.0/720.0)*(pow(x,6) - 36*pow(x,5) + 450*pow(x,4) - 2400*pow(x,3) + 5400*pow(x,2) - 4320*x + 720);
    }
    else{
        cout << "Error!, R is out of range" << endl;
        value  = 0;
    }
    value = exp(-0.5*x)*value; // Weighted used in Longstaff-Scwartz
    return value;
}

double generateGaussianNoise(double mu, double sigma)
{
    const double epsilon = std::numeric_limits<double>::min();
    const double two_pi = 2.0*M_PI;

    static double z0, z1;
    static bool generate;
    generate = !generate;

    if (!generate)
       return z1 * sigma + mu;

    double u1, u2;
    do
     {
       u1 = rand() * (1.0 / RAND_MAX);
       u2 = rand() * (1.0 / RAND_MAX);
     }
    while ( u1 <= epsilon );

    z0 = sqrt(-2.0 * log(u1)) * cos(two_pi * u2);
    z1 = sqrt(-2.0 * log(u1)) * sin(two_pi * u2);
    return z0 * sigma + mu;
}


QSMatrix<double> range(double min, double max, double N){
    QSMatrix<double> mat(N+1,1,0);
    double delta = (max-min)/N;
    for(int i = 0; i < mat.get_rows();i++){
        for(int j = 0; j < mat.get_cols();j++){
            mat(i,j) = min + i*delta;
        }
    }
    return mat;
}

QSMatrix<double> randn_vec(int n, int M){
    QSMatrix<double> mat(n,1,0);
    for(int i = 0; i < mat.get_rows();i++){
        for(int j = 0; j < mat.get_cols();j++){
            mat(i,j) = generateGaussianNoise(M/2,1);
        }
    }
    return mat;
}

QSMatrix<double> randn_vec2(int n, int M){
    QSMatrix<double> mat = randn_vec(n,M);
    QSMatrix<double> mat1(2*n,1,0);
    for(int i = 0; i < mat1.get_rows();i++){
            for(int j = 0; j < mat1.get_cols();j++){
                mat1(i,j) = mat(0,j);
            }
        }
        return mat1;
}

QSMatrix<double> rand_vec(int n, int k){
    QSMatrix<double> mat(n,k,0);
    for(int i = 0; i < mat.get_rows(); i++){
        for(int j = 0; j < mat.get_cols(); j++){
            mat(i,j) = 0.0;
        }
    }
    return mat;
}



double LSM(int T, double r, double sigma , double K, double S0, int N, int M, int R){
    double dt = T/N;                                // Time steps
    QSMatrix<double> t = range(0,T,dt);             // Time vector
    //QSMatrix<double> z = randn_vec(M/2,1);
    //QSMatrix<double> temp = rand_vec(4,1);
    //QSMatrix<double> w = temp + (r-pow(sigma,2))*T + sigma*sqrt(T);
    //z.print();
    //cout << " " << endl;
    //w.print();





    return 0;
}

Please ignore the last part above I am sort of re-editing this question as so:

Ok, so I decided instead of passing in a vector into a function I will make a new function that calls on the previous function randn_vec(). Please turn your attention to this block of code:

QSMatrix<double> randn_vec2(int n, int M){
    QSMatrix<double> mat = randn_vec(n,M);
    QSMatrix<double> mat1(2*n,1,0);
    for(int i = 0; i < mat1.get_rows();i++){
            for(int j = 0; j < mat1.get_cols();j++){
                mat1(i,j) = mat(0,j);
            }
        }
        return mat1;
}

What I am trying to do here is make a function that basically is going to copy the Matlab function $[z;z]$ where z = randn(2,1) the randn function in Matlab generates an array or vector of Normally distributed random numbers. so for example $$z = \begin{pmatrix} 0.3188\\ -1.3077 \end{pmatrix}$$ and when you write $[z;z]$ in Matlab it produces this: $$[z;z] = \begin{pmatrix} 0.3188\\ -1.3077\\ 0.3188\\ -1.3077 \end{pmatrix}$$

Now in the latter block of code I am referring to that is what I am trying to achieve but I cannot seem to get it correctly. This is my new updated question.

$\endgroup$
  • 1
    $\begingroup$ If you're doing this as a hobby, fine, but (especially) if you're using this for a production system, you should know that the QSMatrix is a really poor matrix class implementation. Its main issue is that it doesn't store its rows in contiguous memory, but there are a number of other inefficiencies as well. I recommend using a professionally-developed library such as Eigen, which also is far more feature-rich and easier to use. Presumably you're leaving Matlab for C++ in order to get better speed, and you're leaving a lot on the table with this QSMatrix. $\endgroup$ – Tyler Olsen Jan 22 '17 at 21:28
  • $\begingroup$ @TylerOlsen Yes, that is exactly what I am trying to do. The library known as Eigen you just sent me, is that easier to use when converting Matlab code into C++? $\endgroup$ – Wolfy Jan 22 '17 at 21:34
  • $\begingroup$ It is simply a better library than the QuantStart stuff, which is meant to be a gentle introduction to C++. Eigen happens to support a matlab-like syntax quite efficiently, but converting matlab to C++ is never quite as straightforward as you'd hope. Your code could be essentially identical, but just use a Eigen::MatrixXd rather than a QSMatrix<double>. $\endgroup$ – Tyler Olsen Jan 22 '17 at 21:42
  • 2
    $\begingroup$ Also, it seems like you're pretty new to C++ in general. I'd recommend googling around a bit for some tutorials to get a better handle on the language before trying to translate code from matlab. There's plenty of good stuff out there that will help you to understand the errors that your compiler is giving you. $\endgroup$ – Tyler Olsen Jan 22 '17 at 21:44
  • $\begingroup$ @TylerOlsen Thank you, I have done many tutorials online (thenewboston) on youtube but yea I am still a newb even after using C++ for 2 years now $\endgroup$ – Wolfy Jan 22 '17 at 21:57
1
$\begingroup$
QSMatrix<double> randn_vec2(int n,double vec){

This is the culprit. You want vec to be a vector, so make it such

QSMatrix<double> randn_vec2(int n,QSMatrix<double> vec){

But the code has too many other bugs. For example, you have missed the loop variable in the condition in for(int j = 0; 2*vec.length();j++){. You need a thorough review to make sure that everything is written as you intend it to work.

$\endgroup$
  • $\begingroup$ Please see updated edit. I am new to this beta so I apologize if I am not posting on here correctly. $\endgroup$ – Wolfy Jan 22 '17 at 21:37
  • $\begingroup$ Replace mat1(i,j) = mat(0,j); with mat1(i,j) = mat(i%n,j);. You need to learn some proper programming and do some dry runs of your loop - or just print out every intermediate step. $\endgroup$ – Raziman T V Jan 22 '17 at 21:45
  • $\begingroup$ Will do, believe it or not its been about 2 years for me using C++ but I am still a newb $\endgroup$ – Wolfy Jan 22 '17 at 21:55
  • $\begingroup$ There are also conflicting declarations of the randn_vec2 functions that either take a double or an int as second argument. $\endgroup$ – Wolfgang Bangerth Jan 22 '17 at 23:51

Not the answer you're looking for? Browse other questions tagged or ask your own question.