From 8af0e14de82cda3ea05446b5945e5fbc5fbf8732 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Jun 2021 21:56:35 +0100 Subject: [PATCH] Black-Scholes and greeks --- .gitignore | 3 ++ opstrat/__init__.py | 3 +- opstrat/blackscholes.py | 103 ++++++++++++++++++++++++++++++++++++++++ requirements.txt | 5 ++ setup.py | 29 +---------- 5 files changed, 114 insertions(+), 29 deletions(-) create mode 100644 opstrat/blackscholes.py create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index 5e968d2..6a41db9 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,9 @@ __pycache__/ # C extensions *.so +#VS Code +.vscode/ + # Distribution / packaging .Python env/ diff --git a/opstrat/__init__.py b/opstrat/__init__.py index c59636e..4e1e81a 100644 --- a/opstrat/__init__.py +++ b/opstrat/__init__.py @@ -1,6 +1,7 @@ -__version__ = "0.1.2" +__version__ = "0.1.3" __author__ = "Abhijith Chandradas" from .basic_multi import * from .basic_single import * from .yf import * +from .blackscholes import black_scholes diff --git a/opstrat/blackscholes.py b/opstrat/blackscholes.py new file mode 100644 index 0000000..bd659e7 --- /dev/null +++ b/opstrat/blackscholes.py @@ -0,0 +1,103 @@ +import numpy as np +from scipy.stats import norm + + +def black_scholes(t=40, r=4.00, v=32.00, K=60, St=62, type='c'): + """ + Parameters: + K : Excercise Price + St: Current Stock Price + v : Volatility in percentage + r : Risk free rate in percentage + t : Time to expiration in days + type: Type of option 'c' for call 'p' for put + default: 'c' + """ + # if type = 'c' or 'C' call option else put option + try: + type=type.lower() + if(type=='c'): + option_type='call' + else: + option_type='put' + except: + option_type='put' + + #Check time + try: + #convert time in days to years + t=t/365 + except: + raise TypeError("Enter numerical value for time") + + #Check risk free rate + try: + #convert percentage to decimal + r=r/100 + except: + raise TypeError("Enter numerical value for risk free rate") + + #Check volatility + try: + #convert percentage to decimal + v=v/100 + except: + raise TypeError("Enter numerical value for volatility") + + #Check Stock Price + try: + St=St+0 + except: + raise TypeError("Enter numerical value for stock price") + + #Check Exercise Price + try: + K=K+0 + except: + raise TypeError("Enter numerical value for Exercise price") + + n1=np.log(St/K) + n2=(r+(np.power(v,2)/2))*t + d=v*(np.sqrt(t)) + + d1=(n1+n2)/d + d2=d1-(v*np.sqrt(t)) + + if type=='c': + N_d1=norm.cdf(d1) + N_d2=norm.cdf(d2) + else: + N_d1=norm.cdf(-d1) + N_d2=norm.cdf(-d2) + + A=(St*N_d1) + B=(K*N_d2*(np.exp(-r*t))) + + if type=='c': + val=A-B + val_int=max(0,St-K) + else: + val=B-A + val_int=max(0,K-St) + val_time=val-val_int + + # Option values in dictionary + value={'option value':val, 'intrinsic value':val_int, 'time value':val_time} + + #CALCULATE OPTION GREEKS + if type=='c': + delta=N_d1 + theta=(-((St*v*np.exp(-np.power(d1,2)/2))/(np.sqrt(8*np.pi*t)))-(N_d2*r*K*np.exp(-r*t)))/365 + rho=t*K*N_d2*np.exp(-r*t)/100 + else: + delta=-N_d1 + theta=(-((St*v*np.exp(-np.power(d1,2)/2))/(np.sqrt(8*np.pi*t)))+(N_d2*r*K*np.exp(-r*t)))/365 + rho=-t*K*N_d2*np.exp(-r*t)/100 + + gamma=(np.exp(-np.power(d1,2)/2))/(St*v*np.sqrt(2*np.pi*t)) + vega=(St*np.sqrt(t)*np.exp(-np.power(d1,2)/2))/(np.sqrt(2*np.pi)*100) + + #Option greeks in Dictionary + greeks={'delta':delta, 'gamma':gamma, 'theta':theta, 'vega':vega, 'rho':rho} + + return {'value':value, 'greeks':greeks} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..88db858 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +matplotlib==3.4.2 +numpy==1.21.0 +pandas==1.2.5 +seaborn==0.11.1 +yfinance==0.1.59 \ No newline at end of file diff --git a/setup.py b/setup.py index 3be2941..391293f 100644 --- a/setup.py +++ b/setup.py @@ -7,34 +7,7 @@ README = readme_file.read() -''' -here = os.path.abspath(os.path.dirname(__file__)) - -with open(os.path.join(here, 'README.md'), encoding='utf-8') as f: - long_description = f.read() -''' - -''' -try: - long_description = pypandoc.convert('README.md', 'rst') - long_description = long_description.replace("\r","") # Do not forget this line -except OSError: - print("Pandoc not found. Long_description conversion failure.") - import io - # pandoc is not installed, fallback to using raw contents - with io.open('README.md', encoding="utf-8") as f: - long_description = f.read() -''' - -''' -try: - import pypandoc - long_description = pypandoc.convert('README.md', 'rst') -except(IOError, ImportError): - long_description = open('README.md').read() -''' - -VERSION = '0.1.2' +VERSION = '0.1.3' DESCRIPTION = 'Option stategy visualizer' #LONG_DESCRIPTION = DESCRIPTION URL = 'https://github.com/abhijith-git/opstrat'