#![allow(dead_code)]
use std::panic::{catch_unwind, AssertUnwindSafe};
use rustyqlib::core::traits::Instrument;
use rustyqlib::equity::montecarlo;
use rustyqlib::equity::utils::Engine;
use rustyqlib::equity::vanilla_option::EquityOption;
#[allow(dead_code)]
pub mod plot3d;
pub fn title(text: &str) {
println!("\n{}", "=".repeat(96));
println!(" {text}");
println!("{}", "=".repeat(96));
}
pub fn section(text: &str) {
println!("\n-- {text} {}", "-".repeat(90usize.saturating_sub(text.len())));
}
pub fn table_header() {
println!(
"{:<34} {:>12} {:>10} {:>10} {:>9} {:>9} {:>9} {:>9}",
"method", "npv", "delta", "gamma", "vega", "theta", "rho", "std err"
);
println!("{}", "-".repeat(96));
}
#[allow(dead_code)]
pub fn row_or_refusal(
label: &str,
built: Result<EquityOption, rustyqlib::RustyQLibError>,
) {
match built {
Ok(option) => row(label, &option),
Err(e) => note(&format!("{label}: refused at build() — {e}")),
}
}
pub fn row(label: &str, option: &EquityOption) {
let hook = std::panic::take_hook();
std::panic::set_hook(Box::new(|_| {}));
let result = catch_unwind(AssertUnwindSafe(|| {
let std_err = if option.engine.kind() == Engine::MonteCarlo {
Some(montecarlo::npv_with_stats(option).std_err)
} else {
None
};
let result = option.price().unwrap();
(result.pv, result.greeks.delta, result.greeks.gamma, result.greeks.vega, result.greeks.theta,
option.rho(), std_err)
}));
std::panic::set_hook(hook);
match result {
Ok((pv, delta, gamma, vega, theta, rho, std_err)) => {
let se = match std_err {
Some(v) => format!("{v:.5}"),
None => "-".to_string(),
};
println!(
"{label:<34} {pv:>12.6} {delta:>10.5} {gamma:>10.5} {vega:>9.3} {theta:>9.3} {rho:>9.3} {se:>9}"
);
}
Err(payload) => {
let msg = payload
.downcast_ref::<String>()
.cloned()
.or_else(|| payload.downcast_ref::<&str>().map(|s| s.to_string()))
.unwrap_or_else(|| "panicked".to_string());
let short: String = msg.split(';').next().unwrap_or(&msg).chars().take(52).collect();
println!("{label:<34} {:>12} ({short})", "unsupported");
}
}
}
pub fn check(label: &str, value: f64, expected: f64, tol: f64) {
let diff = (value - expected).abs();
let mark = if diff < tol { "OK " } else { "BAD" };
println!(" [{mark}] {label:<52} {value:>13.6} expected {expected:>13.6} diff {diff:.2e}");
}
pub fn note(text: &str) {
println!(" . {text}");
}