ing-engineer-risk-management/src/options.py

61 lines
2.0 KiB
Python

import pandas as pd
import numpy as np
from scipy.stats import norm
def as_df(option):
"""Creates a dataframe holding the option, and calculates time to maturity"""
df = pd.DataFrame([option])
df["T"] = (df["t1"] - df["t0"]) / np.timedelta64(365, "D")
return df
def black_scholes_option_price_spot(S, K, T, r, sigma, option_type="call"):
"""Calculates option price using Black-Scholes formula with spot price assuming zero dividend"""
sigma_scaled = sigma * np.sqrt(T)
d1 = (np.log(S / K) + (r + 0.5 * sigma**2) * T) / sigma_scaled
d2 = d1 - sigma_scaled
if option_type == "call":
return S * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2)
return K * np.exp(-r * T) * norm.cdf(-d2) - S * norm.cdf(-d1) # put
def black_scholes_option_price_forward(F, K, T, r, sigma, option_type="call"):
"""Calculates option price using Black-Scholes formula with forward price assuming zero dividend"""
sigma_scaled = sigma * np.sqrt(T)
d1 = (np.log(F / K) + (0.5 * sigma**2) * T) / sigma_scaled
d2 = d1 - sigma_scaled
discount = np.exp(-r * T)
if option_type == "call":
return discount * (F * norm.cdf(d1) - K * norm.cdf(d2))
return discount * (K * norm.cdf(-d2) - F * norm.cdf(-d1)) # put
def forward_price(S, T, r):
"""Calculates the forward price assuming zero dividend"""
return S * np.exp(r * T)
def moneyness(strike_price, current_price, option_type="call", threshold=0.005):
"""Calculates if an option is ITM, ATM, or OTM"""
fuzzy_price = threshold * strike_price
if option_type == "put":
if current_price < strike_price - fuzzy_price:
return "ITM"
if current_price > strike_price + fuzzy_price:
return "OTM"
return "ATM"
if option_type == "call":
if current_price > strike_price + fuzzy_price:
return "ITM"
if current_price < strike_price - fuzzy_price:
return "OTM"
return "ATM"
return ""