-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathbasic_garch_example.rs
More file actions
95 lines (76 loc) · 3.13 KB
/
basic_garch_example.rs
File metadata and controls
95 lines (76 loc) · 3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#![allow(deprecated)]
#![allow(unused_imports)]
use chrono::{DateTime, Duration, Utc};
use oxidiviner::{EGARCHModel, GARCHMModel, GARCHModel, GJRGARCHModel, RiskPremiumType};
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("OxiDiviner GARCH Models Example");
println!("-------------------------------\n");
// Generate some synthetic returns data (random walk with some volatility clusters)
let data = generate_sample_data(1000);
println!("Generated {} sample data points", data.len());
// Demonstrate GARCH(1,1) model
println!("\n1. Standard GARCH(1,1) Model");
println!("---------------------------");
let mut garch = GARCHModel::new(1, 1, None)?;
garch.fit(&data, None)?;
println!("{}", garch);
let forecast = garch.forecast_variance(5)?;
println!("5-step ahead variance forecast: {:?}", forecast);
// Demonstrate GJR-GARCH(1,1) model with asymmetric effects
println!("\n2. GJR-GARCH(1,1) Model with Asymmetric Effects");
println!("---------------------------------------------");
let mut gjr_garch = GJRGARCHModel::new(1, 1, None)?;
gjr_garch.fit(&data, None)?;
println!("{}", gjr_garch);
let (shock_values, variance_values) = gjr_garch.news_impact_curve(10, 2.0);
println!("News Impact Curve (10 points):");
for i in 0..shock_values.len() {
println!(
" Shock: {:.2}, Variance: {:.4}",
shock_values[i], variance_values[i]
);
}
// Demonstrate EGARCH(1,1) model
println!("\n3. EGARCH(1,1) Model");
println!("------------------");
let mut egarch = EGARCHModel::new(1, 1, None)?;
egarch.fit(&data, None)?;
println!("{}", egarch);
// Demonstrate GARCH-M(1,1) model with risk premium
println!("\n4. GARCH-M(1,1) Model with Risk Premium");
println!("-------------------------------------");
let mut garch_m = GARCHMModel::new(1, 1, RiskPremiumType::StdDev, None)?;
garch_m.fit(&data, None)?;
println!("{}", garch_m);
let (mean_forecast, var_forecast) = garch_m.forecast(5)?;
println!("5-step ahead mean and variance forecast:");
for i in 0..mean_forecast.len() {
println!(
" Step {}: Mean = {:.4}, Variance = {:.4}",
i + 1,
mean_forecast[i],
var_forecast[i]
);
}
Ok(())
}
// Function to generate sample data with volatility clustering
fn generate_sample_data(n: usize) -> Vec<f64> {
use rand::prelude::*;
use rand_distr::Normal;
let mut rng = rand::thread_rng();
let mut returns = Vec::with_capacity(n);
let mut volatility = 0.01;
let mean = 0.0001; // Small positive drift
for _ in 0..n {
// Create volatility clustering by making volatility autocorrelated
volatility = 0.9 * volatility + 0.1 * (0.005 + 0.015 * rng.gen::<f64>());
// Add a safety check to prevent volatility from getting too large
volatility = volatility.min(0.05);
// Generate return with current volatility
let normal = Normal::new(mean, volatility).unwrap();
let return_value = normal.sample(&mut rng);
returns.push(return_value);
}
returns
}