简体   繁体   English

C ++ Eigen库中用于设置矢量/矩阵的未知错误

[英]Unknown errors within the C++ Eigen library for setting vectors/matrices

I am trying to implement the Longstaff and Scwartz algorithm that essentially is a Least-Squares method to price American options. 我正在尝试实现Longstaff和Scwartz算法,该算法本质上是对美国期权定价的最小二乘法。 I am using Matlab code as a reference to program this in C++. 我使用Matlab代码作为在C ++中进行编程的参考。

What I have done thus far is first I set a time step variable named 到目前为止,我要做的是首先设置一个时间步变量

dt = T/N where T is the expiration time, and N is the number of time steps. dt = T/N ,其中T是到期时间, N是时间步长。

Then a time vector (in Matlab denoted t = 0:dt:T ). 然后是时间向量(在Matlab中表示为t = 0:dt:T )。 I created a function for this in C++ that is posted below: 我在C ++中为此创建了一个函数,发布在下面:

    VectorXd range(double min, double max, int N){
    VectorXd m(N + 1);
     double delta = (max-min)/N;
     for(int i = 0; i <= N; i++){
             m(i) = min + i*delta;
     }
    return m;
}

Then I have to generate a vector that generates a set of normally distributed random numbers. 然后,我必须生成一个向量,该向量生成一组正态分布的随机数。 In Matlab the function is called z = randn(M/2,1) where M is the number of paths. 在Matlab中,该函数称为z = randn(M/2,1) ,其中M是路径数。 In C++ I made a function for this which is listed below: 在C ++中,我为此做了一个函数,下面列出了它:

MatrixXd generateGaussianNoise(int n, int m){
    MatrixXd M(n,m);
    VectorXd V(n);
    normal_distribution<double> nd(0.0, 1.0);
    random_device rd;
    mt19937 gen(rd());
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            M(i,j) = nd(gen);
        }
    }
    return M;
}

Now we have to create another vector called w = (r-sigma^2/2)*T + sigma*sqrt(T)*[z;z] . 现在我们必须创建另一个向量w = (r-sigma^2/2)*T + sigma*sqrt(T)*[z;z] Before this I had to create another C++ function for handling the Matlab syntax [z;z] This is listed below: 在此之前,我必须创建另一个C ++函数来处理Matlab语法[z;z]如下所示:

MatrixXd generateMatrix(MatrixXd z){
    MatrixXd Dm(2*z.rows(),z.cols());
        Dm << z, -z;
        return Dm;
}

Then I can create the w variable with another C++ function I created listed below: 然后,我可以使用下面列出的另一个C ++函数创建w变量:

MatrixXd generateWMatrix(double r, double sigma, double T, MatrixXd Dm){
    MatrixXd w(Dm.rows(),Dm.cols());
    for(int i = 0; i < Dm.rows(); i++){
        for(int j = 0; j < Dm.cols(); j++){
            w(i,j) = (r - pow(sigma,2)/2)*T + sigma*sqrt(T)*Dm(i,j);
        }
    }
        return w;
}

Now we have to create a new variable S = S0*exp(w) where S0 is the initial asset price. 现在我们必须创建一个新变量S = S0*exp(w) ,其中S0是初始资产价格。 We can do this in a for loop which is listed below: 我们可以在下面列出的for循环中执行此操作:

MatrixXd S(w.rows(),w.cols());
        for(int i = 0; i < w.rows(); i++){
            for(int j = 0; j < w.cols(); j++){
                S(i,j) = exp(w(i,j));
            }
        }

Now this is where things for me get a bit ugly which is the Main Point of this post. 现在,这是事情我得到一个有点难看这是这篇文章的要点 We have to do a backward for loop for the actual algorithm. 我们必须为实际算法做一个反向for循环。 I will present the beginning part of the Matlab code for reference which is where things go wrong for me in C++: 我将介绍Matlab代码的开始部分,以供参考,这是C ++中出现问题的地方:

for i = N:-1:2

    z = randn(M/2,1);
    w = t(i)*w/(t(i+1)) + sigma*sqrt(dt*t(i)/(t(i+1)))*[z;z];

Now in C++ what I try to do is this: 现在在C ++中,我尝试做的是:

for(int i = N; i >= 2; i--){
      z(i) = generateGaussianNoise(M/2, 1);
      zz(i) = generateMatrix(z);
      w(i) = t(i)*w(i)/(t(i+1)) + sigma*sqrt(dt*t(i)/(t(i+1)))*zz(i);
}

Although I get the following errors for z(i) : 尽管我得到z(i)的以下错误:

cannot convert 'Eigen::MatrixXd {aka Eigen::Matrix<double, -1, -1>}' to 

