use std::{
fmt::{Display, Formatter, Result as FmtResult},
ops::Neg,
};
use num_traits::ConstZero;
#[derive(Debug, Clone, Eq, PartialEq, Copy)]
#[repr(i8)]
pub enum OptionType {
Call = 1,
Put = -1,
}
impl Neg for OptionType {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
match self {
OptionType::Call => OptionType::Put,
OptionType::Put => OptionType::Call,
}
}
}
impl Display for OptionType {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
OptionType::Call => write!(f, "Call"),
OptionType::Put => write!(f, "Put"),
}
}
}
macro_rules! impl_option_type {
($type:ty) => {
impl From<OptionType> for $type {
#[inline]
fn from(val: OptionType) -> Self {
<$type>::from(val as i8)
}
}
impl From<$type> for OptionType {
#[inline]
fn from(value: $type) -> Self {
if value >= <$type>::ZERO {
OptionType::Call
} else {
OptionType::Put
}
}
}
impl std::ops::Mul<OptionType> for $type {
type Output = $type;
#[inline]
fn mul(self, rhs: OptionType) -> Self::Output {
match rhs {
OptionType::Call => self,
OptionType::Put => -self,
}
}
}
impl std::ops::Mul<$type> for OptionType {
type Output = $type;
#[inline]
fn mul(self, rhs: $type) -> Self::Output {
match self {
OptionType::Call => rhs,
OptionType::Put => -rhs,
}
}
}
};
}
impl_option_type!(f32);
impl_option_type!(f64);
impl_option_type!(i8);
impl_option_type!(i16);
impl_option_type!(i32);
impl_option_type!(i64);
impl_option_type!(i128);
impl_option_type!(isize);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OptionStyle {
European,
American,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct VanillaOption {
pub style: OptionStyle,
pub kind: OptionType,
pub strike: f64,
pub maturity: f64,
}
impl VanillaOption {
#[inline]
pub fn new(style: OptionStyle, kind: OptionType, strike: f64, maturity: f64) -> Self {
Self {
style,
kind,
strike,
maturity,
}
}
#[inline]
pub fn european_call(strike: f64, maturity: f64) -> Self {
Self::new(OptionStyle::European, OptionType::Call, strike, maturity)
}
#[inline]
pub fn european_put(strike: f64, maturity: f64) -> Self {
Self::new(OptionStyle::European, OptionType::Put, strike, maturity)
}
#[inline]
pub fn american_call(strike: f64, maturity: f64) -> Self {
Self::new(OptionStyle::American, OptionType::Call, strike, maturity)
}
#[inline]
pub fn american_put(strike: f64, maturity: f64) -> Self {
Self::new(OptionStyle::American, OptionType::Put, strike, maturity)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct MarketData {
pub spot: f64,
pub rate: f64,
pub dividend_yield: f64,
}
impl MarketData {
#[inline]
pub fn new(spot: f64, rate: f64, dividend_yield: f64) -> Self {
Self {
spot,
rate,
dividend_yield,
}
}
}
#[allow(clippy::struct_excessive_bools)]
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct Greeks {
pub delta: f64,
pub gamma: f64,
pub theta: f64,
pub vega: f64,
pub rho: f64,
pub epsilon: f64,
pub lambda: f64,
pub vanna: f64,
pub charm: f64,
pub veta: f64,
pub vomma: f64,
pub speed: f64,
pub zomma: f64,
pub color: f64,
pub ultima: f64,
pub dual_delta: f64,
pub dual_gamma: f64,
}