云金杞 2024-07-17 21:43 采纳率: 25%
浏览 22
已结题

改写c++进行adf检验的函数代码

使用c++进行单位根检验(ADF test)- 麻烦请运行下答案,提供运行成功的截图,看下是否正确再提交答案,快20个答案了,没一个对的。

python版本的adf检验计算结果

from statsmodels.tsa.stattools import adfuller 
from arch.unitroot import ADF
ADF(data, lags=1)

> Augmented Dickey-Fuller Results
Test Statistic    -2.680
P-value    0.078
Lags    1


Trend: Constant
Critical Values: -4.67 (1%), -3.37 (5%), -2.80 (10%)
Null Hypothesis: The process contains a unit root.
Alternative Hypothesis: The process is weakly stationary.

adfuller(data, 1)

> (-2.680281337094476,
 0.07751305492650781,
 1,
 8,
 {'1%': -4.6651863281249994, '5%': -3.3671868750000002, '10%': -2.802960625},
 -33.3578749925597)

我在chatgpt上问了答案,给出了一个版本,计算出来的t值和python中的adf检验结果不一致

#include <iostream>
#include <vector>
#include <numeric>
#include <cmath>
#include <stdexcept>
#include "gtest/gtest.h"

// 计算均值
double mean(const std::vector<double>& data) {
    return std::accumulate(data.begin(), data.end(), 0.0) / data.size();
}

// 计算向量之间的内积
double dot_product(const std::vector<double>& v1, const std::vector<double>& v2) {
    double result = 0.0;
    for (size_t i = 0; i < v1.size(); ++i) {
        result += v1[i] * v2[i];
    }
    return result;
}

// 矩阵乘法(矩阵和向量)
std::vector<double> matrix_vector_multiply(const std::vector<std::vector<double>>& A, const std::vector<double>& B) {
    int rows = A.size();
    int cols = A[0].size();
    std::vector<double> result(rows, 0.0);
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            result[i] += A[i][j] * B[j];
        }
    }
    return result;
}

// 矩阵求逆(任意大小的方阵)
std::vector<std::vector<double>> matrix_inverse(const std::vector<std::vector<double>>& A) {
    int n = A.size();
    std::vector<std::vector<double>> A_inv(n, std::vector<double>(n, 0.0));
    std::vector<std::vector<double>> augmented_matrix(n, std::vector<double>(2 * n, 0.0));

    // 创建增广矩阵
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            augmented_matrix[i][j] = A[i][j];
        }
        augmented_matrix[i][n + i] = 1.0;
    }

    // 高斯-约旦消元法
    for (int i = 0; i < n; ++i) {
        // 选择主元
        double pivot = augmented_matrix[i][i];
        if (pivot == 0) {
            throw std::runtime_error("Matrix is singular, cannot invert.");
        }

        // 归一化主元行
        for (int j = 0; j < 2 * n; ++j) {
            augmented_matrix[i][j] /= pivot;
        }

        // 消元
        for (int k = 0; k < n; ++k) {
            if (k == i) continue;
            double factor = augmented_matrix[k][i];
            for (int j = 0; j < 2 * n; ++j) {
                augmented_matrix[k][j] -= factor * augmented_matrix[i][j];
            }
        }
    }

    // 提取逆矩阵
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            A_inv[i][j] = augmented_matrix[i][n + j];
        }
    }

    return A_inv;
}