'Eigen::DenseCoeffsBase<Eigen::Matrix<double, -1, -1>, 1>::Scalar {aka 
double}' in assignment

and for zz(i) I get the following error: 对于zz(i)我得到以下错误:

cannot convert 'Eigen::MatrixXd {aka Eigen::Matrix<double, -1, -1>}' to 

'Eigen::DenseCoeffsBase<Eigen::Matrix<double, -1, -1>, 1>::Scalar {aka double}' in assignment

and for w(i) I get the following error: 对于w(i)我得到以下错误:

invalid arguments '
Candidates are:
double sqrt(double)
float sqrt(float)
long double sqrt(long double)
__gnu_cxx::__enable_if<74 0 __value 14 std::__is_integer 1 #074 0 __value 14 std::__is_integer 1 #0,double>::__type sqrt(#0)
const Eigen::CwiseUnaryOp<Eigen::internal::scalar_sqrt_op<#0::Scalar>,const #0> sqrt(const Eigen::ArrayBase<#0> &)
float sqrt(float)
long double sqrt(long double)
std::complex<#0> sqrt(const std::complex<#0> &)
__gnu_cxx::__enable_if<74 0 __value 14 std::__is_integer 1 #074 0 __value 14 std::__is_integer 1 #0,double>::__type 

I am not sure what I am doing wrong in the latter above or what these errors mean. 我不确定上面的后者我在做什么错或这些错误意味着什么。 Of course I have tried googling them to see what the problem is but I don't get any useful information. 当然,我已经尝试使用谷歌搜索它们,以查看问题出在哪里,但我没有得到任何有用的信息。 For completeness I will post my whole code below: 为了完整起见,我将在下面发布整个代码:

#include <iostream>
#include <cmath>
#include <math.h>
#include <limits>
#include <algorithm>
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <random>

using namespace Eigen;
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
MatrixXd generateGaussianNoise(int n, int m); // Generates Normally distributed random numbers
double LSM(double T, double r, double sigma, double K, double S0, int N, int M, int R);
// 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

VectorXd range(double min, double max, int N);
MatrixXd generateMatrix(MatrixXd z);
MatrixXd generateWMatrix(double r, double sigma, double T, MatrixXd z);

int main(){
double r = 0.06;
double sigma = 0.25;
int T = 1.0;
int N = 2;
double dt = T/N;
    VectorXd t = range(0.0, T, N);

    MatrixXd result1 = generateGaussianNoise(2,1);


    MatrixXd result2 = generateMatrix(result1);

    MatrixXd w = generateWMatrix(r,sigma,T, result2);







}


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;
}

MatrixXd generateGaussianNoise(int n, int m){
    MatrixXd M(n,m);
    normal_distribution<double> nd(0.0, 1.0);
    random_device rd;
    mt19937 gen(rd());
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            M(i,j) = nd(gen);
        }
    }
    return M;
}

VectorXd range(double min, double max, int N){
    VectorXd m(N + 1);
     double delta = (max-min)/N;
     for(int i = 0; i <= N; i++){
             m(i) = min + i*delta;
     }
    return m;
}

MatrixXd generateMatrix(MatrixXd z){
    MatrixXd Dm(2*z.rows(),z.cols());
        Dm << z, -z;
        return Dm;
}


MatrixXd generateWMatrix(double r, double sigma, double T, MatrixXd Dm){
    MatrixXd w(Dm.rows(),Dm.cols());
    for(int i = 0; i < Dm.rows(); i++){
        for(int j = 0; j < Dm.cols(); j++){
            w(i,j) = (r - pow(sigma,2)/2)*T + sigma*sqrt(T)*Dm(i,j);
        }
    }
        return w;
}



double LSM(double T, double r, double sigma, double K, double S0, int N, int M, int R){
    double dt = T/N;
    VectorXd t = range(0,T,N);
    MatrixXd z = generateGaussianNoise(M/2, 1);
    MatrixXd zz = generateMatrix(z); // Need to do this for the [z;-z]
    MatrixXd w = generateWMatrix(r, sigma, T, zz);
    MatrixXd S(w.rows(),w.cols());
        for(int i = 0; i < w.rows(); i++){
            for(int j = 0; j < w.cols(); j++){
                S(i,j) = exp(w(i,j));
            }
        }
    MatrixXd P(S.rows(), S.cols());

    MatrixXd z_new(M,1);
    for(int i = N; i >= 2; i--){
        z_new.topRows(M/2) = generateGaussianNoise(M/2,1);
        z_new.bottomRows(M/2) = -z_new.topRows(M/2);
        w = t(i-1)*w/t(i) + sigma*sqrt((dt*t(i-1)/t(i)))*z_new;
    }







    return 0;

}

