-
Option Payoffs 4
-
Lecture1.1
-
Lecture1.2
-
Lecture1.3
-
Lecture1.4
-
-
Binomial Model 8
-
Lecture2.1
-
Lecture2.2
-
Lecture2.3
-
Lecture2.4
-
Lecture2.5
-
Lecture2.6
-
Lecture2.7
-
Lecture2.8
-
-
Black-Scholes 6
-
Lecture3.1
-
Lecture3.2
-
Lecture3.3
-
Lecture3.4
-
Lecture3.5
-
Lecture3.6
-
-
Monte Carlo Simulations 3
-
Lecture4.1
-
Lecture4.2
-
Lecture4.3
-
Black-Scholes Call Options
The Black-Scholes model is one of the most famous models in finance which is used to price options. In this course, we are only going to work with some basics to get the main ideas.
The equation for valuation of a call option is as follows:
$$d_{1} = \frac{1}{\sigma\sqrt{t}}[ln(\frac{S}{K})+(r+\frac{\sigma^2}{2})t]$$
$$d_{2} = d_{1}-\sigma\sqrt{t}$$
$$\text{N() = Cummulative Distribution of the standard Normal Distribution}$$
$$\text{S = Current Stock Price}$$
$$\text{K = Call Strike Price}$$
$$\text{r = Risk-free Rate}$$
$$\text{\sigma = Volatility}$$
$$\text{t = Time to Expiration}$$
Before we can replicate this function in python, we need to recall how to find the cummulative distribution of a normal distribution. The following will return it. For example, the value 1.645 corresponds to 95% for the normal distribution.
import pandas as pd
import numpy as np
from scipy.stats import norm
#With norm.cdf, we can get the CDF value given a standard normal
print(norm.cdf(0))
print(norm.cdf(1.645))
Then build the function.
def black_scholes_call(S, X, sigma, rf, t):
d1 = 1/(sigma*t**.5) * (np.log(S/X) + (rf + sigma **2 /2) * t)
d2 = d1 - sigma * t**.5
return norm.cdf(d1) * S - norm.cdf(d2) * X * np.exp(-rf*t)
print(black_scholes_call(50, 55, .08, .03, 1))
The intrinsic value of an option is what the value of an option is if it were to be exercised right now. This will differ from the value of the option which takes into account the chance that in the future the option may actually be in the money. Let’s compute both values for a range of possible stock prices in the current period. When we plot these values, it is obvious that the call value is always greater than the intrinsic value.
import matplotlib.pyplot as plt
#Compute values for the intrinsic value and the black-scholes value
df = pd.DataFrame(list(range(101)), columns = ['Stock Price'])
df['$55 Call Intrinsic Value'] = df['Stock Price'].apply(lambda x: max(x-55, 0))
df['$55 Call Black-Scholes Value'] = df['Stock Price'].apply(lambda x: black_scholes_call(x, 55, .08, .03, 1))
df = df.set_index('Stock Price')
#Plot the value of the option
ax = df.plot(kind='line')
ax.axhline(0, linestyle='--', color='grey')
plt.xlabel("Stock Price")
plt.ylabel("Value")
plt.title("Black Scholes vs. Intrinsic")
plt.show()
ax = df.plot(kind='line')
ax.axhline(0, linestyle='--', color='grey')
plt.xlim([40,70])
plt.xlabel("Stock Price")
plt.ylabel("Value")
plt.title("Black Scholes vs. Intrinsic")
plt.show()
Let’s check out the effects of the different inputs on the call value. For example, with volatility, the higher the parameter is, the more valuable the call option becomes.
#Test the values with different volatilities
df = pd.DataFrame(list(range(101)), columns = ['Stock Price'])
df['$55 Call Intrinstic Value'] = df['Stock Price'].apply(lambda x: max(x-55, 0))
for vol in [.08, .14, .20, .26, .32]:
df[str(int(vol*100))+"% Vol"] = df['Stock Price'].apply(lambda x: black_scholes_call(x, 55, vol, .03, 1))
df = df.set_index('Stock Price')
ax = df.plot(kind='line')
ax.axhline(0, linestyle='--', color='grey')
plt.xlabel("Stock Price")
plt.ylabel("Value")
plt.title("Black-Scholes vs. Volatility")
plt.show()
ax = df.plot(kind='line')
ax.axhline(0, linestyle='--', color='grey')
plt.xlim([40,70])
plt.xlabel("Stock Price")
plt.ylabel("Value")
plt.title("Black-Scholes vs. Volatility")
plt.show()
With the risk-free rate, the value of the option has a positive relationship.
#Test the values with different risk-free rates
df = pd.DataFrame(list(range(101)), columns = ['Stock Price'])
df['$55 Call Intrinstic Value'] = df['Stock Price'].apply(lambda x: max(x-55, 0))
for rf in [.03, .06, .09, .12]:
df[str(int(rf*100))+"% rf"] = df['Stock Price'].apply(lambda x: black_scholes_call(x, 55, .08, rf, 1))
df = df.set_index('Stock Price')
ax = df.plot(kind='line')
ax.axhline(0, linestyle='--', color='grey')
plt.xlabel("Stock Price")
plt.ylabel("Value")
plt.title("Black-Scholes vs. Risk-free Rate")
plt.show()
ax = df.plot(kind='line')
ax.axhline(0, linestyle='--', color='grey')
plt.xlim([40,70])
plt.xlabel("Stock Price")
plt.ylabel("Value")
plt.title("Black-Scholes vs. Risk-free Rate")
plt.show()
Likewise, let’s also test the time to maturity.
#Test the values with different time to maturities
df = pd.DataFrame(list(range(101)), columns = ['Stock Price'])
df['$55 Call Intrinstic Value'] = df['Stock Price'].apply(lambda x: max(x-55, 0))
for t in [.25, 1, 2]:
df["t="+str(t)] = df['Stock Price'].apply(lambda x: black_scholes_call(x, 55, .08, .03, t))
df = df.set_index('Stock Price')
ax = df.plot(kind='line')
ax.axhline(0, linestyle='--', color='grey')
plt.xlabel("Stock Price")
plt.ylabel("Value")
plt.title("Black-Scholes vs. Time to Maturity")
plt.show()
ax = df.plot(kind='line')
ax.axhline(0, linestyle='--', color='grey')
plt.xlim([40,70])
plt.xlabel("Stock Price")
plt.ylabel("Value")
plt.title("Black-Scholes vs. Time to Maturity")
plt.show()