// 计算ADF统计量
double adf_statistic(const std::vector<double>& data, int lag) {
    int n = data.size();

    if (n <= lag) {
        throw std::invalid_argument("The lag is too large for the data size.");
    }

    // 计算差分序列
    std::vector<double> diff(n - 1);
    for (int i = 1; i < n; ++i) {
        diff[i - 1] = data[i] - data[i - 1];
    }

    // 构建设计矩阵X和响应向量Y
    std::vector<std::vector<double>> X(n - lag - 1, std::vector<double>(lag + 2, 1.0)); // 包含常数项
    std::vector<double> Y(n - lag - 1);

    for (int i = lag; i < n - 1; ++i) {
        Y[i - lag] = diff[i];
        X[i - lag][1] = data[i]; // 第一列为常数项
        for (int j = 1; j <= lag; ++j) {
            X[i - lag][j + 1] = diff[i - j];
        }
    }

    // 计算(X^T * X)和(X^T * Y)
    int p = lag + 2;
    std::vector<std::vector<double>> XtX(p, std::vector<double>(p, 0.0));
    std::vector<double> XtY(p, 0.0);

    for (int i = 0; i < n - lag - 1; ++i) {
        for (int j = 0; j < p; ++j) {
            XtY[j] += X[i][j] * Y[i];
            for (int k = 0; k < p; ++k) {
                XtX[j][k] += X[i][j] * X[i][k];
            }
        }
    }

    // 计算(XtX)的逆
    std::vector<std::vector<double>> XtX_inv = matrix_inverse(XtX);

    // 计算beta = (XtX)^(-1) * XtY
    std::vector<double> beta = matrix_vector_multiply(XtX_inv, XtY);

    // 计算残差
    std::vector<double> residuals(n - lag - 1, 0.0);
    for (int i = 0; i < n - lag - 1; ++i) {
        residuals[i] = Y[i];
        for (int j = 0; j < p; ++j) {
            residuals[i] -= X[i][j] * beta[j];
        }
    }

    // 计算标准误差
    double sum_squared_residuals = std::inner_product(residuals.begin(), residuals.end(), residuals.begin(), 0.0);
    double sigma = std::sqrt(sum_squared_residuals / (n - lag - p));

    // 计算ADF统计量
    double adf_stat = beta[1] / (sigma * std::sqrt(XtX_inv[1][1]));

    return adf_stat;
}

// 测试类
class AdfTest : public ::testing::Test {
protected:
    // 可以在这里添加初始化和清理代码
};

TEST_F(AdfTest, basic) {
    // 示例时间序列数据
    std::vector<double> data = {4.4, 4.2, 4.1, 3.9, 3.8, 3.7, 3.6, 3.5, 3.4, 3.3};
    int lag = 1; // 设置滞后阶数

    double adf_stat = adf_statistic(data, lag);

    std::cout << "ADF Statistic: " << adf_stat << std::endl;
    ASSERT_NEAR(adf_stat, -2.680, 0.001);
}

求改进c++的算法,计算出来的adf_stat值和python中计算出来的值一致。改进算法50,如果能计算出来这个值对应的p值,额外打赏40

  • 写回答

