(
params: OuProcessParams,
initial_price: f64,
n_paths: usize,
horizon: usize,
seed: u64,
)
| 152 | } |
| 153 | |
| 154 | pub fn generate_ou_paths( |
| 155 | params: OuProcessParams, |
| 156 | initial_price: f64, |
| 157 | n_paths: usize, |
| 158 | horizon: usize, |
| 159 | seed: u64, |
| 160 | ) -> Result<Vec<Vec<f64>>, String> { |
| 161 | if !initial_price.is_finite() { |
| 162 | return Err("initial_price must be finite".to_string()); |
| 163 | } |
| 164 | if n_paths == 0 || horizon < 2 { |
| 165 | return Err("n_paths must be > 0 and horizon must be >= 2".to_string()); |
| 166 | } |
| 167 | if !params.phi.is_finite() |
| 168 | || !params.intercept.is_finite() |
| 169 | || !params.equilibrium.is_finite() |
| 170 | || !params.sigma.is_finite() |
| 171 | { |
| 172 | return Err("O-U parameters must be finite".to_string()); |
| 173 | } |
| 174 | if params.sigma < 0.0 { |
| 175 | return Err("sigma must be non-negative".to_string()); |
| 176 | } |
| 177 | |
| 178 | let mut rng = StdRng::seed_from_u64(seed); |
| 179 | let noise = StandardNormal; |
| 180 | let mut out = Vec::with_capacity(n_paths); |
| 181 | |
| 182 | for _ in 0..n_paths { |
| 183 | let mut path = Vec::with_capacity(horizon); |
| 184 | path.push(initial_price); |
| 185 | for _ in 1..horizon { |
| 186 | let prev = path[path.len() - 1]; |
| 187 | let eps: f64 = noise.sample(&mut rng); |
| 188 | let next = params.intercept + params.phi * prev + params.sigma * eps; |
| 189 | path.push(next); |
| 190 | } |
| 191 | out.push(path); |
| 192 | } |
| 193 | |
| 194 | Ok(out) |
| 195 | } |
| 196 | |
| 197 | pub fn evaluate_rule_on_paths( |
| 198 | paths: &[Vec<f64>], |
no test coverage detected