I've amended a code for the Black-Scholes formula for European pricing options found here at the bottom of the page and fixed the math functions accordingly. Unlike the code on the website, mine has run successfully giving me the correct mathematical solution.
- Would this be the method in solving this issue?
- Could the coding be improved?
import scipy.stats as sp
import numpy as np
class BsmModel:
def __init__(self, option_type, price, strike, interest_rate, expiry, volatility, dividend_yield=0):
self.s = price # Underlying asset price
self.k = strike # Option strike K
self.r = interest_rate # Continuous risk fee rate
self.q = dividend_yield # Dividend continuous rate
self.T = expiry # time to expiry (year)
self.sigma = volatility # Underlying volatility
self.type = option_type # option type "p" put option "c" call option
def n(self, d):
# cumulative probability distribution function of standard normal distribution
return sp.norm.cdf(d)
def dn(self, d):
# the first order derivative of n(d)
return sp.norm.pdf(d)
def d1(self):
return (math.log(self.s / self.k) + (self.r - self.q + self.sigma ** 2 * 0.5) * self.T) / (self.sigma * math.sqrt(self.T))
def d2(self):
return (math.log(self.s / self.k) + (self.r - self.q - self.sigma ** 2 * 0.5) * self.T) / (self.sigma * math.sqrt(self.T))
def bsm_price(self):
d1 = self.d1()
d2 = d1 - self.sigma * math.sqrt(self.T)
if self.type == 'c':
return math.exp(-self.r*self.T) * (self.s * math.exp((self.r - self.q)*self.T) * self.n(d1) - self.k * self.n(d2))
if self.type == 'p':
return math.exp(-self.r*self.T) * (self.k * self.n(-d2) - (self.s * math.exp((self.r - self.q)*self.T) * self.n(-d1)))
print ("option type can only be c or p")
a = BsmModel('c', 42, 35, 0.1, 90.0/365, 0.2)
a.bsm_price()
## 7.8778518797804225
The error I received using the code from the website was:
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-25-0e7b66f29cf6> in <module>
35
36 a = BsmModel('c', 42, 35, 0.1, 90.0/365, 0.2)
---> 37 a.bsm_price()
<ipython-input-25-0e7b66f29cf6> in bsm_price(self)
26
27 def bsm_price(self):
---> 28 d1 = self.d1()
29 d2 = d1 - self.sigma * sqrt(self.T)
30 if self.type == 'c':
<ipython-input-25-0e7b66f29cf6> in d1(self)
20
21 def d1(self):
---> 22 return (log(self.s / self.k) + (self.r - self.q + self.sigma ** 2 * 0.5) * self.T) / (self.sigma * sqrt(self.T))
23
24 def d2(self):
NameError: name 'log' is not defined