Skip to main content

EquityOption

Struct EquityOption 

Source
pub struct EquityOption {
    pub base: EquityOptionBase,
    pub payoff: Box<dyn Payoff>,
    pub engine: Engine,
    pub mc: MonteCarloConfig,
    pub fd: FdConfig,
    pub heston: Option<HestonParams>,
}

Fields§

§base: EquityOptionBase§payoff: Box<dyn Payoff>§engine: Engine§mc: MonteCarloConfig

Monte Carlo settings (paths, time steps, scheme, sampler, seed). mc.model (GBM vs local vol) also applies to the FD engine.

§fd: FdConfig

Finite difference grid settings; only consulted when engine is Engine::FiniteDifference.

§heston: Option<HestonParams>

Heston parameters; required when the model is Heston.

Implementations§

Source§

impl EquityOption

Source

pub fn time_to_maturity(&self) -> f64

Source§

impl EquityOption

Source§

impl EquityOption

Source

pub fn get_premium_at_risk(&self) -> f64

Source

pub fn try_imp_vol(&self, option_price: f64) -> Result<f64, String>

Implied Black-Scholes volatility for option_price (safeguarded Newton with arbitrage-bound checks); does not modify the option.

Source

pub fn imp_vol(&mut self, option_price: f64) -> f64

Implied vol for option_price; leaves the option holding a flat surface at the solved vol. Panics on arbitrage-violating prices — use try_imp_vol to handle those gracefully.

Source

pub fn get_imp_vol(&mut self) -> f64

Source§

impl EquityOption

Greeks per engine: Monte Carlo uses bump-and-reprice with common random numbers (supporting American via Longstaff-Schwartz repricing); the FD engine reads delta/gamma/theta off its own grid (so American and barrier sensitivities are engine-consistent) with vega/rho by re-solving; the remaining engines use the analytic Black-Scholes closed forms.

Source

pub fn delta(&self) -> f64

