# Fixing math library functions in Black-Scholes options pricing model

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


You seem to reporting that some narrative discourse in a HTML web page omitted an obvious from math import log statement. Which is rather different from code published on github / pypi lacking the import.
1. in the immediate timeframe, create local file which imports log plus author's code so you can use it now
If the author had published this code on e.g. GitHub, the appropriate response would be to politely submit a PR that adds a suggested import.