From 58ae1086e9ed7537a28d3c2a11b1092bf6edd8bd Mon Sep 17 00:00:00 2001 From: Daniel Boros Date: Thu, 12 Sep 2024 22:14:26 +0200 Subject: [PATCH] feat: add rbergomi model --- stochastic-rs-core/src/volatility.rs | 33 +-------- stochastic-rs-core/src/volatility/rbergomi.rs | 71 +++++++++++++++++++ 2 files changed, 73 insertions(+), 31 deletions(-) create mode 100644 stochastic-rs-core/src/volatility/rbergomi.rs diff --git a/stochastic-rs-core/src/volatility.rs b/stochastic-rs-core/src/volatility.rs index 55131f3..09dfe61 100644 --- a/stochastic-rs-core/src/volatility.rs +++ b/stochastic-rs-core/src/volatility.rs @@ -1,33 +1,4 @@ -//! This module contains the implementations of various diffusion processes. -//! -//! The following diffusion processes are implemented: -//! -//! - Duffie-Kan Model -//! - The Duffie-Kan model is a multifactor interest rate model incorporating correlated Brownian motions. -//! - SDE: `dr(t) = (a1 * r(t) + b1 * x(t) + c1) * dt + sigma1 * (alpha * r(t) + beta * x(t) + gamma) * dW_r(t)` -//! - SDE: `dx(t) = (a2 * r(t) + b2 * x(t) + c2) * dt + sigma2 * (alpha * r(t) + beta * x(t) + gamma) * dW_x(t)` -//! - where Corr(W_r(t), W_x(t)) = rho -//! -//! - **Heston Model** -//! - A stochastic volatility model used to describe the evolution of the volatility of an underlying asset. -//! - SDE: `dS(t) = mu * S(t) * dt + S(t) * sqrt(V(t)) * dW_1(t)` -//! - SDE: `dV(t) = kappa * (theta - V(t)) * dt + eta * sqrt(V(t)) * dW_2(t)` -//! -//! - SABR (Stochastic Alpha, Beta, Rho) Model -//! - Widely used in financial mathematics for modeling stochastic volatility. -//! - SDE: `dF(t) = V(t) * F(t)^beta * dW_F(t)` -//! - SDE: `dV(t) = alpha * V(t) * dW_V(t)` -//! - where Corr(W_F(t), W_V(t)) = rho -//! -//! - **Vasicek Model** -//! - An Ornstein-Uhlenbeck process used to model interest rates. -//! - SDE: `dX(t) = theta * (mu - X(t)) * dt + sigma * dW(t)` -//! -//! - **Fractional Vasicek (fVasicek) Model** -//! - Incorporates fractional Brownian motion into the Vasicek model. -//! - SDE: `dX(t) = theta * (mu - X(t)) * dt + sigma * dW^H(t)` -//! -//! Each process has its own module and functions to generate sample paths. - +pub mod fheston; pub mod heston; +pub mod rbergomi; pub mod sabr; diff --git a/stochastic-rs-core/src/volatility/rbergomi.rs b/stochastic-rs-core/src/volatility/rbergomi.rs new file mode 100644 index 0000000..330533f --- /dev/null +++ b/stochastic-rs-core/src/volatility/rbergomi.rs @@ -0,0 +1,71 @@ +use ndarray::{s, Array1}; + +use crate::{noise::cgns::Cgns, Sampling2D}; + +#[derive(Default)] +pub struct RoughBergomi { + pub hurst: f64, + pub nu: f64, + pub sigma_0: f64, + pub r: f64, + pub rho: f64, + pub n: usize, + pub t: Option, + pub m: Option, + pub cgns: Cgns, +} + +impl RoughBergomi { + #[must_use] + pub fn new(params: &Self) -> Self { + let cgns = Cgns::new(&Cgns { + rho: params.rho, + n: params.n, + t: params.t, + m: params.m, + }); + + Self { + hurst: params.hurst, + nu: params.nu, + sigma_0: params.sigma_0, + r: params.r, + rho: params.rho, + n: params.n, + t: params.t, + m: params.m, + cgns, + } + } +} + +impl Sampling2D for RoughBergomi { + fn sample(&self) -> [Array1; 2] { + let dt = self.t.unwrap_or(1.0) / self.n as f64; + let [cgn1, z] = self.cgns.sample(); + + let mut s = Array1::::zeros(self.n + 1); + let mut sigma2 = Array1::::zeros(self.n + 1); + + for i in 1..(self.n + 1) { + s[i] = s[i - 1] + self.r * s[i - 1] + sigma2[i - 1] * cgn1[i - 1]; + + let sum_z = z.slice(s![..i]).sum(); + let t = i as f64 * dt; + sigma2[i] = self.sigma_0.powi(2) + * (self.nu * (2.0 * self.hurst).sqrt() * t.powf(self.hurst - 0.5) * sum_z + - 0.5 * self.nu.powi(2) * t.powf(2.0 * self.hurst)) + .exp(); + } + + [s, sigma2] + } + + fn n(&self) -> usize { + self.n + } + + fn m(&self) -> Option { + self.m + } +}