全部版块 我的主页
论坛 数据科学与人工智能 数据分析与数据科学 数据分析与数据挖掘
1644 0
2018-07-15
分位数回归是计量,金融常用模型,无论是CoVaR还是VaR背后都有分位数回归的身影。我采用MCMC算法估计分位数回归模型,具体算法参考Korobilis(2017)文章。关于代码作以下说明:
1. 由于代码过长(完整代码接近800行),省略自己写的矩阵类(Matrix)和随机数类(Randgen)以及数据的载入、存储,头文件等,只粘贴估计过程(接近200行)
2.平时主要搞金融计量,matlab,C++通常只作为语言工具,因此代码疏漏,bug难免,欢迎C++高手批评指正
//////////////////////////////////////////////////////分隔符///////////////////////分隔符//////////////////////////////////////////////////////////
double **QuantileReg::Reg(double **Ydata, double **Xdata, double Prob, int T, int Vartotal,int Maxiter)
{
        Matrix M;//矩阵算法Class
        Randgen Gen;//随机数Class
        ////prior////
        double **Vinv, a0 = 0.1, b0 = 0.1;
        Vinv = new double*[Vartotal];
        for (int i = 0; i < Vartotal; i++)
        {
                Vinv[i] = new double[Vartotal];
                for (int j = 0; j < Vartotal; j++)
                {
                        if (i == j)
                        {
                                Vinv[i][j] = 1.0/9.0;
                        }
                        else
                        {
                                Vinv[i][j] = 0.0;
                        }
                }
        }
        /////preset//////
        double **beta, **z, sig2 = 0.1, theta = 0.0, tau = 0.0,tau_q,theta_q,*Err,**Tmp,b1,**Diag,sig2old=sig2;
        double **beta_post, **z_post, sig2_post = 0.0;
        int a1;
        beta = new double*[Vartotal];
        beta_post = new double*[Vartotal];
        for (int i = 0; i < Vartotal; i++)
        {
                beta[i] = new double[1];
                beta_post[i] = new double[1];
        }
        for (int i = 0; i < Vartotal; i++)
        {
                for (int j = 0; j < 1; j++)
                {
                        beta[i][j] = 0.0;
                        beta_post[i][j] = 0.0;
                }
        }
        z = new double*[T];
        z_post = new double*[T];
        for (int i = 0; i < T; i++)
        {
                z[i] = new double[1];
                z_post[i] = new double[1];
        }
        for (int i = 0; i < T; i++)
        {
                for (int j = 0; j < 1; j++)
                {
                        z[i][j] = 0.2;
                        z_post[i][j] = 0.0;
                }
        }
        Err = new double[T];
        Diag = new double*[T];
        for (int t = 0; t < T; t++)
        {
                Diag[t] = new double[T];
        }
        /////////////major cycle/////////////
        int maxiter = Maxiter, burnin = floor(maxiter*0.5);
        double **Xtile, **Ytile,**V1,**Mu1,**Rtmp;
        V1 = new double*[Vartotal];
        for (int i = 0; i < Vartotal; i++)
        {
                V1[i] = new double[Vartotal];
        }
        Ytile = new double*[T];
        for (int t = 0; t < T; t++)
        {
                Ytile[t] = new double[1];
        }
        for (int iter = 0; iter < maxiter; iter++)
        {
                std::cout << "迭代次数" << iter+1<< endl;
                 tau_q = 2.0 / (Prob*(1.0 - Prob));
                 theta_q = (1.0 - 2.0*Prob) / (Prob*(1.0 - Prob));
                 /////step1 drawing sig2///////
                 a1 = a0 + floor(1.5*T);
                 Tmp = M.Matrixdot(Xdata, beta, T, Vartotal, Vartotal, 1);
                 for (int t = 0; t < T; t++)
                 {
                         Err[t] = Ydata[t][0] - Tmp[t][0] - theta_q*z[t][0];
                         Err[t] = pow(Err[t], 2.0);
                 }
                 b1 = b0;
                 for (int t = 0; t < T; t++)
                 {
                         b1 = b1 + Err[t] / (2.0*z[t][0] + tau_q);
                 }
                 Tmp = Gen.IGrnd(a1, b1, 1, 1);
                 sig2 = Tmp[0][0];
                 if (sig2 < 1e-4)
                 {
                         sig2 = sig2old;
                 }
                 sig2old = sig2;
                 //////////step2 drawing beta///////////
                 for (int i = 0; i < T; i++)
                 {
                         for (int j = 0; j < T; j++)
                         {
                                 if (i == j)
                                 {
                                         Diag[i][j] = 1.0 / (sqrt(sig2)*tau_q*z[i][0]);
                                 }
                                 else
                                 {
                                         Diag[i][j] = 0.0;
                                 }
                         }
                 }
                 Tmp = M.Matrixtrans(Xdata, T, Vartotal);//矩阵转置
                 Xtile = M.Matrixdot(Tmp, Diag, Vartotal, T, T, T);//矩阵乘法
                 Tmp = M.Matrixdot(Xtile, Xdata, Vartotal, T, T, Vartotal);
                 for (int i = 0; i < Vartotal; i++)
                 {
                         for (int j = 0; j < Vartotal; j++)
                         {
                                 V1[i][j] = Tmp[i][j] + Vinv[i][j];
                         }
                 }
                 V1 = M.Matrixinv(V1, Vartotal);
                 if (_isnan(V1[Vartotal - 1][Vartotal - 1]))
                 {
                         V1 = M.Matrixinv(Vinv, Vartotal);
                 }
                 for (int t = 0; t < T; t++)
                 {
                         Ytile[t][0] = Ydata[t][0] - theta_q*z[t][0];
                 }
                 Tmp = M.Matrixdot(Xtile, Ytile, Vartotal, T, T, 1);
                 Mu1 = M.Matrixdot(V1, Tmp, Vartotal, Vartotal, Vartotal, 1);
                 Tmp = M.Matrixchol(V1, Vartotal);
                 Rtmp = Gen.Normrnd(Vartotal, 1);
                 Tmp = M.Matrixdot(Tmp, Rtmp, Vartotal, Vartotal, Vartotal, 1);
            for (int i = 0; i < Vartotal; i++)
                 {
                         beta[i][0] = Mu1[i][0] + Tmp[i][0];
                         //std::cout << beta[i][0] << "\t";
                 }
                 ////////////step3 draw z/////////////
                 Tmp = M.Matrixdot(Xdata,beta,T,Vartotal,Vartotal,1);
                 for (int t = 0; t < T; t++)
                 {
                         double k1 = sqrt(pow(theta_q, 2.0) + 2.0*tau_q) / abs(Ydata[t][0] - Tmp[t][0]);
                         double k2 = (pow(theta_q, 2.0) + 2.0*tau_q) / tau_q;
                         Rtmp = Gen.InvGrnd(k1, k2, 1, 1);
                         if (Rtmp[0][0]>1e-3)
                         {
                                 z[t][0] = Rtmp[0][0];
                         }
                         else
                         {
                                 z[t][0] = 1e-3;
                         }
                 }
                 /////////step4 save%%%%%%%%%%%%%%
                 if (iter >= burnin)
                 {
                         for (int i = 0; i < Vartotal; i++)
                         {
                                 beta_post[i][0] = beta_post[i][0] + beta[i][0] / (maxiter - burnin);
                         }
                         for (int t = 0; t < T; t++)
                         {
                                 z_post[t][0] = z_post[t][0] + z[t][0] / (maxiter - burnin);
                         }
                         sig2_post = sig2_post + sig2 / (maxiter - burnin);
                 }
        }
        ////////////释放内存///////////////////
        for (int t = 0; t < T; t++)
        {
                delete[] Diag[t];
        }
        delete[] Diag;
        for (int t = 0; t < Vartotal; t++)
        {
                delete[] Vinv[t];
                delete[] beta[t];
        }
        delete[] Vinv;
        delete[] beta;
        delete[] Err;
        for (int t = 0; t < T; t++)
        {
                delete[] Ytile[t];
                delete[] z[t];
        }
        delete[] Ytile;
        delete[] z;
        std::cout << "估计参数向量:" << endl;
        for (int i = 0; i < Vartotal; i++)
        {
                std::cout << beta_post[i][0] << "\t";
        }
        std::cout << "残差标准差:" << endl;
        std::cout << sig2_post << endl;
        return z;//返回潜变量序列
}

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群