forked from avhz/RustQuant
-
Notifications
You must be signed in to change notification settings - Fork 0
/
custom_process.rs
83 lines (71 loc) · 2.69 KB
/
custom_process.rs
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
// This example is a demonstration of implementing a custom stochastic process
// and using it to generate a path.
// You can create your own stochastic process by creating a struct that
// implements the `StochasticProcess` trait.
//
// The demonstration uses the Rickter Wavelet function in the diffusion
// coefficient.
//
// From Wikipedia: https://en.wikipedia.org/wiki/Ricker_wavelet
//
// """
// The Ricker Wavelet is the negative normalized second derivative of a Gaussian
// function, i.e., up to scale and normalization, the second Hermite function.
// It is a special case of the family of continuous wavelets (wavelets used in a
// continuous wavelet transform) known as Hermitian wavelets.
// The Ricker wavelet is frequently employed to model seismic data, and as a
// broad spectrum source term in computational electrodynamics. It is usually
// only referred to as the Mexican hat wavelet in the Americas, due to taking
// the shape of a sombrero when used as a 2D image processing kernel.
// It is also known as the Marr wavelet for David Marr.
// """
use std::f64::consts::PI;
use RustQuant::{math::Sequence, plot_vector, stochastics::process::StochasticProcess};
fn main() {
// Create an x-axis.
let x = f64::linspace(-5., 5., 1000);
// Create a y axis.
let y = x.iter().map(|&t| ricker_wavelet(t, 1.)).collect::<Vec<_>>();
// Plot the wavelet.
plot_vector!(y, "./images/ricker_wavelet.png");
// Create a custom Ito process instance.
let custom_process = CustomItoProcess {
mu: 0.0,
sigma: 1.0,
};
// Generate a path and plot it.
let output = custom_process.euler_maruyama(0.01, 0.0, 10.0, 500, 1, false);
plot_vector!(output.paths[0], "./images/ricker_wavelet_process.png");
}
// Your custom stochastic process parameters.
// In theory you can have as many parameters as you want,
// but you will need to implement the `StochasticProcess` trait.
struct CustomItoProcess {
/// The drift coefficient ($\mu$).
pub mu: f64,
/// The volatility coefficient ($\sigma$).
pub sigma: f64,
}
// dX(t)
// = μ(X, t) dt + σ(X, t) dW(t)
// = μ * X dt + φ(t - 5, σ) * X dW(t)
impl StochasticProcess for CustomItoProcess {
// μ(X, t) = μ * X
fn drift(&self, x: f64, _t: f64) -> f64 {
self.mu * x
}
// σ(X, t) = φ(t - 5, σ) * X
fn diffusion(&self, x: f64, t: f64) -> f64 {
x * ricker_wavelet(t - 5., self.sigma)
}
fn jump(&self, _x: f64, _t: f64) -> Option<f64> {
None
}
}
// The Ricker Wavelet.
fn ricker_wavelet(t: f64, sigma: f64) -> f64 {
2. * f64::sqrt(3. * sigma)
* f64::powf(PI, 0.25)
* (1. - f64::powi(t / sigma, 2))
* f64::exp(-0.5 * f64::powi(t / sigma, 2))
}