use std::sync::OnceLock;
use gauss_quad::GaussLegendre;
use nalgebra::DVector;
use crate::CalibrationLossScore;
pub mod bsm;
pub mod cgmysv;
pub mod double_heston;
pub mod heston;
pub mod heston_stoch_corr;
pub mod hkde;
pub mod hw_swaption;
pub mod levy;
pub mod rbergomi;
pub mod sabr;
pub mod sabr_caplet;
pub mod svj;
pub use bsm::BSMCalibrationResult;
pub use bsm::BSMCalibrator;
pub use bsm::BSMParams;
pub use cgmysv::CgmysvCalibrationResult;
pub use cgmysv::CgmysvCalibrator;
pub use double_heston::DoubleHestonCalibrationResult;
pub use double_heston::DoubleHestonCalibrator;
pub use double_heston::DoubleHestonParams;
pub use heston::HestonCalibrationResult;
pub use heston::HestonCalibrator;
pub use heston::HestonParams;
pub use heston_stoch_corr::HscmCalibrationResult;
pub use heston_stoch_corr::MarketOption;
pub use heston_stoch_corr::calibrate_hscm;
pub use hkde::HKDECalibrationResult;
pub use hkde::HKDECalibrator;
pub use hkde::HKDEParams;
pub use hw_swaption::HullWhiteCalibrationResult;
pub use hw_swaption::HullWhiteSwaptionCalibrator;
pub use hw_swaption::SwaptionQuote;
pub use levy::LevyCalibrationResult;
pub use levy::LevyCalibrator;
pub use levy::LevyModelType;
pub use levy::MarketSlice;
pub use sabr::SabrCalibrationResult;
pub use sabr::SabrCalibrator;
pub use sabr::SabrParams;
pub use sabr_caplet::SabrCapletCalibrationResult;
pub use sabr_caplet::SabrCapletCalibrator;
pub use svj::SVJCalibrationResult;
pub use svj::SVJCalibrator;
pub use svj::SVJParams;
pub(crate) const GL_U_MAX: f64 = 100.0;
pub(crate) fn gauss_legendre_64() -> (&'static [f64], &'static [f64]) {
static GL64: OnceLock<(Vec<f64>, Vec<f64>)> = OnceLock::new();
let (nodes, weights) = GL64.get_or_init(|| {
let quad = GaussLegendre::new(64.try_into().unwrap());
let nodes: Vec<f64> = quad.nodes().copied().collect();
let weights: Vec<f64> = quad.weights().copied().collect();
(nodes, weights)
});
(nodes.as_slice(), weights.as_slice())
}
pub(crate) fn periodic_map(x: f64, c: f64, d: f64) -> f64 {
if c <= x && x <= d {
x
} else {
let range = d - c;
if range <= 0.0 {
return c;
}
let n = ((x - c) / range).floor();
let n_int = n as i64;
if n_int % 2 == 0 {
x - n * range
} else {
d + n * range - (x - c)
}
}
}
#[derive(Clone, Debug)]
pub struct CalibrationHistory<T> {
pub residuals: DVector<f64>,
pub call_put: DVector<(f64, f64)>,
pub params: T,
pub loss_scores: CalibrationLossScore,
}
impl<T> CalibrationHistory<T> {
pub fn metric_history(history: &[Self], metric: crate::LossMetric) -> Vec<f64> {
history.iter().map(|h| h.loss_scores.get(metric)).collect()
}
}