Skip to content

Instantly share code, notes, and snippets.

@ycytai
Last active May 5, 2024 04:54
Show Gist options
  • Save ycytai/dfa19662a2df5528d4660ef2fba2ee67 to your computer and use it in GitHub Desktop.
Save ycytai/dfa19662a2df5528d4660ef2fba2ee67 to your computer and use it in GitHub Desktop.
from enum import Enum
import numpy as np
import scipy.stats as st
class OptionType(str, Enum):
call = 'Call'
put = 'Put'
class Option:
def __init__(
self, option_type: OptionType, s:float, k:float, v:float,
t:float, r:float, q:float | None = None
) -> None:
"""
Parameters:
option_type: option type, use 'call' or 'put'
s: spot price
k: strike price
r: interest rate
v: volatility
t: maturity(year)
q: yield rate
"""
self.spot = s
self.strike = k
self.volatility = v
self.maturity = t
self.rate = r
self.yield_rate = q
self.option_type = option_type
@property
def delta(self) -> float:
if self.option_type == OptionType.call:
return st.norm.cdf(self.d1)
if self.option_type == OptionType.put:
return st.norm.cdf(self.d1) - 1
@property
def gamma(self) -> float:
return st.norm.pdf(self.d1) / (self.spot * self.volatility * (self.maturity**0.5))
@property
def theta(self):
if self.option_type == OptionType.call:
return - (self.spot * st.norm.pdf(self.d1) * self.volatility) / (2 * self.maturity**0.5) \
- (self.rate * self.strike * np.exp(-self.rate * self.maturity) * st.norm.cdf(self.d2))
if self.option_type == OptionType.put:
return - (self.spot * st.norm.pdf(self.d1) * self.volatility) / (2 * self.maturity**0.5) \
+ (self.rate * self.strike * np.exp(-self.rate * self.maturity) * st.norm.cdf(-self.d2))
@property
def vega(self) -> float:
return self.spot * self.maturity**0.5 * st.norm.pdf(self.d1)
@property
def rho(self) -> float:
if self.option_type == OptionType.call:
return self.strike * self.maturity * np.exp(-self.rate * self.maturity) * st.norm.cdf(self.d2)
if self.option_type == OptionType.put:
return -self.strike * self.maturity * np.exp(-self.rate * self.maturity) * st.norm.cdf(-self.d2)
@property
def d1(self) -> float:
var = self.rate - self.yield_rate if self.yield_rate else self.rate
return (np.log(self.spot / self.strike) + ((var + self.volatility**2 / 2) * self.maturity)) \
/ (self.volatility * self.maturity**0.5)
@property
def d2(self) -> float:
return self.d1 - (self.volatility*self.maturity**0.5)
def change_spot_price_to(self, price:float):
self.spot = price
@property
def greeks(self) -> dict[str, float]:
return {
'delta': self.delta,
'gamma': self.gamma,
'theta': self.theta,
'vega': self.vega,
'rho': self.rho
}
@property
def summary(self) -> str:
return f'{self.strike} {self.option_type.value}'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment