(Finance 02) Black-Scholes and Brownian movement option pricing with Web Scraping

In this video we cover

  • Using and testing Black-Scholes model for option pricing
  • Geometric Brownian Movement for option pricing
  • Web Scraping for extraction of data required for option pricing

We will also see how to determine daily and annual volatility, risk free rate and cumulative distribution function. We develop functions that we can use later for finding gaps in option trading markets and use them to make profit.

I will write each function codes after the video.

# Black-Scholes model for pricing options

import datetime, numpy as np

def norm_cdf(x):
    s = 0
    x0 = 100
    n = 1000
    for i in range(1,n+1):
        y = -x0 + (x + x0) / n * i
        s = s + np.exp(-(y**2)/2) * (x + x0) / n
    return s/np.sqrt(2*np.pi)

S = 172.57
K = 130
vol = 0.4634
r = 0.0475
dt = ((datetime.date(2023,9,15)-datetime.date(2023,5,12)).days+1)/365
d1 = (np.log(S/K) + ((r + (vol**2) / 2) * dt)) / (vol * np.sqrt(dt))
d2 = d1 - vol * np.sqrt(dt)

cdf_d1 = norm_cdf(d1)
cdf_d2 = norm_cdf(d2)

call_price = S * cdf_d1 - K * np.exp(-r * dt) * cdf_d2
print(call_price)
# Volatility and Geometric Brownian Motion

import numpy as np
from yfinance import download as get_data
import datetime as dt
import matplotlib.pyplot as plt
import time

start_date = dt.datetime.now() - dt.timedelta(days = 365*2)
end_date = dt.datetime.now()
data = get_data("SPY", start_date, end_date)
data = data["Adj Close"]

returns = data.pct_change()
mean_return = returns.mean()
std_dev = returns.std()
print(mean_return, " , ", std_dev*np.sqrt(252))

last_close = data[len(data)-1]
parice_paths=[]
for i in range(2000):
    parice_paths.append([last_close])
    y = np.random.normal(mean_return,std_dev,252)
    for j in range(252):
        parice_paths[i].append((1 + y[j]) * parice_paths[i][j])
    plt.plot(parice_paths[i])
    plt.pause(0.005)

print(last_close * ((1 + mean_return) ** 252), sum([line[-1] for line in parice_paths])/len(parice_paths))
plt.show()
# Scrape 1-year treasury bill (risk free rate) from ycharts.com

import requests

def risk_free_rate():
    my_headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36" }
    html_code = requests.get("https://ycharts.com/indicators/1_year_treasury_rate", headers = my_headers).text

    html_code = html_code.split('<td class="text-right">')

    for i in range(1,11):
        r_text = html_code[i]
        r_index = r_text.find("%")
        print(r_text[r_index-4:r_index])

risk_free_rate()
# Scrape BHP option price details from asx.com.au

import requests,datetime,json

def get_options():
    for d in range(0,31):
        the_day = datetime.date.today() + datetime.timedelta(days = d)
        if (the_day.weekday() == 3 and the_day.day > 14 and the_day.day < 22):
            closest_option_date = the_day
            break

    html_code = requests.get("https://asx.api.markitdigital.com/asx-research/1.0/derivatives/equity/BHP/options/expiry-groups?callsPuts=calls&showOpenInterestOnly=false&showTheoreticalPricesOnly=false&styles=european&includeLepoToressOptions=false&expiryDates[]="
     + str(closest_option_date)).text

    options_data = json.loads(html_code)
    options = options_data["data"]["items"][0]["exerciseGroups"]

    option_list = []
    for option in options:
        if option["call"]["volume"] > 0:
            option_list.append([option["priceExercise"],option["call"]["priceLast"]])

    return closest_option_date, option_list

print(get_options())

Leave a Reply

Your email address will not be published. Required fields are marked *