forward_start_option/common/
mod.rs1use std::panic::{catch_unwind, AssertUnwindSafe};
9
10use rustyqlib::core::traits::Instrument;
11use rustyqlib::equity::montecarlo;
12use rustyqlib::equity::utils::Engine;
13use rustyqlib::equity::vanila_option::EquityOption;
14
15#[allow(dead_code)]
17pub mod plot3d;
18
19pub fn title(text: &str) {
20 println!("\n{}", "=".repeat(96));
21 println!(" {text}");
22 println!("{}", "=".repeat(96));
23}
24
25pub fn section(text: &str) {
26 println!("\n-- {text} {}", "-".repeat(90usize.saturating_sub(text.len())));
27}
28
29pub fn table_header() {
30 println!(
31 "{:<34} {:>12} {:>10} {:>10} {:>9} {:>9} {:>9} {:>9}",
32 "method", "npv", "delta", "gamma", "vega", "theta", "rho", "std err"
33 );
34 println!("{}", "-".repeat(96));
35}
36
37pub fn row(label: &str, option: &EquityOption) {
40 let hook = std::panic::take_hook();
42 std::panic::set_hook(Box::new(|_| {}));
43 let result = catch_unwind(AssertUnwindSafe(|| {
44 let (pv, std_err) = if option.engine == Engine::MonteCarlo {
45 let s = montecarlo::npv_with_stats(option);
46 (s.pv, Some(s.std_err))
47 } else {
48 (option.npv(), None)
49 };
50 (pv, option.delta(), option.gamma(), option.vega(), option.theta(), option.rho(), std_err)
51 }));
52 std::panic::set_hook(hook);
53 match result {
54 Ok((pv, delta, gamma, vega, theta, rho, std_err)) => {
55 let se = match std_err {
56 Some(v) => format!("{v:.5}"),
57 None => "-".to_string(),
58 };
59 println!(
60 "{label:<34} {pv:>12.6} {delta:>10.5} {gamma:>10.5} {vega:>9.3} {theta:>9.3} {rho:>9.3} {se:>9}"
61 );
62 }
63 Err(payload) => {
64 let msg = payload
65 .downcast_ref::<String>()
66 .cloned()
67 .or_else(|| payload.downcast_ref::<&str>().map(|s| s.to_string()))
68 .unwrap_or_else(|| "panicked".to_string());
69 let short: String = msg.split(';').next().unwrap_or(&msg).chars().take(52).collect();
70 println!("{label:<34} {:>12} ({short})", "unsupported");
71 }
72 }
73}
74
75pub fn check(label: &str, value: f64, expected: f64, tol: f64) {
77 let diff = (value - expected).abs();
78 let mark = if diff < tol { "OK " } else { "BAD" };
79 println!(" [{mark}] {label:<52} {value:>13.6} expected {expected:>13.6} diff {diff:.2e}");
80}
81
82pub fn note(text: &str) {
83 println!(" . {text}");
84}