23条回答 默认 最新

  • Java毕设王 2024-07-18 21:38
    关注

    引用讯飞星火
    为了计算ADF检验的p值,我们需要知道分布的自由度和统计量。在C++中,我们可以使用Boost库中的统计分布函数来计算p值。以下是一个改进后的C++代码示例,用于计算ADF检验的t值和p值:

    #include <iostream>
    #include <vector>
    #include <numeric>
    #include <cmath>
    #include <stdexcept>
    #include <boost/math/distributions/students_t.hpp>
    
    // 计算均值
    double mean(const std::vector<double>& data) {
        return std::accumulate(data.begin(), data.end(), 0.0) / data.size();
    }
    
    // 计算向量之间的内积
    double dot_product(const std::vector<double>& v1, const std::vector<double>& v2) {
        double result = 0.0;
        for (size_t i = 0; i < v1.size(); ++i) {
            result += v1[i] * v2[i];
        }
        return result;
    }
    
    // 矩阵乘法(矩阵和向量)
    std::vector<double> matrix_vector_multiply(const std::vector<std::vector<double>>& A, const std::vector<double>& B) {
        int rows = A.size();
        int cols = A[0].size();
        std::vector<double> result(rows, 0.0);
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                result[i] += A[i][j] * B[j];
            }
        }
        return result;
    }
    
    // 矩阵求逆(任意大小的方阵)
    std::vector<std::vector<double>> matrix_inverse(const std::vector<std::vector<double>>& A) {
        int n = A.size();
        std::vector<std::vector<double>> A_inv(n, std::vector<double>(n, 0.0));
        std::vector<std::vector<double>> augmented_matrix(n, std::vector<double>(2 * n, 0.0));
    
        // 创建增广矩阵
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                augmented_matrix[i][j] = A[i][j];
            }
            augmented_matrix[i][n + i] = 1.0;
        }
    
        // 高斯-约旦消元法
        for (int i = 0; i < n; ++i) {
            // 选择主元
            double pivot = augmented_matrix[i][i];
            if (pivot == 0) {
                throw std::runtime_error("Matrix is singular, cannot invert.");
            }
    
            // 归一化主元行
            for (int j = 0; j < 2 * n; ++j) {
                augmented_matrix[i][j] /= pivot;
            }
    
            // 消元
            for (int k = 0; k < n; ++k) {
                if (k == i) continue;
                double factor = augmented_matrix[k][i];
                for (int j = 0; j < 2 * n; ++j) {
                    augmented_matrix[k][j] -= factor * augmented_matrix[i][j];
                }
            }
        }
    
        // 提取逆矩阵
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                A_inv[i][j] = augmented_matrix[i][n + j];
            }
        }
    
        return A_inv;
    }
    
    // 计算ADF统计量和p值
    std::pair<double, double> adf_statistic_and_pvalue(const std::vector<double>& data, int lag) {
        int n = data.size();
    
        if (n <= lag) {
            throw std::invalid_argument("The lag is too large for the data size.");
        }
    
        // 计算差分序列
        std::vector<double> diff(n - 1);
        for (int i = 1; i < n; ++i) {
            diff[i - 1] = data[i] - data[i - 1];
        }
    
        // 构建设计矩阵X和响应向量Y
        std::vector<std::vector<double>> X(n - lag - 1, std::vector<double>(lag + 2, 1.0)); // 包含常数项
        std::vector<double> Y(n - lag - 1);
    
        for (int i = lag; i < n - 1; ++i) {
            Y[i - lag] = diff[i];
            X[i - lag][1] = data[i]; // 第一列为常数项
            for (int j = 1; j <= lag; ++j) {
                X[i - lag][j + 1] = diff[i - j];
            }
        }
    
        // 计算(X^T * X)和(X^T * Y)
        int p = lag + 2;
        std::vector<std::vector<double>> XtX(p, std::vector<double>(p, 0.0));
        std::vector<double> XtY(p, 0.0);
    
        for (int i = 0; i < n - lag - 1; ++i) {
            for (int j = 0; j < p; ++j) {
                XtY[j] += X[i][j] * Y[i];
                for (int k = 0; k < p; ++k) {
                    XtX[j][k] += X[i][j] * X[i][k];
                }
            }
        }
    
        // 计算(XtX)的逆
        std::vector<std::vector<double>> XtX_inv = matrix_inverse(XtX);
    
        // 计算beta = (XtX)^(-1) * XtY
        std::vector<double> beta = matrix_vector_multiply(XtX_inv, XtY);
    
        // 计算残差
        std::vector<double> residuals(n - lag - 1, 0.0);
        for (int i = 0; i < n - lag - 1; ++i) {
            residuals[i] = Y[i];
            for (int j = 0; j < p; ++j) {
                residuals[i] -= X[i][j] * beta[j];
            }
        }
    
        // 计算标准误差
        double sum_squared_residuals = std::inner_product(residuals.begin(), residuals.end(), residuals.begin(), 0.0);
        double sigma = std::sqrt(sum_squared_residuals / (n - lag - p));
    
        // 计算ADF统计量
        double adf_stat = beta[1] / (sigma * std::sqrt(XtX_inv[1][1]));
    
        // 计算自由度和p值
        int df = n - p;
        boost::math::students_t dist(df);
        double p_value = 2 * (1 - boost::math::cdf(boost::math::complement(dist, adf_stat)));
    
        return std::make_pair(adf_stat, p_value);
    }
    

    现在,你可以使用adf_statistic_and_pvalue函数来计算ADF统计量和对应的p值。例如:

    std::vector<double> data = {4.4, 4.2, 4.1, 3.9, 3.8, 3.7, 3.6, 3.5, 3.4, 3.3};
    int lag = 1; // 设置滞后阶数
    auto result = adf_statistic_and_pvalue(data, lag);
    std::cout << "ADF Statistic: " << result.first << std::endl;
    std::cout << "P-value: " << result.second << std::endl;
    
    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 7月25日
  • 修改了问题 7月20日
  • 赞助了问题酬金50元 7月18日
  • 创建了问题 7月17日

悬赏问题

  • ¥15 数据量少可以用MK趋势分析吗
  • ¥15 使用VH6501干扰RTR位,CANoe上显示的错误帧不足32个就进入bus off快慢恢复,为什么?
  • ¥15 大智慧怎么编写一个选股程序
  • ¥100 python 调用 cgps 命令获取 实时位置信息
  • ¥15 两台交换机分别是trunk接口和access接口为何无法通信,通信过程是如何?
  • ¥15 C语言使用vscode编码错误
  • ¥15 用KSV5转成本时,如何不生成那笔中间凭证
  • ¥20 ensp怎么配置让PC1和PC2通讯上
  • ¥50 有没有适合匹配类似图中的运动规律的图像处理算法
  • ¥15 dnat基础问题,本机发出,别人返回的包,不能命中