Examples found in repository?
examples/common/mod.rs (line 50)
39pub fn row(label: &str, option: &EquityOption) {
40    // keep the table readable: the caught panic is reported in the row
41    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}
More examples
Hide additional examples
examples/vanilla_option.rs (line 197)
168fn greek_surfaces() {
169    use common::plot3d::{greek_surface, linspace, save_surface_html, Labels};
170
171    common::section("Greek surfaces over (moneyness, maturity) -> runs/vanilla_option/*.html");
172
173    // x = moneyness S/K (0.4 .. 1.6, i.e. spot 40..160 for K=100);
174    // y = maturity 0.05..2.0y (short-dated ATM is where the structure lives)
175    let moneyness = linspace(0.6, 1.4, 72);
176    let mats = linspace(0.05, 1.0, 56);
177
178    // a call priced analytically at (moneyness, maturity); spot = m * K
179    let greek = |select: fn(&EquityOption) -> f64| {
180        move |m: f64, years: f64| -> f64 {
181            let option = EquityOptionBuilder::new()
182                .spot(m * STRIKE)
183                .strike(STRIKE)
184                .flat_vol(VOL)
185                .flat_rate(RATE)
186                .dividend_yield(DIV)
187                .valuation_date(asof())
188                .years_to_maturity(years)
189                .vanilla(PutOrCall::Call)
190                .engine(Engine::BlackScholes)
191                .build();
192            select(&option)
193        }
194    };
195
196    for (name, file, select) in [
197        ("Delta", "delta", (|o: &EquityOption| o.delta()) as fn(&EquityOption) -> f64),
198        ("Gamma", "gamma", |o: &EquityOption| o.gamma()),
199        ("Vega", "vega", |o: &EquityOption| o.vega()),
200        ("Theta", "theta", |o: &EquityOption| o.theta()),
201    ] {
202        let surface = greek_surface(&moneyness, &mats, greek(select));
203        save_surface_html(
204            &surface,
205            &format!("runs/vanilla_option/{file}_surface.html"),
206            &Labels {
207                title: &format!("Vanilla call {name} (K=100, sigma=30%, r=5%, q=2%)"),
208                x: "moneyness (S/K)",
209                y: "maturity (y)",
210                z: name,
211            },
212        );
213    }
214    common::note("open the HTML in a browser to rotate, zoom and hover the surfaces");
215}
examples/forward_start_option.rs (line 135)
39fn main() {
40    common::title("FORWARD-START OPTION — S=100, strike = 1.0 x S(0.5y), T=1y, sigma=30%");
41
42    common::section("Black-Scholes: analytic vs Monte Carlo");
43    common::table_header();
44    common::row(
45        "Analytical (Rubinstein)",
46        &base()
47            .forward_start(PutOrCall::Call, 1.0, START)
48            .engine(Engine::BlackScholes)
49            .build(),
50    );
51    common::row(
52        "Monte Carlo (GBM)",
53        &base()
54            .forward_start(PutOrCall::Call, 1.0, START)
55            .engine(Engine::MonteCarlo)
56            .paths(100_000)
57            .build(),
58    );
59    common::row(
60        "Finite difference (unsupported)",
61        &base()
62            .forward_start(PutOrCall::Call, 1.0, START)
63            .engine(Engine::FiniteDifference)
64            .build(),
65    );
66
67    common::section("Forward smile: Heston vs Black-Scholes");
68    common::table_header();
69    let bs = base()
70        .forward_start(PutOrCall::Call, 1.0, START)
71        .engine(Engine::BlackScholes)
72        .build()
73        .npv();
74    common::row(
75        "Heston vol-of-vol=0.001 (-> BS)",
76        &base()
77            .forward_start(PutOrCall::Call, 1.0, START)
78            .engine(Engine::MonteCarlo)
79            .heston(heston_params(1e-3, 0.0))
80            .paths(50_000)
81            .build(),
82    );
83    for (vov, rho) in [(0.2, -0.7), (0.4, -0.7), (0.6, -0.7), (0.4, 0.0)] {
84        common::row(
85            &format!("Heston vol-of-vol={vov}, rho={rho}"),
86            &base()
87                .forward_start(PutOrCall::Call, 1.0, START)
88                .engine(Engine::MonteCarlo)
89                .heston(heston_params(vov, rho))
90                .paths(50_000)
91                .build(),
92        );
93    }
94    common::note(&format!("Black-Scholes reference: {bs:.6}"));
95    common::note("the gap is the forward-smile effect — the reason to price these on a stoch-vol model");
96
97    common::section("Strike fraction sweep (analytic)");
98    common::table_header();
99    for k in [0.9, 0.95, 1.0, 1.05, 1.1] {
100        common::row(
101            &format!("strike = {k} x S(t_f), call"),
102            &base().forward_start(PutOrCall::Call, k, START).engine(Engine::BlackScholes).build(),
103        );
104    }
105
106    common::section("Fixing date sweep (analytic, ATM)");
107    common::table_header();
108    for start in [0.1, 0.25, 0.5, 0.75, 0.9] {
109        common::row(
110            &format!("fixing at {:.0}% of life", start * 100.0),
111            &base().forward_start(PutOrCall::Call, 1.0, start).engine(Engine::BlackScholes).build(),
112        );
113    }
114    common::note("later fixing leaves less time to expiry, so the option is worth less");
115
116    common::section("Identities");
117    common::check(
118        "immediate fixing -> vanilla struck at S0",
119        forward_start_price(SPOT, 1.0, RATE, DIV, VOL, 1e-6, 1.0, PutOrCall::Call),
120        base()
121            .strike(SPOT)
122            .vanilla(PutOrCall::Call)
123            .engine(Engine::BlackScholes)
124            .build()
125            .npv(),
126        1e-3,
127    );
128    let p100 = forward_start_price(100.0, 1.0, RATE, DIV, VOL, 0.5, 1.0, PutOrCall::Call);
129    let p200 = forward_start_price(200.0, 1.0, RATE, DIV, VOL, 0.5, 1.0, PutOrCall::Call);
130    common::check("homogeneity: price(2S) = 2 price(S)", p200, 2.0 * p100, 1e-12);
131    let fs = base()
132        .forward_start(PutOrCall::Call, 1.0, START)
133        .engine(Engine::BlackScholes)
134        .build();
135    common::check("delta = price / spot (homogeneity)", fs.delta(), fs.npv() / SPOT, 1e-6);
136    println!();
137}
examples/binary_option.rs (line 105)
33fn main() {
34    common::title("BINARY OPTION — S=100 K=100 sigma=30% r=5% q=2% T=1y");
35
36    for (name, binary_type, cash) in [
37        ("cash-or-nothing (1 unit)", BinaryType::CashOrNothing, CASH),
38        ("asset-or-nothing", BinaryType::AssetOrNothing, 0.0),
39    ] {
40        for pc in [PutOrCall::Call, PutOrCall::Put] {
41            common::section(&format!("{name} {pc:?}"));
42            common::table_header();
43            for (label, engine) in [
44                ("Analytical (closed form)", Engine::BlackScholes),
45                ("Binomial (1000 steps)", Engine::Binomial),
46                ("Finite difference", Engine::FiniteDifference),
47                ("Monte Carlo (Sobol, 100k)", Engine::MonteCarlo),
48            ] {
49                common::row(label, &base().binary(pc, binary_type, cash).engine(engine).build());
50            }
51        }
52    }
53    common::note("the tree oscillates on digitals: the strike falls between terminal nodes");
54
55    common::section("Cash amount scales linearly");
56    common::table_header();
57    for cash in [1.0, 100.0, 1000.0] {
58        common::row(
59            &format!("cash-or-nothing call, cash={cash}"),
60            &base()
61                .binary(PutOrCall::Call, BinaryType::CashOrNothing, cash)
62                .engine(Engine::BlackScholes)
63                .build(),
64        );
65    }
66
67    common::section("Identities");
68    let cash_call = base()
69        .binary(PutOrCall::Call, BinaryType::CashOrNothing, CASH)
70        .engine(Engine::BlackScholes)
71        .build();
72    let cash_put = base()
73        .binary(PutOrCall::Put, BinaryType::CashOrNothing, CASH)
74        .engine(Engine::BlackScholes)
75        .build();
76    common::check(
77        "cash call + cash put = e^{-rT}",
78        cash_call.npv() + cash_put.npv(),
79        (-RATE * 1.0_f64).exp(),
80        1e-12,
81    );
82
83    let asset_call = base()
84        .binary(PutOrCall::Call, BinaryType::AssetOrNothing, 0.0)
85        .engine(Engine::BlackScholes)
86        .build();
87    let asset_put = base()
88        .binary(PutOrCall::Put, BinaryType::AssetOrNothing, 0.0)
89        .engine(Engine::BlackScholes)
90        .build();
91    common::check(
92        "asset call + asset put = S e^{-qT}",
93        asset_call.npv() + asset_put.npv(),
94        SPOT * (-DIV * 1.0_f64).exp(),
95        1e-10,
96    );
97
98    common::section("Replication: asset digital = vanilla call + K cash digitals");
99    let vanilla = base().vanilla(PutOrCall::Call).engine(Engine::BlackScholes).build();
100    let k_cash = base()
101        .binary(PutOrCall::Call, BinaryType::CashOrNothing, STRIKE)
102        .engine(Engine::BlackScholes)
103        .build();
104    common::check("npv", asset_call.npv(), vanilla.npv() + k_cash.npv(), 1e-10);
105    common::check("delta", asset_call.delta(), vanilla.delta() + k_cash.delta(), 1e-10);
106    common::check("gamma", asset_call.gamma(), vanilla.gamma() + k_cash.gamma(), 1e-10);
107    common::check("vega", asset_call.vega(), vanilla.vega() + k_cash.vega(), 1e-10);
108    common::check("theta", asset_call.theta(), vanilla.theta() + k_cash.theta(), 1e-10);
109    common::check("rho", asset_call.rho(), vanilla.rho() + k_cash.rho(), 1e-10);
110    common::note("both sides are implemented independently, so this is a real cross-check");
111
112    common::section("Digital risk: delta and gamma explode near the strike at expiry");
113    common::table_header();
114    for years in [1.0, 0.25, 0.05, 0.01] {
115        common::row(
116            &format!("cash-or-nothing call, T={years}y"),
117            &base()
118                .years_to_maturity(years)
119                .binary(PutOrCall::Call, BinaryType::CashOrNothing, CASH)
120                .engine(Engine::BlackScholes)
121                .build(),
122        );
123    }
124
125    digital_greek_surfaces();
126    println!();
127}
128
129/// The digital's Greeks are the standout case for visualizing (lack of)
130/// smoothness: as maturity shrinks the delta spikes into a tall bump at the
131/// strike and gamma flips sign right across it. Saved as self-contained
132/// interactive HTML to `runs/binary_option/`.
133fn digital_greek_surfaces() {
134    use common::plot3d::{greek_surface, linspace, save_surface_html, Labels};
135    use rustyqlib::equity::vanila_option::EquityOption;
136
137    common::section("Digital Greek surfaces over (moneyness, maturity) -> runs/binary_option/*.html");
138
139    // tighter moneyness band and shorter maturities: that is where the
140    // digital's delta/gamma structure lives
141    let moneyness = linspace(0.8, 1.2, 80);
142    let mats = linspace(0.02, 1.0, 60);
143
144    let greek = |select: fn(&EquityOption) -> f64| {
145        move |m: f64, years: f64| -> f64 {
146            let option = base()
147                .spot(m * STRIKE)
148                .years_to_maturity(years)
149                .binary(PutOrCall::Call, BinaryType::CashOrNothing, CASH)
150                .engine(Engine::BlackScholes)
151                .build();
152            select(&option)
153        }
154    };
155
156    for (name, file, select) in [
157        ("Delta", "delta", (|o: &EquityOption| o.delta()) as fn(&EquityOption) -> f64),
158        ("Gamma", "gamma", |o: &EquityOption| o.gamma()),
159    ] {
160        let surface = greek_surface(&moneyness, &mats, greek(select));
161        save_surface_html(
162            &surface,
163            &format!("runs/binary_option/{file}_surface.html"),
164            &Labels {
165                title: &format!("Cash digital call {name} (K=100) — note the near-expiry spike"),
166                x: "moneyness (S/K)",
167                y: "maturity (y)",
168                z: name,
169            },
170        );
171    }
172    common::note("contrast with the vanilla surfaces: the digital is far from smooth near the strike");
173}
Source

pub fn gamma(&self) -> f64

Examples found in repository?
examples/common/mod.rs (line 50)
39pub fn row(label: &str, option: &EquityOption) {
40    // keep the table readable: the caught panic is reported in the row
41    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}
More examples
Hide additional examples
examples/vanilla_option.rs (line 198)
168fn greek_surfaces() {
169    use common::plot3d::{greek_surface, linspace, save_surface_html, Labels};
170
171    common::section("Greek surfaces over (moneyness, maturity) -> runs/vanilla_option/*.html");
172
173    // x = moneyness S/K (0.4 .. 1.6, i.e. spot 40..160 for K=100);
174    // y = maturity 0.05..2.0y (short-dated ATM is where the structure lives)
175    let moneyness = linspace(0.6, 1.4, 72);
176    let mats = linspace(0.05, 1.0, 56);
177
178    // a call priced analytically at (moneyness, maturity); spot = m * K
179    let greek = |select: fn(&EquityOption) -> f64| {
180        move |m: f64, years: f64| -> f64 {
181            let option = EquityOptionBuilder::new()
182                .spot(m * STRIKE)
183                .strike(STRIKE)
184                .flat_vol(VOL)
185                .flat_rate(RATE)
186                .dividend_yield(DIV)
187                .valuation_date(asof())
188                .years_to_maturity(years)
189                .vanilla(PutOrCall::Call)
190                .engine(Engine::BlackScholes)
191                .build();
192            select(&option)
193        }
194    };
195
196    for (name, file, select) in [
197        ("Delta", "delta", (|o: &EquityOption| o.delta()) as fn(&EquityOption) -> f64),
198        ("Gamma", "gamma", |o: &EquityOption| o.gamma()),
199        ("Vega", "vega", |o: &EquityOption| o.vega()),
200        ("Theta", "theta", |o: &EquityOption| o.theta()),
201    ] {
202        let surface = greek_surface(&moneyness, &mats, greek(select));
203        save_surface_html(
204            &surface,
205            &format!("runs/vanilla_option/{file}_surface.html"),
206            &Labels {
207                title: &format!("Vanilla call {name} (K=100, sigma=30%, r=5%, q=2%)"),
208                x: "moneyness (S/K)",
209                y: "maturity (y)",
210                z: name,
211            },
212        );
213    }
214    common::note("open the HTML in a browser to rotate, zoom and hover the surfaces");
215}
examples/binary_option.rs (line 106)
33fn main() {
34    common::title("BINARY OPTION — S=100 K=100 sigma=30% r=5% q=2% T=1y");
35
36    for (name, binary_type, cash) in [
37        ("cash-or-nothing (1 unit)", BinaryType::CashOrNothing, CASH),
38        ("asset-or-nothing", BinaryType::AssetOrNothing, 0.0),
39    ] {
40        for pc in [PutOrCall::Call, PutOrCall::Put] {
41            common::section(&format!("{name} {pc:?}"));
42            common::table_header();
43            for (label, engine) in [
44                ("Analytical (closed form)", Engine::BlackScholes),
45                ("Binomial (1000 steps)", Engine::Binomial),
46                ("Finite difference", Engine::FiniteDifference),
47                ("Monte Carlo (Sobol, 100k)", Engine::MonteCarlo),
48            ] {
49                common::row(label, &base().binary(pc, binary_type, cash).engine(engine).build());
50            }
51        }
52    }
53    common::note("the tree oscillates on digitals: the strike falls between terminal nodes");
54
55    common::section("Cash amount scales linearly");
56    common::table_header();
57    for cash in [1.0, 100.0, 1000.0] {
58        common::row(
59            &format!("cash-or-nothing call, cash={cash}"),
60            &base()
61                .binary(PutOrCall::Call, BinaryType::CashOrNothing, cash)
62                .engine(Engine::BlackScholes)
63                .build(),
64        );
65    }
66
67    common::section("Identities");
68    let cash_call = base()
69        .binary(PutOrCall::Call, BinaryType::CashOrNothing, CASH)
70        .engine(Engine::BlackScholes)
71        .build();
72    let cash_put = base()
73        .binary(PutOrCall::Put, BinaryType::CashOrNothing, CASH)
74        .engine(Engine::BlackScholes)
75        .build();
76    common::check(
77        "cash call + cash put = e^{-rT}",
78        cash_call.npv() + cash_put.npv(),
79        (-RATE * 1.0_f64).exp(),
80        1e-12,
81    );
82
83    let asset_call = base()
84        .binary(PutOrCall::Call, BinaryType::AssetOrNothing, 0.0)
85        .engine(Engine::BlackScholes)
86        .build();
87    let asset_put = base()
88        .binary(PutOrCall::Put, BinaryType::AssetOrNothing, 0.0)
89        .engine(Engine::BlackScholes)
90        .build();
91    common::check(
92        "asset call + asset put = S e^{-qT}",
93        asset_call.npv() + asset_put.npv(),
94        SPOT * (-DIV * 1.0_f64).exp(),
95        1e-10,
96    );
97
98    common::section("Replication: asset digital = vanilla call + K cash digitals");
99    let vanilla = base().vanilla(PutOrCall::Call).engine(Engine::BlackScholes).build();
100    let k_cash = base()
101        .binary(PutOrCall::Call, BinaryType::CashOrNothing, STRIKE)
102        .engine(Engine::BlackScholes)
103        .build();
104    common::check("npv", asset_call.npv(), vanilla.npv() + k_cash.npv(), 1e-10);
105    common::check("delta", asset_call.delta(), vanilla.delta() + k_cash.delta(), 1e-10);
106    common::check("gamma", asset_call.gamma(), vanilla.gamma() + k_cash.gamma(), 1e-10);
107    common::check("vega", asset_call.vega(), vanilla.vega() + k_cash.vega(), 1e-10);
108    common::check("theta", asset_call.theta(), vanilla.theta() + k_cash.theta(), 1e-10);
109    common::check("rho", asset_call.rho(), vanilla.rho() + k_cash.rho(), 1e-10);
110    common::note("both sides are implemented independently, so this is a real cross-check");
111
112    common::section("Digital risk: delta and gamma explode near the strike at expiry");
113    common::table_header();
114    for years in [1.0, 0.25, 0.05, 0.01] {
115        common::row(
116            &format!("cash-or-nothing call, T={years}y"),
117            &base()
118                .years_to_maturity(years)
119                .binary(PutOrCall::Call, BinaryType::CashOrNothing, CASH)
120                .engine(Engine::BlackScholes)
121                .build(),
122        );
123    }
124
125    digital_greek_surfaces();
126    println!();
127}
128
129/// The digital's Greeks are the standout case for visualizing (lack of)
130/// smoothness: as maturity shrinks the delta spikes into a tall bump at the
131/// strike and gamma flips sign right across it. Saved as self-contained
132/// interactive HTML to `runs/binary_option/`.
133fn digital_greek_surfaces() {
134    use common::plot3d::{greek_surface, linspace, save_surface_html, Labels};
135    use rustyqlib::equity::vanila_option::EquityOption;
136
137    common::section("Digital Greek surfaces over (moneyness, maturity) -> runs/binary_option/*.html");
138
139    // tighter moneyness band and shorter maturities: that is where the
140    // digital's delta/gamma structure lives
141    let moneyness = linspace(0.8, 1.2, 80);
142    let mats = linspace(0.02, 1.0, 60);
143
144    let greek = |select: fn(&EquityOption) -> f64| {
145        move |m: f64, years: f64| -> f64 {
146            let option = base()
147                .spot(m * STRIKE)
148                .years_to_maturity(years)
149                .binary(PutOrCall::Call, BinaryType::CashOrNothing, CASH)
150                .engine(Engine::BlackScholes)
151                .build();
152            select(&option)
153        }
154    };
155
156    for (name, file, select) in [
157        ("Delta", "delta", (|o: &EquityOption| o.delta()) as fn(&EquityOption) -> f64),
158        ("Gamma", "gamma", |o: &EquityOption| o.gamma()),
159    ] {
160        let surface = greek_surface(&moneyness, &mats, greek(select));
161        save_surface_html(
162            &surface,
163            &format!("runs/binary_option/{file}_surface.html"),
164            &Labels {
165                title: &format!("Cash digital call {name} (K=100) — note the near-expiry spike"),
166                x: "moneyness (S/K)",
167                y: "maturity (y)",
168                z: name,
169            },
170        );
171    }
172    common::note("contrast with the vanilla surfaces: the digital is far from smooth near the strike");
173}
Source

pub fn vega(&self) -> f64

Examples found in repository?
examples/common/mod.rs (line 50)
39pub fn row(label: &str, option: &EquityOption) {
40    // keep the table readable: the caught panic is reported in the row
41    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}
More examples
Hide additional examples
examples/vanilla_option.rs (line 199)
168fn greek_surfaces() {
169    use common::plot3d::{greek_surface, linspace, save_surface_html, Labels};
170
171    common::section("Greek surfaces over (moneyness, maturity) -> runs/vanilla_option/*.html");
172
173    // x = moneyness S/K (0.4 .. 1.6, i.e. spot 40..160 for K=100);
174    // y = maturity 0.05..2.0y (short-dated ATM is where the structure lives)
175    let moneyness = linspace(0.6, 1.4, 72);
176    let mats = linspace(0.05, 1.0, 56);
177
178    // a call priced analytically at (moneyness, maturity); spot = m * K
179    let greek = |select: fn(&EquityOption) -> f64| {
180        move |m: f64, years: f64| -> f64 {
181            let option = EquityOptionBuilder::new()
182                .spot(m * STRIKE)
183                .strike(STRIKE)
184                .flat_vol(VOL)
185                .flat_rate(RATE)
186                .dividend_yield(DIV)
187                .valuation_date(asof())
188                .years_to_maturity(years)
189                .vanilla(PutOrCall::Call)
190                .engine(Engine::BlackScholes)
191                .build();
192            select(&option)
193        }
194    };
195
196    for (name, file, select) in [
197        ("Delta", "delta", (|o: &EquityOption| o.delta()) as fn(&EquityOption) -> f64),
198        ("Gamma", "gamma", |o: &EquityOption| o.gamma()),
199        ("Vega", "vega", |o: &EquityOption| o.vega()),
200        ("Theta", "theta", |o: &EquityOption| o.theta()),
201    ] {
202        let surface = greek_surface(&moneyness, &mats, greek(select));
203        save_surface_html(
204            &surface,
205            &format!("runs/vanilla_option/{file}_surface.html"),
206            &Labels {
207                title: &format!("Vanilla call {name} (K=100, sigma=30%, r=5%, q=2%)"),
208                x: "moneyness (S/K)",
209                y: "maturity (y)",
210                z: name,
211            },
212        );
213    }
214    common::note("open the HTML in a browser to rotate, zoom and hover the surfaces");
215}
examples/binary_option.rs (line 107)
33fn main() {
34    common::title("BINARY OPTION — S=100 K=100 sigma=30% r=5% q=2% T=1y");
35
36    for (name, binary_type, cash) in [
37        ("cash-or-nothing (1 unit)", BinaryType::CashOrNothing, CASH),
38        ("asset-or-nothing", BinaryType::AssetOrNothing, 0.0),
39    ] {
40        for pc in [PutOrCall::Call, PutOrCall::Put] {
41            common::section(&format!("{name} {pc:?}"));
42            common::table_header();
43            for (label, engine) in [
44                ("Analytical (closed form)", Engine::BlackScholes),
45                ("Binomial (1000 steps)", Engine::Binomial),
46                ("Finite difference", Engine::FiniteDifference),
47                ("Monte Carlo (Sobol, 100k)", Engine::MonteCarlo),
48            ] {
49                common::row(label, &base().binary(pc, binary_type, cash).engine(engine).build());
50            }
51        }
52    }
53    common::note("the tree oscillates on digitals: the strike falls between terminal nodes");
54
55    common::section("Cash amount scales linearly");
56    common::table_header();
57    for cash in [1.0, 100.0, 1000.0] {
58        common::row(
59            &format!("cash-or-nothing call, cash={cash}"),
60            &base()
61                .binary(PutOrCall::Call, BinaryType::CashOrNothing, cash)
62                .engine(Engine::BlackScholes)
63                .build(),
64        );
65    }
66
67    common::section("Identities");
68    let cash_call = base()
69        .binary(PutOrCall::Call, BinaryType::CashOrNothing, CASH)
70        .engine(Engine::BlackScholes)
71        .build();
72    let cash_put = base()
73        .binary(PutOrCall::Put, BinaryType::CashOrNothing, CASH)
74        .engine(Engine::BlackScholes)
75        .build();
76    common::check(
77        "cash call + cash put = e^{-rT}",
78        cash_call.npv() + cash_put.npv(),
79        (-RATE * 1.0_f64).exp(),
80        1e-12,
81    );
82
83    let asset_call = base()
84        .binary(PutOrCall::Call, BinaryType::AssetOrNothing, 0.0)
85        .engine(Engine::BlackScholes)
86        .build();
87    let asset_put = base()
88        .binary(PutOrCall::Put, BinaryType::AssetOrNothing, 0.0)
89        .engine(Engine::BlackScholes)
90        .build();
91    common::check(
92        "asset call + asset put = S e^{-qT}",
93        asset_call.npv() + asset_put.npv(),
94        SPOT * (-DIV * 1.0_f64).exp(),
95        1e-10,
96    );
97
98    common::section("Replication: asset digital = vanilla call + K cash digitals");
99    let vanilla = base().vanilla(PutOrCall::Call).engine(Engine::BlackScholes).build();
100    let k_cash = base()
101        .binary(PutOrCall::Call, BinaryType::CashOrNothing, STRIKE)
102        .engine(Engine::BlackScholes)
103        .build();
104    common::check("npv", asset_call.npv(), vanilla.npv() + k_cash.npv(), 1e-10);
105    common::check("delta", asset_call.delta(), vanilla.delta() + k_cash.delta(), 1e-10);
106    common::check("gamma", asset_call.gamma(), vanilla.gamma() + k_cash.gamma(), 1e-10);
107    common::check("vega", asset_call.vega(), vanilla.vega() + k_cash.vega(), 1e-10);
108    common::check("theta", asset_call.theta(), vanilla.theta() + k_cash.theta(), 1e-10);
109    common::check("rho", asset_call.rho(), vanilla.rho() + k_cash.rho(), 1e-10);
110    common::note("both sides are implemented independently, so this is a real cross-check");
111
112    common::section("Digital risk: delta and gamma explode near the strike at expiry");
113    common::table_header();
114    for years in [1.0, 0.25, 0.05, 0.01] {
115        common::row(
116            &format!("cash-or-nothing call, T={years}y"),
117            &base()
118                .years_to_maturity(years)
119                .binary(PutOrCall::Call, BinaryType::CashOrNothing, CASH)
120                .engine(Engine::BlackScholes)
121                .build(),
122        );
123    }
124
125    digital_greek_surfaces();
126    println!();
127}
Source

