1use std::{
8 fmt::{Display, Formatter, Result as FmtResult},
9 ops::Neg,
10};
11
12use num_traits::ConstZero;
13
14#[derive(Debug, Clone, Eq, PartialEq, Copy)]
16#[repr(i8)]
17pub enum OptionType {
18 Call = 1,
19 Put = -1,
20}
21
22impl Neg for OptionType {
23 type Output = Self;
24
25 #[inline]
26 fn neg(self) -> Self::Output {
27 match self {
28 OptionType::Call => OptionType::Put,
29 OptionType::Put => OptionType::Call,
30 }
31 }
32}
33
34impl Display for OptionType {
35 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
36 match self {
37 OptionType::Call => write!(f, "Call"),
38 OptionType::Put => write!(f, "Put"),
39 }
40 }
41}
42
43macro_rules! impl_option_type {
44 ($type:ty) => {
45 impl From<OptionType> for $type {
46 #[inline]
47 fn from(val: OptionType) -> Self {
48 <$type>::from(val as i8)
49 }
50 }
51
52 impl From<$type> for OptionType {
53 #[inline]
54 fn from(value: $type) -> Self {
55 if value >= <$type>::ZERO {
56 OptionType::Call
57 } else {
58 OptionType::Put
59 }
60 }
61 }
62
63 impl std::ops::Mul<OptionType> for $type {
64 type Output = $type;
65
66 #[inline]
67 fn mul(self, rhs: OptionType) -> Self::Output {
68 match rhs {
69 OptionType::Call => self,
70 OptionType::Put => -self,
71 }
72 }
73 }
74
75 impl std::ops::Mul<$type> for OptionType {
76 type Output = $type;
77
78 #[inline]
79 fn mul(self, rhs: $type) -> Self::Output {
80 match self {
81 OptionType::Call => rhs,
82 OptionType::Put => -rhs,
83 }
84 }
85 }
86 };
87}
88
89impl_option_type!(f32);
90impl_option_type!(f64);
91impl_option_type!(i8);
92impl_option_type!(i16);
93impl_option_type!(i32);
94impl_option_type!(i64);
95impl_option_type!(i128);
96impl_option_type!(isize);
97
98#[derive(Debug, Clone, Copy, PartialEq, Eq)]
100pub enum OptionStyle {
101 European,
103 American,
105}
106
107#[derive(Debug, Clone, Copy, PartialEq)]
112pub struct VanillaOption {
113 pub style: OptionStyle,
115 pub kind: OptionType,
117 pub strike: f64,
119 pub maturity: f64,
125}
126
127impl VanillaOption {
128 #[inline]
130 pub fn new(style: OptionStyle, kind: OptionType, strike: f64, maturity: f64) -> Self {
131 Self {
132 style,
133 kind,
134 strike,
135 maturity,
136 }
137 }
138
139 #[inline]
141 pub fn european_call(strike: f64, maturity: f64) -> Self {
142 Self::new(OptionStyle::European, OptionType::Call, strike, maturity)
143 }
144
145 #[inline]
147 pub fn european_put(strike: f64, maturity: f64) -> Self {
148 Self::new(OptionStyle::European, OptionType::Put, strike, maturity)
149 }
150
151 #[inline]
153 pub fn american_call(strike: f64, maturity: f64) -> Self {
154 Self::new(OptionStyle::American, OptionType::Call, strike, maturity)
155 }
156
157 #[inline]
159 pub fn american_put(strike: f64, maturity: f64) -> Self {
160 Self::new(OptionStyle::American, OptionType::Put, strike, maturity)
161 }
162}
163
164#[derive(Debug, Clone, Copy, PartialEq)]
166pub struct MarketData {
167 pub spot: f64,
169 pub rate: f64,
171 pub dividend_yield: f64,
173}
174
175impl MarketData {
176 #[inline]
178 pub fn new(spot: f64, rate: f64, dividend_yield: f64) -> Self {
179 Self {
180 spot,
181 rate,
182 dividend_yield,
183 }
184 }
185}
186
187#[allow(clippy::struct_excessive_bools)]
193#[derive(Debug, Clone, Copy, Default, PartialEq)]
194pub struct Greeks {
195 pub delta: f64,
196 pub gamma: f64,
197 pub theta: f64,
198 pub vega: f64,
199 pub rho: f64,
200 pub epsilon: f64,
201 pub lambda: f64,
202 pub vanna: f64,
203 pub charm: f64,
204 pub veta: f64,
205 pub vomma: f64,
206 pub speed: f64,
207 pub zomma: f64,
208 pub color: f64,
209 pub ultima: f64,
210 pub dual_delta: f64,
211 pub dual_gamma: f64,
212}