Skip to content

Commit

Permalink
Merge pull request #9 from ssoudan/0.6.0-rc
Browse files Browse the repository at this point in the history
0.6.0-rc
  • Loading branch information
ssoudan authored Oct 11, 2023
2 parents 43ac82d + 899adb2 commit bb6d8f4
Show file tree
Hide file tree
Showing 12 changed files with 212 additions and 74 deletions.
34 changes: 17 additions & 17 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,21 +85,21 @@ jobs:
command: build
args: --release --all-features --all-targets

benches:
name: Benchmarks
runs-on: ubuntu-latest
# benches:
# name: Benchmarks
# runs-on: ubuntu-latest

steps:
- name: Install lld
run: sudo apt-get update && sudo apt-get install -y lld wget unzip
- name: Install latest nightly
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
override: true
- uses: actions/checkout@v2
- name: Bench
uses: actions-rs/cargo@v1
with:
command: bench
args: --all --features=unstable
# steps:
# - name: Install lld
# run: sudo apt-get update && sudo apt-get install -y lld wget unzip
# - name: Install latest nightly
# uses: actions-rs/toolchain@v1
# with:
# toolchain: nightly
# override: true
# - uses: actions/checkout@v2
# - name: Bench
# uses: actions-rs/cargo@v1
# with:
# command: bench
# args: --all --features=unstable
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
Cargo.lock
.vscode
BUILD.sh
venv/
test.ipynb
12 changes: 8 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,30 @@ exclude = [
"/.cargo/*",
"/.gitignore",
"/.devcontainer/*",
"/.vscode/*",
"/.git/*",
"/.idea/*",
"/venv/*",
]

[features]
default = []
unstable = [ "rand", "rand_distr"]
unstable = ["rand", "rand_distr"]

[[bench]]
name = "ols"
harness = false
required-features = [ "unstable" ]
required-features = ["unstable"]

[[bench]]
name = "dickeyfuller"
harness = false
required-features = [ "unstable" ]
required-features = ["unstable"]

[[bench]]
name = "adf"
harness = false
required-features = [ "unstable" ]
required-features = ["unstable"]

[dependencies]
nalgebra = "0"
Expand Down
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ Stationarity tests for time-series data in Rust.

At the moment:
[Dickey-Fuller test](https://en.wikipedia.org/wiki/Dickey–Fuller_test) and
[Augmented Dickey-Fuller test](https://en.wikipedia.org/wiki/Augmented_Dickey–Fuller_test) with a
constant but no trend.
[Augmented Dickey-Fuller test](https://en.wikipedia.org/wiki/Augmented_Dickey–Fuller_test) with no constan no trend, constant or constant and trend.

## License

Expand Down Expand Up @@ -43,16 +42,16 @@ fn main() {

// compute the test statistic
let regression = Regression::Constant;
let report = tools::adf::adf_test(&y, lag, regression).unwrap();
let report = tools::adf_test(&y, lag, regression).unwrap();

// critical values for the model with a constant but no trend:
let critical_value = distrib::dickeyfuller::get_critical_value(
let critical_value: f32 = distrib::dickeyfuller::get_critical_value(
regression,
report.size,
AlphaLevel::OnePercent,
)
.unwrap();
assert_eq!(report.size, 10);
assert_eq!(report.size, 8);

// comparison
let t_stat = report.test_statistic;
Expand Down
2 changes: 1 addition & 1 deletion benches/adf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use rand::SeedableRng;
use unit_root::prelude::distrib::Regression;
use unit_root::prelude::tools::adf::adf_test;
use unit_root::prelude::tools::adf_test;
use unit_root::utils::gen_ar_1;

fn adf_benchmark_f32_2(c: &mut Criterion) {
Expand Down
6 changes: 3 additions & 3 deletions benches/dickeyfuller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use rand::SeedableRng;
use unit_root::prelude::distrib::Regression;
use unit_root::prelude::tools::dickeyfuller;
use unit_root::prelude::tools::dickeyfuller_test;
use unit_root::utils::gen_ar_1;

fn df_benchmark_f32(c: &mut Criterion) {
Expand All @@ -30,7 +30,7 @@ fn df_benchmark_f32(c: &mut Criterion) {
let y = gen_ar_1(&mut rng, *size, mu, delta, sigma);

c.bench_with_input(BenchmarkId::new("df_f32", size), &y, |b, y| {
b.iter(|| dickeyfuller::dickeyfuller_test(y, Regression::Constant))
b.iter(|| dickeyfuller_test(y, Regression::Constant))
});
}
}
Expand All @@ -45,7 +45,7 @@ fn df_benchmark_f64(c: &mut Criterion) {
let y = gen_ar_1(&mut rng, *size, mu, delta, sigma);

c.bench_with_input(BenchmarkId::new("df_f64", size), &y, |b, y| {
b.iter(|| dickeyfuller::dickeyfuller_test(y, Regression::Constant))
b.iter(|| dickeyfuller_test(y, Regression::Constant))
});
}
}
Expand Down
2 changes: 1 addition & 1 deletion examples/adf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ fn main() {
// compute the test statistic
let lag = 1;
let regression = Regression::Constant;
let report = tools::adf::adf_test(&y, lag, regression).unwrap();
let report = tools::adf_test(&y, lag, regression).unwrap();

// critical values for the model with a constant but no trend:
let critical_value =
Expand Down
2 changes: 1 addition & 1 deletion examples/dickeyfuller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fn main() {
-0.42968979,
]);

let report = tools::dickeyfuller::dickeyfuller_test(&y, Regression::Constant).unwrap();
let report = tools::dickeyfuller_test(&y, Regression::Constant).unwrap();

let critical_value =
constant_no_trend_critical_value(report.size, AlphaLevel::OnePercent).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
//! use unit_root::prelude::distrib::dickeyfuller::get_critical_value;
//! use unit_root::prelude::distrib::{AlphaLevel, Regression};
//! use unit_root::prelude::nalgebra::DVector;
//! use unit_root::prelude::tools::adf::adf_test;
//! use unit_root::prelude::tools::adf_test;
//! use unit_root::prelude::*;
//!
//! let y = DVector::from_row_slice(&[
Expand Down
14 changes: 4 additions & 10 deletions src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,11 @@ pub use crate::Error;

/// Tools
pub mod tools {
pub use crate::tools::Report;

/// Dickey-Fuller test
pub mod dickeyfuller {
pub use crate::tools::dickeyfuller::dickeyfuller_test;
}

/// Augmented Dickey-Fuller test
pub mod adf {
pub use crate::tools::adf::adf_test;
}
pub use crate::tools::adf::adf_test;
/// Dickey-Fuller test
pub use crate::tools::dickeyfuller::dickeyfuller_test;
pub use crate::tools::Report;
}

/// Distributions
Expand Down
125 changes: 95 additions & 30 deletions src/tools/adf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,47 +40,112 @@ pub fn adf_test<F: RealField + Scalar + Float>(
})
}

/// Comparison with statsmodels.tsa.stattools.adfuller use the following code:
/// ```python
/// import numpy as np
/// import pandas as pd
/// import statsmodels.tsa.stattools as ts
/// pd.options.display.float_format = '{:.12g}'.format
///
/// def adf_test(timeseries, maxlag=None, regression="c", autolag="AIC"):
/// print("Results of Dickey-Fuller Test:")
/// dftest = ts.adfuller(timeseries, maxlag=maxlag, regression=regression, autolag=autolag)
/// dfoutput = pd.Series(
/// dftest[0:4],
/// index=[
/// "Test Statistic",
/// "p-value",
/// "#Lags Used",
/// "Number of Observations Used",
/// ],
/// )
/// for key, value in dftest[4].items():
/// dfoutput["Critical Value (%s)" % key] = value
/// print(dfoutput)
///
/// y = [-1.06714348, -1.14700339, 0.79204106, -0.05845247, -0.67476754,
/// -0.10396661, 1.82059282, -0.51169443, 2.07712365, 1.85668086, 2.56363688]
///
/// adf_test(y, maxlag=2, regression='n')
/// adf_test(y, maxlag=2, regression='c')
/// adf_test(y, maxlag=2, regression='ct')
/// ```
///
/// Note: this library does not support the `autolag` yet. Tests are using the lag from
/// statsmodels.
#[cfg(test)]
mod tests {
use approx::assert_relative_eq;
use nalgebra::DVector;

use crate::distrib::Regression;
use crate::prelude::tools::dickeyfuller;
use crate::tools::adf::adf_test;
use crate::prelude::tools::{adf_test, dickeyfuller_test};

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 lag = 1;
let y = DVector::from_row_slice(&Y[..]);

let report = adf_test(&y, lag, Regression::NoConstantNoTrend).unwrap();
assert_eq!(report.size, 9);
assert_relative_eq!(report.test_statistic, -0.417100483298f64, epsilon = 1e-9);
// Test Statistic -0.417100483298
// p-value 0.529851882135
// #Lags Used 1
// Number of Observations Used 9
// Critical Value (1%) -2.85894
// Critical Value (5%) -1.96955775034
// Critical Value (10%) -1.58602219479
}

#[test]
fn test_t_statistics() {
fn test_t_statistics_c() {
let lag = 2;
let y = DVector::from_row_slice(&[
-1.06714348,
-1.14700339,
0.79204106,
-0.05845247,
-0.67476754,
-0.10396661,
1.82059282,
-0.51169443,
2.07712365,
1.85668086,
2.56363688,
]);
let y = DVector::from_row_slice(&Y[..]);

let report = adf_test(&y, lag, Regression::Constant).unwrap();
assert_eq!(report.size, 8);
assert_relative_eq!(
report.test_statistic,
0.48612142266202985f64,
epsilon = 1e-3
);
// statsmodels.tsa.stattools.adfuller(y, maxlag=2, regression='c') gives:
// ADF Statistic: 0.486121
// p-value: 0.984445
// Critical Values:
// 1%: -4.665
// 5%: -3.367
// 10%: -2.803
// usedlag= 2
assert_relative_eq!(report.test_statistic, 0.486121422662f64, epsilon = 1e-9);
// Results of Dickey-Fuller Test:
// Test Statistic 0.486121422662
// p-value 0.984445107564
// #Lags Used 2
// Number of Observations Used 8
// Critical Value (1%) -4.66518632812
// Critical Value (5%) -3.367186875
// Critical Value (10%) -2.802960625
}

#[test]
fn test_t_statistics_ct() {
let lag = 0;
let y = DVector::from_row_slice(&Y[..]);

let report = adf_test(&y, lag, Regression::ConstantAndTrend).unwrap();
assert_eq!(report.size, 10);
assert_relative_eq!(report.test_statistic, -4.20337098854f64, epsilon = 1e-9);
// Results of Dickey-Fuller Test:
// Test Statistic -4.20337098854
// p-value 0.00442477220907
// #Lags Used 0
// Number of Observations Used 10
// Critical Value (1%) -5.282515
// Critical Value (5%) -3.985264
// Critical Value (10%) -3.44724
}

#[test]
Expand All @@ -94,7 +159,7 @@ mod tests {
let regression = Regression::Constant;

let report = adf_test(&y, lag, regression).unwrap();
let df_report = dickeyfuller::dickeyfuller_test(&y, regression).unwrap();
let df_report = dickeyfuller_test(&y, regression).unwrap();

assert_eq!(report.test_statistic, df_report.test_statistic);
assert_eq!(report.size, df_report.size);
Expand Down
Loading

0 comments on commit bb6d8f4

Please sign in to comment.