pub fn theta(&self) -> f64

Examples found in repository?
examples/common/mod.rs (line 50)
39pub fn row(label: &str, option: &EquityOption) {
40    // keep the table readable: the caught panic is reported in the row
41    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}
More examples
Hide additional examples
examples/vanilla_option.rs (line 200)
168fn greek_surfaces() {
169    use common::plot3d::{greek_surface, linspace, save_surface_html, Labels};
170
171    common::section("Greek surfaces over (moneyness, maturity) -> runs/vanilla_option/*.html");
172
173    // x = moneyness S/K (0.4 .. 1.6, i.e. spot 40..160 for K=100);
174    // y = maturity 0.05..2.0y (short-dated ATM is where the structure lives)
175    let moneyness = linspace(0.6, 1.4, 72);
176    let mats = linspace(0.05, 1.0, 56);
177
178    // a call priced analytically at (moneyness, maturity); spot = m * K
179    let greek = |select: fn(&EquityOption) -> f64| {
180        move |m: f64, years: f64| -> f64 {
181            let option = EquityOptionBuilder::new()
182                .spot(m * STRIKE)
183                .strike(STRIKE)
184                .flat_vol(VOL)
185                .flat_rate(RATE)
186                .dividend_yield(DIV)
187                .valuation_date(asof())
188                .years_to_maturity(years)
189                .vanilla(PutOrCall::Call)
190                .engine(Engine::BlackScholes)
191                .build();
192            select(&option)
193        }
194    };
195
196    for (name, file, select) in [
197        ("Delta", "delta", (|o: &EquityOption| o.delta()) as fn(&EquityOption) -> f64),
198        ("Gamma", "gamma", |o: &EquityOption| o.gamma()),
199        ("Vega", "vega", |o: &EquityOption| o.vega()),
200        ("Theta", "theta", |o: &EquityOption| o.theta()),
201    ] {
202        let surface = greek_surface(&moneyness, &mats, greek(select));
203        save_surface_html(
204            &surface,
205            &format!("runs/vanilla_option/{file}_surface.html"),
206            &Labels {
207                title: &format!("Vanilla call {name} (K=100, sigma=30%, r=5%, q=2%)"),
208                x: "moneyness (S/K)",
209                y: "maturity (y)",
210                z: name,
211            },
212        );
213    }
214    common::note("open the HTML in a browser to rotate, zoom and hover the surfaces");
215}
examples/binary_option.rs (line 108)
33fn main() {
34    common::title("BINARY OPTION — S=100 K=100 sigma=30% r=5% q=2% T=1y");
35
36    for (name, binary_type, cash) in [
37        ("cash-or-nothing (1 unit)", BinaryType::CashOrNothing, CASH),
38        ("asset-or-nothing", BinaryType::AssetOrNothing, 0.0),
39    ] {
40        for pc in [PutOrCall::Call, PutOrCall::Put] {
41            common::section(&format!("{name} {pc:?}"));
42            common::table_header();
43            for (label, engine) in [
44                ("Analytical (closed form)", Engine::BlackScholes),
45                ("Binomial (1000 steps)", Engine::Binomial),
46                ("Finite difference", Engine::FiniteDifference),
47                ("Monte Carlo (Sobol, 100k)", Engine::MonteCarlo),
48            ] {
49                common::row(label, &base().binary(pc, binary_type, cash).engine(engine).build());
50            }
51        }
52    }
53    common::note("the tree oscillates on digitals: the strike falls between terminal nodes");
54
55    common::section("Cash amount scales linearly");
56    common::table_header();
57    for cash in [1.0, 100.0, 1000.0] {
58        common::row(
59            &format!("cash-or-nothing call, cash={cash}"),
60            &base()
61                .binary(PutOrCall::Call, BinaryType::CashOrNothing, cash)
62                .engine(Engine::BlackScholes)
63                .build(),
64        );
65    }
66
67    common::section("Identities");
68    let cash_call = base()
69        .binary(PutOrCall::Call, BinaryType::CashOrNothing, CASH)
70        .engine(Engine::BlackScholes)
71        .build();
72    let cash_put = base()
73        .binary(PutOrCall::Put, BinaryType::CashOrNothing, CASH)
74        .engine(Engine::BlackScholes)
75        .build();
76    common::check(
77        "cash call + cash put = e^{-rT}",
78        cash_call.npv() + cash_put.npv(),
79        (-RATE * 1.0_f64).exp(),
80        1e-12,
81    );
82
83    let asset_call = base()
84        .binary(PutOrCall::Call, BinaryType::AssetOrNothing, 0.0)
85        .engine(Engine::BlackScholes)
86        .build();
87    let asset_put = base()
88        .binary(PutOrCall::Put, BinaryType::AssetOrNothing, 0.0)
89        .engine(Engine::BlackScholes)
90        .build();
91    common::check(
92        "asset call + asset put = S e^{-qT}",
93        asset_call.npv() + asset_put.npv(),
94        SPOT * (-DIV * 1.0_f64).exp(),
95        1e-10,
96    );
97
98    common::section("Replication: asset digital = vanilla call + K cash digitals");
99    let vanilla = base().vanilla(PutOrCall::Call).engine(Engine::BlackScholes).build();
100    let k_cash = base()
101        .binary(PutOrCall::Call, BinaryType::CashOrNothing, STRIKE)
102        .engine(Engine::BlackScholes)
103        .build();
104    common::check("npv", asset_call.npv(), vanilla.npv() + k_cash.npv(), 1e-10);
105    common::check("delta", asset_call.delta(), vanilla.delta() + k_cash.delta(), 1e-10);
106    common::check("gamma", asset_call.gamma(), vanilla.gamma() + k_cash.gamma(), 1e-10);
107    common::check("vega", asset_call.vega(), vanilla.vega() + k_cash.vega(), 1e-10);
108    common::check("theta", asset_call.theta(), vanilla.theta() + k_cash.theta(), 1e-10);
109    common::check("rho", asset_call.rho(), vanilla.rho() + k_cash.rho(), 1e-10);
110    common::note("both sides are implemented independently, so this is a real cross-check");
111
112    common::section("Digital risk: delta and gamma explode near the strike at expiry");
113    common::table_header();
114    for years in [1.0, 0.25, 0.05, 0.01] {
115        common::row(
116            &format!("cash-or-nothing call, T={years}y"),
117            &base()
118                .years_to_maturity(years)
119                .binary(PutOrCall::Call, BinaryType::CashOrNothing, CASH)
120                .engine(Engine::BlackScholes)
121                .build(),
122        );
123    }
124
125    digital_greek_surfaces();
126    println!();
127}
Source