Update: I added the new full code but I am still getting some errors in the exp() and sqrt() in the function called double LSM(double T, double r, double sigma, double K, double S0, int N, int M, int R) I have tried to google what I could but I don't have any idea how to fix the following error messages: 更新:我添加了新的完整代码,但在名为double LSM(double T, double r, double sigma, double K, double S0, int N, int M, int R) sqrt()的函数的exp()sqrt()中仍然出现一些错误double LSM(double T, double r, double sigma, double K, double S0, int N, int M, int R)我已经尝试过用Google搜索,但是我不知道如何解决以下错误消息:

For exp() I get this message: 对于exp()我得到以下消息:

Invalid arguments '
Candidates are:
double exp(double)
float exp(float)
long double exp(long double)
__gnu_cxx::__enable_if<74 0 __value 14 std::__is_integer 1 #074 0 __value 14 std::__is_integer 1 #0,double>::__type exp(#0)
const Eigen::CwiseUnaryOp<Eigen::internal::scalar_exp_op<#0::Scalar>,const #0> exp(const Eigen::ArrayBase<#0> &)
float exp(float)
long double exp(long double)
std::complex<#0> exp(const std::complex<#0> &)
__gnu_cxx::__enable_if<74 0 __value 14 std::__is_integer 1 #074 0 __value 14 std::__is_integer 1 #0,double>::__type 

For the sqrt() I get this message: 对于sqrt()我得到以下消息:

Invalid arguments '
Candidates are:
double sqrt(double)
float sqrt(float)
long double sqrt(long double)
__gnu_cxx::__enable_if<74 0 __value 14 std::__is_integer 1 #074 0 __value 14 std::__is_integer 1 #0,double>::__type sqrt(#0)
const Eigen::CwiseUnaryOp<Eigen::internal::scalar_sqrt_op<#0::Scalar>,const #0> sqrt(const Eigen::ArrayBase<#0> &)
float sqrt(float)
long double sqrt(long double)
std::complex<#0> sqrt(const std::complex<#0> &)
__gnu_cxx::__enable_if<74 0 __value 14 std::__is_integer 1 #074 0 __value 14 std::__is_integer 1 #0,double>::__type

Here is the Matlab code I am trying to implement in Eigen. 这是我试图在Eigen中实现的Matlab代码。 I will just post the parts in the Matlab code that I have done successfully and the parts that I having a hard time implementing: 我将在成功完成的Matlab代码中发布我很难实现的部分:

function u = LSM(T,r,sigma,K,S0,N,M,k)
% 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
% k Number of basis functions
dt = T/N; % Time steps
t = 0:dt:T; % Time vector
z = randn(M/2,1);
w = (r-sigmaˆ2/2)*T + sigma*sqrt(T)*[z;-z];
S = S0*exp(w);
P = max(K-S,0); % Payoff at time T
for i = N:-1:2
z = randn(M/2,1);
w = t(i)*w/t(i+1) + sigma*sqrt(dt*t(i)/t(i+1))*[z;-z];

Everything after the for loop is where I am struggling... for循环之后的所有内容都是我在努力的地方...

The following line does not make sense: 以下行没有意义:

zz(i) = generateMatrix(z);

zz(i) is a double& whereas generateMatrix returns a MatrixXd . zz(i)double&generateMatrix返回MatrixXd Same for w(i) . w(i)相同。

You can almost literally translate this Matlab code 您几乎可以从字面上翻译此Matlab代码

for i = N:-1:2
    z = randn(M/2,1);
    w = t(i)*w/t(i+1) + sigma*sqrt(dt*t(i)/t(i+1))*[z;-z];
end

to Eigen (assuming everything outside the loop works): 到Eigen(假设循环外的所有内容都有效):

MatrixXd zz(M,1); // allocate space for [z; -z] only once
for(int i=N; i>=2; --i){
    zz.topRows(M/2) = generateGaussianNoise(M/2,1);
    zz.bottomRows(M/2) = -zz.topRows(M/2);

    w = t(i-1)*w/t(i) + sigma*std::sqrt(dt*t(i-1)/t(i))*zz;
}

Essentially, the only difference is that Matlab starts indexing at 1 and Eigen starts at 0. 本质上,唯一的区别是Matlab从1开始索引,而Eigen从0开始。

Also concatenating [z;-z] is not possible "inlined" in Eigen, but I'm wondering why you do the same calculations for z and -z anyway ... 另外,在[z;-z] Eigen [z;-z]中不可能将[z;-z]串联起来,但是我想知道为什么您无论如何-zz-z进行相同的计算...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM