use ndarray::Array1;
use num_complex::Complex;
use super::coefficients::fourier_coefficients_dx;
use super::coefficients::fourier_coefficients_dx_uniform;
use crate::traits::FloatExt;
mod helpers;
mod integrated;
mod spot;
mod validation;
#[cfg(test)]
mod bias_correction_tests;
#[cfg(test)]
mod tests;
#[cfg(test)]
mod validation_tests;
pub struct FMVol<T: FloatExt> {
pub(super) dx: Array1<Complex<T>>,
pub(super) period: T,
pub(super) n: usize,
pub(super) mesh: T,
pub(super) origin: T,
pub(super) n_freq: usize,
pub(super) max_freq: usize,
}
impl<T: FloatExt> FMVol<T> {
pub fn new(prices: &[T], times: &[T], period: T) -> Self {
Self::try_new(prices, times, period)
.expect("FMVol::new precondition violated — call try_new to handle this gracefully")
}
pub fn try_new(prices: &[T], times: &[T], period: T) -> anyhow::Result<Self> {
let (n, mesh, origin) = validation::validate_irregular_inputs(prices, times, period)?;
let big_n = n / 2;
let max_freq = validation::default_max_frequency(n, big_n, mesh)?;
validation::validate_frequency_bounds(n, big_n, max_freq)?;
let dx = fourier_coefficients_dx(prices, times, period, max_freq);
Ok(Self {
dx,
period,
n,
mesh,
origin,
n_freq: big_n,
max_freq,
})
}
pub fn new_uniform(prices: &[T], period: T) -> Self {
Self::try_new_uniform(prices, period).expect(
"FMVol::new_uniform precondition violated — call try_new_uniform to handle this gracefully",
)
}
pub fn try_new_uniform(prices: &[T], period: T) -> anyhow::Result<Self> {
let n = validation::validate_uniform_inputs(prices, period)?;
let mesh = period / T::from_usize_(n);
let big_n = n / 2;
let max_freq = validation::default_max_frequency(n, big_n, mesh)?;
validation::validate_frequency_bounds(n, big_n, max_freq)?;
let dx = fourier_coefficients_dx_uniform(prices, period, max_freq);
Ok(Self {
dx,
period,
n,
mesh,
origin: T::zero(),
n_freq: big_n,
max_freq,
})
}
pub fn with_freq(prices: &[T], times: &[T], period: T, n_freq: usize, max_freq: usize) -> Self {
Self::try_with_freq(prices, times, period, n_freq, max_freq).expect(
"FMVol::with_freq precondition violated — call try_with_freq to handle this gracefully",
)
}
pub fn try_with_freq(
prices: &[T],
times: &[T],
period: T,
n_freq: usize,
max_freq: usize,
) -> anyhow::Result<Self> {
let (n, mesh, origin) = validation::validate_irregular_inputs(prices, times, period)?;
validation::validate_frequency_bounds(n, n_freq, max_freq)?;
let dx = fourier_coefficients_dx(prices, times, period, max_freq);
Ok(Self {
dx,
period,
n,
mesh,
origin,
n_freq,
max_freq,
})
}
pub fn n_freq(&self) -> usize {
self.n_freq
}
pub fn n(&self) -> usize {
self.n
}
pub fn period(&self) -> T {
self.period
}
pub fn mesh(&self) -> T {
self.mesh
}
pub fn time_origin(&self) -> T {
self.origin
}
}