use nalgebra::{RealField, Scalar};
use num_traits::Float;
use crate::distrib::Regression;
use crate::prelude::nalgebra::DVector;
use crate::prelude::tools::Report;
use crate::regression::ols;
use crate::tools::prepare;
use crate::Error;
pub fn dickeyfuller_test<F: Float + Scalar + RealField>(
series: &DVector<F>,
regression: Regression,
) -> Result<Report<F>, Error> {
let (delta_y, y_t_1, size) = prepare(series, 0, regression)?;
let (_betas, t_stats) = ols(&delta_y, &y_t_1)?;
Ok(Report {
test_statistic: t_stats[0],
size,
})
}
#[cfg(test)]
mod tests {
use approx::assert_relative_eq;
use rand::prelude::*;
use rand_chacha::ChaCha8Rng;
use super::*;
use crate::distrib::dickeyfuller::constant_no_trend_critical_value;
use crate::distrib::AlphaLevel;
use crate::utils::gen_ar_1;
const Y: [f64; 11] = [
-1.06714348,
-1.14700339,
0.79204106,
-0.05845247,
-0.67476754,
-0.10396661,
1.82059282,
-0.51169443,
2.07712365,
1.85668086,
2.56363688,
];
#[test]
fn test_t_statistics_n() {
let y = DVector::from_row_slice(&Y[..]);
let report = dickeyfuller_test(&y, Regression::NoConstantNoTrend).unwrap();
assert_eq!(report.size, 10);
assert_relative_eq!(report.test_statistic, -1.5140129055f64, epsilon = 1e-9);
}
#[test]
fn test_t_statistics_c() {
let y = DVector::from_row_slice(&Y[..]);
let report = dickeyfuller_test(&y, Regression::Constant).unwrap();
assert_eq!(report.size, 10);
assert_relative_eq!(report.test_statistic, -1.83288396527f64, epsilon = 1e-9);
}
#[test]
fn test_t_statistics_ct() {
let y = DVector::from_row_slice(&Y[..]);
let report = dickeyfuller_test(&y, Regression::ConstantAndTrend).unwrap();
assert_eq!(report.size, 10);
assert_relative_eq!(report.test_statistic, -4.20337098854f64, epsilon = 1e-9);
}
#[test]
fn test_dickeyfuller_no_unit_root_f32() {
let n = 100;
let mut rng = ChaCha8Rng::seed_from_u64(42);
let delta: f32 = 0.5;
let y = gen_ar_1(&mut rng, n, 0.0, delta, 1.0);
let report = dickeyfuller_test(&y, Regression::Constant).unwrap();
let critical_value =
match constant_no_trend_critical_value(report.size, AlphaLevel::OnePercent) {
Ok(v) => v,
Err(_) => f32::MIN,
};
let t_stat = report.test_statistic;
assert!(t_stat < critical_value);
}
#[test]
fn test_dickeyfuller_with_unit_root_f32() {
let n = 100;
let mut rng = ChaCha8Rng::seed_from_u64(42);
let delta: f32 = 1.0;
let y = gen_ar_1(&mut rng, n, 0.0, delta, 1.0);
let report = dickeyfuller_test(&y, Regression::Constant).unwrap();
let critical_value =
match constant_no_trend_critical_value(report.size, AlphaLevel::OnePercent) {
Ok(v) => v,
Err(_) => f32::MAX,
};
let t_stat = report.test_statistic;
assert!(t_stat > critical_value);
}
#[test]
fn test_dickeyfuller_no_unit_root_f64() {
let n = 100;
let mut rng = ChaCha8Rng::seed_from_u64(42);
let delta: f64 = 0.5;
let y = gen_ar_1(&mut rng, n, 0.0, delta, 1.0);
let report = dickeyfuller_test(&y, Regression::Constant).unwrap();
let critical_value =
match constant_no_trend_critical_value(report.size, AlphaLevel::OnePercent) {
Ok(v) => v,
Err(_) => f64::MIN,
};
let t_stat = report.test_statistic;
assert!(t_stat < critical_value);
}
#[test]
fn test_dickeyfuller_with_unit_root_f64() {
let n = 100;
let mut rng = ChaCha8Rng::seed_from_u64(42);
let delta: f64 = 1.0;
let y = gen_ar_1(&mut rng, n, 0.0, delta, 1.0);
let report = dickeyfuller_test(&y, Regression::Constant).unwrap();
let critical_value =
match constant_no_trend_critical_value(report.size, AlphaLevel::OnePercent) {
Ok(v) => v,
Err(_) => f64::MAX,
};
let t_stat = report.test_statistic;
assert!(t_stat > critical_value);
}
#[test]
fn no_enough_data() {
let y = DVector::from_row_slice(&[1.0]);
let report = dickeyfuller_test(&y, Regression::Constant);
assert!(report.is_err());
}
#[test]
fn test_constant_no_trend_test() {
let y = vec![1_f32, 3., 6., 10., 15., 21., 28., 36., 45., 55.];
let y = DVector::from(y);
let report = dickeyfuller_test(&y, Regression::Constant).unwrap();
assert_eq!(report.size, 9);
}
}