pub fn rho(&self) -> f64

Examples found in repository?
examples/common/mod.rs (line 50)
39pub fn row(label: &str, option: &EquityOption) {
40    // keep the table readable: the caught panic is reported in the row
41    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}
More examples
Hide additional examples
examples/futures_option.rs (line 72)
38fn main() {
39    common::title("OPTIONS ON FUTURES (Black-76) — F=100 K=100 sigma=30% r=5% T=1y");
40
41    for (name, settlement) in [
42        ("Discounted (standard Black-76)", FuturesSettlement::Discounted),
43        ("Margined (futures-style)", FuturesSettlement::Margined),
44    ] {
45        common::section(name);
46        common::table_header();
47        common::row("call", &futures_option(PutOrCall::Call, settlement));
48        common::row("put", &futures_option(PutOrCall::Put, settlement));
49    }
50    common::note("margined has zero rho (no discounting) and a larger vega/theta");
51
52    common::section("Settlement effect: margined = discounted / e^{-rT}");
53    let disc = futures_option(PutOrCall::Call, FuturesSettlement::Discounted).npv();
54    let marg = futures_option(PutOrCall::Call, FuturesSettlement::Margined).npv();
55    println!("  discounted call {disc:.6}   margined call {marg:.6}   ratio {:.6} (= e^rT {:.6})",
56        marg / disc, (R * T).exp());
57
58    common::section("Identities");
59    let dc = futures_option(PutOrCall::Call, FuturesSettlement::Discounted);
60    let dp = futures_option(PutOrCall::Put, FuturesSettlement::Discounted);
61    common::check(
62        "discounted parity C - P = e^{-rT}(F - K)",
63        dc.npv() - dp.npv(),
64        (-R * T).exp() * (F - K),
65        1e-10,
66    );
67    let mc = futures_option(PutOrCall::Call, FuturesSettlement::Margined);
68    let mp = futures_option(PutOrCall::Put, FuturesSettlement::Margined);
69    common::check("margined parity C - P = F - K", mc.npv() - mp.npv(), F - K, 1e-10);
70    common::check(
71        "margined rho is exactly zero",
72        futures_option(PutOrCall::Call, FuturesSettlement::Margined).rho(),
73        0.0,
74        1e-15,
75    );
76
77    common::section("Black-76 on the forward reproduces spot Black-Scholes");
78    // an option on F = S e^{(r-q)T} equals the equivalent spot option
79    let (s, q) = (100.0, 0.02);
80    let fwd = s * ((R - q) * T).exp();
81    let on_forward = price(fwd, K, R, VOL, T, PutOrCall::Call, FuturesSettlement::Discounted);
82    let spot_bsm = bs_price(s, K, R, q, VOL, T, PutOrCall::Call);
83    common::check("black76(F = S e^{(r-q)T}) = BSM(S, q)", on_forward, spot_bsm, 1e-10);
84
85    common::section("Skew across strikes (discounted put)");
86    common::table_header();
87    for k in [80.0, 90.0, 100.0, 110.0, 120.0] {
88        common::row(
89            &format!("K = {k}"),
90            &EquityOptionBuilder::new()
91                .spot(F)
92                .strike(k)
93                .flat_vol(VOL)
94                .flat_rate(R)
95                .valuation_date(NaiveDate::from_ymd_opt(2026, 1, 1).unwrap())
96                .maturity_date(NaiveDate::from_ymd_opt(2027, 1, 1).unwrap())
97                .vanilla(PutOrCall::Put)
98                .on_future(FuturesSettlement::Discounted)
99                .engine(Engine::BlackScholes)
100                .build(),
101        );
102    }
103    println!();
104}
examples/binary_option.rs (line 109)
33fn main() {
34    common::title("BINARY OPTION — S=100 K=100 sigma=30% r=5% q=2% T=1y");
35
36    for (name, binary_type, cash) in [
37        ("cash-or-nothing (1 unit)", BinaryType::CashOrNothing, CASH),
38        ("asset-or-nothing", BinaryType::AssetOrNothing, 0.0),
39    ] {
40        for pc in [PutOrCall::Call, PutOrCall::Put] {
41            common::section(&format!("{name} {pc:?}"));
42            common::table_header();
43            for (label, engine) in [
44                ("Analytical (closed form)", Engine::BlackScholes),
45                ("Binomial (1000 steps)", Engine::Binomial),
46                ("Finite difference", Engine::FiniteDifference),
47                ("Monte Carlo (Sobol, 100k)", Engine::MonteCarlo),
48            ] {
49                common::row(label, &base().binary(pc, binary_type, cash).engine(engine).build());
50            }
51        }
52    }
53    common::note("the tree oscillates on digitals: the strike falls between terminal nodes");
54
55    common::section("Cash amount scales linearly");
56    common::table_header();
57    for cash in [1.0, 100.0, 1000.0] {
58        common::row(
59            &format!("cash-or-nothing call, cash={cash}"),
60            &base()
61                .binary(PutOrCall::Call, BinaryType::CashOrNothing, cash)
62                .engine(Engine::BlackScholes)
63                .build(),
64        );
65    }
66
67    common::section("Identities");
68    let cash_call = base()
69        .binary(PutOrCall::Call, BinaryType::CashOrNothing, CASH)
70        .engine(Engine::BlackScholes)
71        .build();
72    let cash_put = base()
73        .binary(PutOrCall::Put, BinaryType::CashOrNothing, CASH)
74        .engine(Engine::BlackScholes)
75        .build();
76    common::check(
77        "cash call + cash put = e^{-rT}",
78        cash_call.npv() + cash_put.npv(),
79        (-RATE * 1.0_f64).exp(),
80        1e-12,
81    );
82
83    let asset_call = base()
84        .binary(PutOrCall::Call, BinaryType::AssetOrNothing, 0.0)
85        .engine(Engine::BlackScholes)
86        .build();
87    let asset_put = base()
88        .binary(PutOrCall::Put, BinaryType::AssetOrNothing, 0.0)
89        .engine(Engine::BlackScholes)
90        .build();
91    common::check(
92        "asset call + asset put = S e^{-qT}",
93        asset_call.npv() + asset_put.npv(),
94        SPOT * (-DIV * 1.0_f64).exp(),
95        1e-10,
96    );
97
98    common::section("Replication: asset digital = vanilla call + K cash digitals");
99    let vanilla = base().vanilla(PutOrCall::Call).engine(Engine::BlackScholes).build();
100    let k_cash = base()
101        .binary(PutOrCall::Call, BinaryType::CashOrNothing, STRIKE)
102        .engine(Engine::BlackScholes)
103        .build();
104    common::check("npv", asset_call.npv(), vanilla.npv() + k_cash.npv(), 1e-10);
105    common::check("delta", asset_call.delta(), vanilla.delta() + k_cash.delta(), 1e-10);
106    common::check("gamma", asset_call.gamma(), vanilla.gamma() + k_cash.gamma(), 1e-10);
107    common::check("vega", asset_call.vega(), vanilla.vega() + k_cash.vega(), 1e-10);
108    common::check("theta", asset_call.theta(), vanilla.theta() + k_cash.theta(), 1e-10);
109    common::check("rho", asset_call.rho(), vanilla.rho() + k_cash.rho(), 1e-10);
110    common::note("both sides are implemented independently, so this is a real cross-check");
111
112    common::section("Digital risk: delta and gamma explode near the strike at expiry");
113    common::table_header();
114    for years in [1.0, 0.25, 0.05, 0.01] {
115        common::row(
116            &format!("cash-or-nothing call, T={years}y"),
117            &base()
118                .years_to_maturity(years)
119                .binary(PutOrCall::Call, BinaryType::CashOrNothing, CASH)
120                .engine(Engine::BlackScholes)
121                .build(),
122        );
123    }
124
125    digital_greek_surfaces();
126    println!();
127}

Trait Implementations§

Source§

impl Debug for EquityOption

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Instrument for EquityOption

Source§

fn npv(&self) -> f64

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V