Revision notes for FIN312
Mathematics and Programming for FinTech
Study Unit 5 – Options/Black-Scholes/Volatility
What is option?
- Contract between 2 parties. Either party can buy or sell their asset at a
future time “T” but at an agreed price “K”
- The agreed price to buy/sell is denote as “K” which
buy = exercise price
sell = strike price
- “T”= Maturity (when it will be mature to exercise/strike)
For options, we can choose to:
- Buy = Call option ; Sell = Put option
- Exercise the option ONLY@maturity = European ;
- Anytime prior to maturity = American
- Cash or physically settled the option
Call options (Mean I buy)
Contract to buy an asset at a strike price “K” at time “T”
When will it be valuable (ie, making profit) = Bullish
- When the strike price@maturity is more than strike price@purchase
- Able to exercise the option and buy the asset at price “K” and sell to the
market at “ST”. Profit = ST – K
- But if ST < K, meaning the current asset price is higher than what I buy,
then this option is expired worthless
- Payoff of a call option C = MAX(ST – K,0)
Put options (Mean I sell)
Contract to sell an asset at a strike price “K” at time “T”
When will it be valuable (ie, making profit) = Bearish
- When the strike price@purchase is more than strike price@maturity
- Able to exercise the option and buy the stock from the market “ST” at
price “K” . Profit = ST – K
- But if ST > K, meaning the current asset price is higher than what I sell,
then this option is expired worthless
- Payoff of a put option P = MAX(K - ST,0)
In summary (Call vs Put option)
Call option
Every option is a contract that has come with a maturity date at a future date.
I buy stock A on 01-01-20 and it will mature 30-06-20 (6mth later)
2 scenarios that will happen on 30-06-20
1. I buy stock A at $4 (call option) and sell at $10@maturity = $6 gain ($10-
$4)
2. I buy stock A at $4 (call option) and upon maturity, current stock value
market = $2, stock A will expire on 30-06-20 worthless/loss $2 ($4 - $2)
Put option
I will selling the option that I have purchase earlier.
Stock E is purchased on 01-01-20 and will expire on 30-06-20 @$4
2 scenarios that will happen on 30-06-20
1. I sell stock B (put option) @$10 and gain $6 ($10-$4)
2. I want to sell stock B at $10 but current market value of stock B is $2,
this option will expire on 30-06-20 worthless/loss $2 ($4 - $2)
Long vs short option
- long an option = buy an option (call option)
- short an option = sell an option (put option)
ATM, OTM, ITM
- ATM = “At The Money" = Current asset price is at the strike price
- OTM = “Out The Money" = Option is not making money
- ITM = “In The Money" ) = Option is making money
Vanilla vs Exotic
- Call and Put options are vanilla options
- Exotic options have payoff profiles that can be customised
How to draw a payoff diagram@Expiry
1. Depending factor = Stock price@maturity
2. We use P = MAX(K - ST,0) or P = MAX(ST - K,0) to plot the diagram
Bullish vs Bearish stock market
When a market is bullish:
- Stock price will increase = We “BUY STOCK” = But it might be more
expensive when buying during bullish market
- “BUY a CALL” = Cheaper than buying stock but we allow leverage
- “SELL a PUT” = Earn the fixed premium from selling the option
When a market is bearish:
- Stock price will fall = We “SELL STOCK” to minimise the risk
- “BUY a PUT”
- “SHORT a CALL” = Earn the fixed premium
Covered call VS Protecting Profits
Covered call = Long a stock + short a call
Protective Put: Long stock + Long a put option
Case examples (Covered call)
Use Case (1) Options are used by bullish investors to boast returns from
holdings of stocks.
Use Case (2) A fund can use a covered call strategy to sell stocks at a
target price K
Case examples (Protecting profits)
Use Case: A trader can use a put option to lock in his profits if he is unwilling to
sell his stocks because there is growth potential.
Cash flows from covered call
- If ST < K, the option expired worthless and the stock was not sold.
However, a cash flow from the sale of the option would have enriched
the option seller.
- If ST > K, the stock was sold and the gains from the stock are realised.
Cash flows from protecting profits
- If ST < K, the loss from the stock is compensated by the put option going
ITM.
- If ST > K, the put option expired worthless.
Case example
How do we use Juyter to present our answers?
We need to install the package first
pip install alpha_vantage pandas
We need to import all the different package to run the codes
import numpy as np
import pandas as pd
import scipy.stats as sp
from alpha_vantage.timeseries import TimeSeries
import matplotlib.pyplot as plt
s0 = 100
k1 = 90 # long, 1 unit
k2 = 100 # short, 2 units
k3 = 110 # long, 1 unit
x = pd.DataFrame(range(0, 201), columns=['future prc'])
x['a'] = (x['future prc'] - k1).clip(lower=0) # max(0, St-k1)
x['b'] = (x['future prc'] - k2).clip(lower=0)
x['c'] = (x['future prc'] - k3).clip(lower=0)
x['payoff'] = x['a'] -2*x['b'] + x['c']
print(x)
Output from Juyter
Explanation for the code used:
x = pd.DataFrame(range(0, 201), columns=['future prc'])
We use “x” for output
pd = pandas
pd.DataFrame () function which is defined in the Pandas module automatically
(by default) address in the form of row indices and column indices is generated
to represent each data element/point in the DataFrame that is called index
We range from 0 to 201 because, note that k2 has 2 units call option and 1 unit
= $100
However, we add +1 because the last number will not be captured so the
range will be 200 + 1 = 201
So in this way, the range will be in rows of “0” to “200” and the first column
will be named “future prc”
x['a'] = (x['future prc'] - k1).clip(lower=0) # max(0, St-k1)
We create ‘a’ as the next column as we are using the payoff option
P = MAX(ST - K,0)
We use .clip to limit a value which is in this case, we limit to anything lower
than 0 is equal to 0
x['payoff'] = x['a'] -2*x['b'] + x['c']
When we want to know the payoff, we multiply by the unit accordingly.
print(x)
This denote that we are printing output “x”
Once we have the data, we can plot the payoff diagram
plt.style.use('ggplot')
fig = plt.figure(figsize=[12,6])
ax = plt.subplot(1,1,1)
ax.plot(x['future prc'], x['payoff'])
ax.set_xlabel('future stock price')
ax.set_title('investor\'s payoff')
# importing all the necessary packages
import numpy as np
import matplotlib.pyplot as plt
# using the style for the plot
plt.style.use('ggplot')
# create a figure
plt.figure()
# adding first subplot
plt.subplot(1,1,1)
Link for creating multiple subplot :
https://matplotlib.org/stable/gallery/subplots_axes_and_figures/
subplots_demo.html
Link for labelling axis:
https://www.geeksforgeeks.org/matplotlib-axes-axes-plot-in-python/
# Labelling the x-axis as “Future Stock Price”
ax.set_xlabel('future stock price')
#Labelling the title of the diagram
ax.set_title('investor\'s payoff') = we need “\” because it will not be able to
capture ‘s as a string of label to be reflected
Option premium
Option premium is also known as the option’s price or the fair value of the
option.
What is fair value?
Fair value is also the present value of the expected option payoff under risk
natural measure
Lecture note unit 5, slide 13, equation 1
Q
where E (.) define the expected value of the payoff, PV denotes the present
valuing and V is the cash flow received.
But to price a call option, equation as followed:
Lecture note unit 5, slide 13, equation 2
where MAX(ST – K, 0) is the cash flow happening at the option's expiry.
However, we usually discount for option as exp(-rT) so that the actual option
will be closer to present value.
Discounted formula for call option premium
Lecture note 5, slide 14 equation 3
where r is the riskfree rate
Discounted formula for put option premium
where r is the riskfree rate
What is Black-Scholes
Lecture note 5, slide 15 equation 4
where c and p are the option price of a call and put option respectively. S0 is
the current asset price, σ is the volatility of asset's returns, r is the risk free
rate. K and T are the strike price and the maturity of the option respectively.
d1 and d2 are defined as
N(x) is defined as the cumulative distribution of the standard Normal
distribution.
Case example 1 for Black-Scholes
UDF do not need to print the output hence we just have to rewrite the code in
Juyter so that it can be define accordingly.
UDF = User-defined function for call options as below:
def call_option(s,k,r,vol,T):
d1 = (np.log(s/k) + (r + 0.5*vol*vol)*T)/vol/np.sqrt(T)
d2 = d1 - vol*np.sqrt(T)
return (s*sp.norm.cdf(d1) - k*np.exp(-r*T)*sp.norm.cdf(d2))
UDF = User-defined function for put options as below:
def put_option(s,k,r,vol,T):
d1 = (np.log(s/k) + (r + 0.5*vol*vol)*T)/vol/np.sqrt(T)
d2 = d1 - vol*np.sqrt(T)
return (k*np.exp(-r*T)*sp.norm.cdf(-d2)-s*sp.norm.cdf(-d1))
Case example 2 for Black-Scholes
S0 is the current asset price, σ is the volatility of asset's returns, r is the risk free
rate. K and T are the strike price and the maturity of the option respectively
s0 = 100
K = 100
vol = 0.39
rf = 0.013
T = 91/365
def call_option(s,k,r,vol,T):
d1 = (np.log(s/k) + (r + 0.5*vol*vol)*T)/vol/np.sqrt(T)
d2 = d1 - vol*np.sqrt(T)
return (s*sp.norm.cdf(d1) - k*np.exp(-r*T)*sp.norm.cdf(d2))
prc = call_option(s0,K,rf,vol,T)
print(f'it will cost ${prc:.2f} to buy a call option.')
initial_w = 100
final_stock_prc = 80
# buy stock
units_stock = initial_w/s0
final_wealth_stock = units_stock*final_stock_prc
ret_stock = final_wealth_stock/initial_w-1
print(f'the return from holding stock is {ret_stock*100:.2f}% and the final wealth is ${final_wealth_stock:.1f}.')
# buy options
units_option = initial_w/prc
final_wealth_option = units_option*max(0, final_stock_prc - K)
ret_option = final_wealth_option/initial_w-1
print(f'the return from holding option is {ret_option*100:.2f}% and the final wealth is $
{final_wealth_option:.1f}.')
Volatility Risk Premium
Option prices are affected by volatility level. We can use the Black-Scholes
equation to obtain the volatility implied by the market - Implied volatility.
The realised volatility is lower than the implied volatility and hence, you can
make money by selling options - volatility risk premium.
Case example 1
monthly_vol = 0.05 # realised vol
spot = 100
moneyness = 1 # ratio of strike/spot
vrp = 0.01
T = 1/12 # years
implied_vol = (1+ vrp)*monthly_vol
N
def= put_option(s,k,r,vol,T):
120 #months
wealth = 1*(1+ret)**N
d1 = (np.log(s/k) + (r + 0.5*vol*vol)*T)/vol/np.sqrt(T)
print('The cumulative return from VRP in {} months in {:.2f}%.'.format(N, 100*wealth))
d2 = d1 - vol*np.sqrt(T)
return (k*np.exp(-r*T)*sp.norm.cdf(-d2)-s*sp.norm.cdf(-d1))
prc = put_option(spot,spot*moneyness,0.0,implied_vol*np.sqrt(12),T)
true_val = put_option(spot,spot*moneyness,0.0,monthly_vol*np.sqrt(12),T)
ret = (prc - true_val)/prc
Case example 2
api_key = 'NTIQNX09BLY3UYW6'
ts = TimeSeries(key = api_key, output_format='pandas')
data, meta_data = ts.get_daily('SPY', outputsize='full')
data = data.sort_index()
spy = data[['4. close']]
spy = spy.rename(columns={'4. close':'spy'})
spy['r'] = spy/spy.shift()-1
# we assume there are 22 trading days in a month
spy['vol'] = spy['r'].rolling(22).std(ddof=1) # vol is std of return
spy = spy.loc[spy.index.values[::22], ['spy', 'vol']] # resampling at every 22 days
spy['vol'] = np.sqrt(22)*spy['vol']
print(spy)
Case example 3
fig = plt.figure(figsize=[12,6])
ax = plt.subplot(1,2,1)
ax.plot(spy.index, spy['spy'])
ax.set_title('SPY price level')
ax = plt.subplot(1,2,2)
ax.plot(spy.index, spy['vol'], label='monthly vol')
ax.plot(spy.index, spy['vol'].expanding().mean(), label='running mean of vol')
ax.legend()
ax.set_title('SPY vol level')
plt.tight_layout()
# in the event of a market crash, realised vol = 5 x monthly_vol
new_true_val = put_option(spot,spot*moneyness,0.0,monthly_vol*np.sqrt(12)*5,T)
ret_2 = (prc - new_true_val)/prc
print('Option price:${:.2f}, new true value: ${:.2f}, return: {:.2f}%'.format(prc, new_true_val,
100*ret_2))
# 10 years of return is entirely wiped out by 1 market event