1
\$\begingroup\$

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
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Would this be the method in solving this issue?

No.

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.

The appropriate remedy is

  1. in the immediate timeframe, create local file which imports log plus author's code so you can use it now
  2. report the issue to the author so in coming weeks we will see an upstream fix

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.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.