use std::f64::consts::FRAC_1_PI;
use num_complex::Complex64;
use super::model::HestonStochCorrPricer;
use crate::pricing::cf_quadrature::integrate_to_convergence;
use crate::traits::TimeExt;
impl HestonStochCorrPricer {
pub fn price_call_carr_madan(&self) -> f64 {
let tau = self.tau_or_from_dates();
let alpha = 1.25_f64;
let log_k = self.k.ln();
let r = self.r;
let integrand = |u: f64| -> f64 {
if u.abs() < 1e-14 {
return 0.0;
}
let u_shifted = Complex64::new(u, -(alpha + 1.0));
let phi = self.char_func_complex(u_shifted);
let disc_phi = (-r * tau).exp() * phi;
let denom = Complex64::new(alpha * alpha + alpha - u * u, (2.0 * alpha + 1.0) * u);
let val = (-Complex64::i() * u * log_k).exp() * disc_phi / denom;
val.re
};
let integral = integrate_to_convergence(integrand, 0.0, 1e-8);
let call = (-alpha * log_k).exp() * FRAC_1_PI * integral;
call.max(0.0)
}
pub fn price_call_at_strike(&self, k: f64) -> f64 {
let mut p = self.clone();
p.k = k;
p.price_call_carr_madan()
}
}
#[derive(Clone, Copy, Debug)]
pub struct HscmModel {
pub v0: f64,
pub kappa_v: f64,
pub theta_v: f64,
pub sigma_v: f64,
pub rho0: f64,
pub kappa_r: f64,
pub mu_r: f64,
pub sigma_r: f64,
pub rho2: f64,
}
impl crate::traits::ModelPricer for HscmModel {
fn price_call(&self, s: f64, k: f64, r: f64, q: f64, tau: f64) -> f64 {
let mut pricer = HestonStochCorrPricer::new(
s,
r,
k,
self.v0,
self.kappa_v,
self.theta_v,
self.sigma_v,
self.rho0,
self.kappa_r,
self.mu_r,
self.sigma_r,
self.rho2,
tau,
);
pricer.q = Some(q);
pricer.price_call_carr_madan()
}
}