implied_vol/builder/
price_bachelier.rs1use crate::{SpecialFn, lets_be_rational};
2use bon::Builder;
3
4#[derive(Builder)]
5#[builder(const, derive(Clone, Debug),
6finish_fn(name = build_unchecked,
7doc{
8})
15)]
16pub struct PriceBachelier {
17 forward: f64,
18 strike: f64,
19 volatility: f64,
20 expiry: f64,
21 is_call: bool,
22}
23
24impl<S: price_bachelier_builder::IsComplete> PriceBachelierBuilder<S> {
25 pub const fn build(self) -> Option<PriceBachelier> {
26 let price_bachelier = self.build_unchecked();
27 if !price_bachelier.forward.is_finite() {
28 return None;
29 }
30 if !price_bachelier.strike.is_finite() {
31 return None;
32 }
33 if !(price_bachelier.volatility >= 0.0) {
34 return None;
35 }
36 if !(price_bachelier.expiry >= 0.0) {
37 return None;
38 }
39 Some(price_bachelier)
40 }
41}
42
43impl PriceBachelier {
44 #[must_use]
45 #[inline(always)]
46 pub fn calculate<SpFn: SpecialFn>(&self) -> f64 {
47 if self.is_call {
48 lets_be_rational::bachelier_impl::bachelier_price::<true>(
49 self.forward,
50 self.strike,
51 self.volatility,
52 self.expiry,
53 )
54 } else {
55 lets_be_rational::bachelier_impl::bachelier_price::<false>(
56 self.forward,
57 self.strike,
58 self.volatility,
59 self.expiry,
60 )
61 }
62 }
63}