-
Notifications
You must be signed in to change notification settings - Fork 6
Closed
Description
Hi,
I have tried to run the calibration code. Some runs return negative values for v0, theta, kappa, signa, which should all be strictly positive.
Attached is a code sample. It runs the calibration over several v0, and keep the minimul mape loss.
Also, if you uncomment the set_initial_params line, you will see that sigma and rho will have NaN assigned values.
Am I doing something wrong? I run the calibration over call options with 1 months maturity with same spot, and different strikes.
use stochastic_rs::quant::calibration::heston::{HestonCalibrator, HestonParams};
use stochastic_rs::quant::OptionType;
use std::cmp::Ordering;
use ndarray::Array1;
#[tokio::main]
async fn main() {
let r = 0.04;
let q = 0.06;
let t = 0.083;
let strikes_ls: Vec<f64> = vec![5220.318, 6090.371, 6960.424, 7830.477, 8265.5035, 8483.01675, 8700.53, 8918.04325, 9135.5565, 9570.583, 10440.636, 11310.689];
let spots_ls: Vec<f64> = vec![8700.53, 8700.53, 8700.53, 8700.53, 8700.53, 8700.53, 8700.53, 8700.53, 8700.53, 8700.53, 8700.53, 8700.53];
let vol_ls: Vec<f64> = vec![0.3669, 0.3082, 0.2218, 0.1799, 0.1393, 0.1156, 0.1019, 0.0923, 0.0915, 0.1086, 0.1237, 0.136];
let markets_ls: Vec<f64> = vec![3499.564, 2632.74, 1765.933, 901.846, 479.055, 279.313, 118.848, 28.79, 4.23, 0.143, 1.799e-5, 1.259e-9];
let v0 = Array1::linspace(1e-5, 2.0, 5);
for v in v0.iter() {
let mut calibrator = HestonCalibrator::new(
HestonParams {
v0: *v,
theta: 6.47e-5,
rho: -1.98e-3,
kappa: 6.57e-3,
sigma: 5.09e-4,
},
markets_ls.clone().into(), spots_ls.clone().into(), strikes_ls.clone().into(),
t, r, Some(q), OptionType::Call,
);
// Uncomment to witness NaN Sigma/Rho
// calibrator.set_initial_params(spots_ls.clone().into(), vol_ls.clone().into(), r);
let result = calibrator.calibrate();
let result_unwrap = result.unwrap();
let minimum_loss = result_unwrap.iter().min_by(|a, b| {
a.loss_scores.mape.partial_cmp(&b.loss_scores.mape).unwrap_or(Ordering::Equal)
});
println!("{:?}", minimum_loss.clone().unwrap().loss_scores.mape);
println!("{:?}", minimum_loss.clone().unwrap().params);
}
}
The markets_ls array was computed with:
let markets_ls: Vec<f64> = data.iter().map(|x| {
let bs = BSMPricer::new(x.spot, x.vol, x.strike, r, None, None, Some(q), Some(t), None, None, OptionType::Call, BSMCoc::BSM1973);
let (c, _) = bs.calculate_call_put();
return c;
}).collect()
Metadata
Metadata
Assignees
Labels
No labels