0% found this document useful (0 votes)
6 views

Assignment 2 Computational Part

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

Assignment 2 Computational Part

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

9/10/24, 8:21 p.m.

FM 9587 Rodrigo Gonzalez Assignment 2

FM 9578 Assignment 2- week 3


Unit 1: Computational Finance - week 2

Rodrigo Ernesto Gonzalez Eslava


In [1]: ##Activate the next line in case you don't have yahooquery installed
#pip install yahooquery
import pandas as pd
import numpy as np
import seaborn as sns
import glob
import os
import matplotlib.pyplot as plt
import plotly.express as px
from yahooquery import Ticker
import warnings
import statistics
import math
warnings.filterwarnings('ignore')

pd.set_option('display.max_columns', 500)
%matplotlib inline

data_path = os.getcwd()+'\\'
files = os.listdir(data_path)
data_path
#files

Out[1]: 'C:\\Users\\Usuario\\Documents\\2024\\Western\\Fall\\Mathematics of Financial Opti


ons\\Assignment 2\\'

First let's get the data from yahoo finance

In [10]: name='^GSPTSE'
tickers=[name]
folder= data_path

nosuccess=[]
for ticker in tickers:
print('Working on: ', ticker)
try:
dfprice=Ticker(ticker)
df=dfprice.history(period='5y',interval='1d')
thefile=folder+ticker+'.csv'
df.to_csv(thefile)
print(ticker+' has been saved to: '+folder)
except FileNotFoundError:
nosuccess.append(ticker)

localhost:8985/doc/tree/Documents/2024/Western/Fall/Mathematics of Financial Options/Assignment 2/FM 9587 Rodrigo Gonzalez Assignment 2.ipynb 1/9
9/10/24, 8:21 p.m. FM 9587 Rodrigo Gonzalez Assignment 2

print('Found no price for: ' +ticker)


continue
tickers=[name]
folder= data_path

Working on: ^GSPTSE


^GSPTSE has been saved to: C:\Users\Usuario\Documents\2024\Western\Fall\Mathematics
of Financial Options\Assignment 2\

First view to the data

In [39]: #We're reading the data extracted from yahoo finance


raw_data = pd.read_csv(data_path + name +'.csv')
raw_data.head(100)

Out[39]: symbol date open high low close volume

2019-
0 ^GSPTSE 16347.299805 16409.099609 16308.700195 16379.900391 168389300 1
10-09

2019-
1 ^GSPTSE 16375.400391 16444.400391 16358.099609 16422.699219 186014600 1
10-10

2019-
2 ^GSPTSE 16487.199219 16516.699219 16413.400391 16415.199219 200746600 1
10-11

2019-
3 ^GSPTSE 16433.699219 16510.699219 16417.800781 16418.400391 212333000 1
10-15

2019-
4 ^GSPTSE 16435.099609 16445.599609 16408.699219 16427.199219 165968300 1
10-16

... ... ... ... ... ... ... ...

2020-
95 ^GSPTSE 17140.900391 17304.599609 17029.900391 17041.900391 303632000 1
02-26

2020-
96 ^GSPTSE 16803.400391 16816.199219 16456.800781 16717.400391 232685900 1
02-27

2020-
97 ^GSPTSE 16184.400391 16276.900391 15896.400391 16263.099609 590219300 1
02-28

2020-
98 ^GSPTSE 16325.000000 16566.699219 16166.299805 16553.300781 374721500 1
03-02

2020-
99 ^GSPTSE 16674.900391 16798.199219 16378.299805 16423.599609 393127900 1
03-03

100 rows × 8 columns

In [40]: raw_data.isnull().values.any()

Out[40]: False

localhost:8985/doc/tree/Documents/2024/Western/Fall/Mathematics of Financial Options/Assignment 2/FM 9587 Rodrigo Gonzalez Assignment 2.ipynb 2/9
9/10/24, 8:21 p.m. FM 9587 Rodrigo Gonzalez Assignment 2

In [41]: pd.isnull(raw_data).count()

Out[41]: symbol 1256


date 1256
open 1256
high 1256
low 1256
close 1256
volume 1256
adjclose 1256
dtype: int64

In [42]: raw_data.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1256 entries, 0 to 1255
Data columns (total 8 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 symbol 1256 non-null object
1 date 1256 non-null object
2 open 1256 non-null float64
3 high 1256 non-null float64
4 low 1256 non-null float64
5 close 1256 non-null float64
6 volume 1256 non-null int64
7 adjclose 1256 non-null float64
dtypes: float64(5), int64(1), object(2)
memory usage: 78.6+ KB

As we can see there are no missing values on the original data

Next, we will extract the "adjclose" column

In [51]: data=pd.DataFrame(raw_data[['date','adjclose']])
data.columns=['date', 'adjclose']
data.drop(1255, inplace= True)
data

localhost:8985/doc/tree/Documents/2024/Western/Fall/Mathematics of Financial Options/Assignment 2/FM 9587 Rodrigo Gonzalez Assignment 2.ipynb 3/9
9/10/24, 8:21 p.m. FM 9587 Rodrigo Gonzalez Assignment 2

Out[51]: date adjclose

0 2019-10-09 16379.900391

1 2019-10-10 16422.699219

2 2019-10-11 16415.199219

3 2019-10-15 16418.400391

4 2019-10-16 16427.199219

... ... ...

1250 2024-10-02 24001.599609

1251 2024-10-03 23968.500000

1252 2024-10-04 24162.800781

1253 2024-10-07 24102.699219

1254 2024-10-08 24072.500000

1255 rows × 2 columns

In [53]: # Calculate the weekly 3-day Moving Average


data['3d avg'] = data['adjclose'].rolling(3).mean()
data.fillna(value=data['3d avg'][2], inplace=True)
data['weekly 3d avg'] = data['3d avg'].rolling(5).mean()
data.fillna(value=data['weekly 3d avg'][4], inplace=True)

data

localhost:8985/doc/tree/Documents/2024/Western/Fall/Mathematics of Financial Options/Assignment 2/FM 9587 Rodrigo Gonzalez Assignment 2.ipynb 4/9
9/10/24, 8:21 p.m. FM 9587 Rodrigo Gonzalez Assignment 2

Out[53]: date adjclose 3d avg weekly 3d avg

0 2019-10-09 16379.900391 16405.932943 16411.366276

1 2019-10-10 16422.699219 16405.932943 16411.366276

2 2019-10-11 16415.199219 16405.932943 16411.366276

3 2019-10-15 16418.400391 16418.766276 16411.366276

4 2019-10-16 16427.199219 16420.266276 16411.366276

... ... ... ... ...

1250 2024-10-02 24001.599609 24012.000000 23987.107031

1251 2024-10-03 23968.500000 24001.366536 23994.586979

1252 2024-10-04 24162.800781 24044.300130 24010.346875

1253 2024-10-07 24102.699219 24078.000000 24026.546745

1254 2024-10-08 24072.500000 24112.666667 24049.666667

1255 rows × 4 columns

Now let's make a series for the log returns

In [58]: data['log_ret'] = np.log(data['weekly 3d avg']/data['weekly 3d avg'].shift(1))


data.fillna(value=0, inplace=True)
data

Out[58]: date adjclose 3d avg weekly 3d avg log_ret

0 2019-10-09 16379.900391 16405.932943 16411.366276 0.000000

1 2019-10-10 16422.699219 16405.932943 16411.366276 0.000000

2 2019-10-11 16415.199219 16405.932943 16411.366276 0.000000

3 2019-10-15 16418.400391 16418.766276 16411.366276 0.000000

4 2019-10-16 16427.199219 16420.266276 16411.366276 0.000000

... ... ... ... ... ...

1250 2024-10-02 24001.599609 24012.000000 23987.107031 0.000787

1251 2024-10-03 23968.500000 24001.366536 23994.586979 0.000312

1252 2024-10-04 24162.800781 24044.300130 24010.346875 0.000657

1253 2024-10-07 24102.699219 24078.000000 24026.546745 0.000674

1254 2024-10-08 24072.500000 24112.666667 24049.666667 0.000962

1255 rows × 5 columns

localhost:8985/doc/tree/Documents/2024/Western/Fall/Mathematics of Financial Options/Assignment 2/FM 9587 Rodrigo Gonzalez Assignment 2.ipynb 5/9
9/10/24, 8:21 p.m. FM 9587 Rodrigo Gonzalez Assignment 2

Now let´s compute the mean and standar deviation

In [79]: print(f"The mean of the log returns is: {sum(data['log_ret'])/(len(data['log_ret'])

The mean of the log returns is: 0.00030474240515029357

In [68]: print("The standard deviation of the log returns is: " + str(statistics.stdev(data[

The standard deviation of the log returns is: 0.004565571240670406

Now let´s find the annualized values for the mean and standard deviation (drift and volatility)

In [70]: print("The annualized mean of the log returns is: " + str((252/1254)*sum(data['log_

The annualized mean of the log returns is: 0.07679508609787399

In [74]: print("The annualized standard deviation of the log returns is: " + str((math.sqrt

The annualized standard deviation of the log returns is: 0.0724761965745751

Bonus
Ussing the code seen in the python labs

Writing the StockOption base class

In [81]: import math

"""
Stores common attributes of a stock option
"""
class StockOption(object):
def __init__(
self, S0, K, r=0.05, T=1, N=2, pu=0, pd=0,
div=0, sigma=0, is_put=False, is_am=False):
"""
Initialize the stock option base class.
Defaults to European call unless specified.

:param S0: initial stock price


:param K: strike price
:param r: risk-free interest rate
:param T: time to maturity
:param N: number of time steps
:param pu: probability at up state [Su-S0/S0] % increase rate
:param pd: probability at down state [Sd-S0/S0] % decrease rate
:param div: Dividend yield
:param is_put: True for a put option,
False for a call option
:param is_am: True for an American option,
False for a European option
"""
self.S0 = S0
self.K = K

localhost:8985/doc/tree/Documents/2024/Western/Fall/Mathematics of Financial Options/Assignment 2/FM 9587 Rodrigo Gonzalez Assignment 2.ipynb 6/9
9/10/24, 8:21 p.m. FM 9587 Rodrigo Gonzalez Assignment 2

self.r = r
self.T = T
self.N = max(1, N)
self.STs = [] # Declare the stock prices tree

""" Optional parameters used by derived classes """


self.pu, self.pd = pu, pd
self.div = div
self.sigma = sigma
self.is_call = not is_put
self.is_european = not is_am

@property
def dt(self):
""" Single time step, in years """
return self.T/float(self.N)

@property
def df(self):
""" The discount factor """
return math.exp(-(self.r-self.div)*self.dt)

A class for European options using a binomial tree

In [82]: import math


import numpy as np
from decimal import Decimal

"""
Price a European option by the binomial tree model
"""
class BinomialEuropeanOption(StockOption):

def setup_parameters(self):
# Required calculations for the model
self.M = self.N+1 # Number of terminal nodes of tree
self.u = 1+self.pu # Expected value in the up state
self.d = 1-self.pd # Expected value in the down state
self.qu = (math.exp(
(self.r-self.div)*self.dt)-self.d)/(self.u-self.d)
self.qd = 1-self.qu # Probability up is qu and down dq

def init_stock_price_tree(self):
# Initialize terminal price nodes to zeros
self.STs = np.zeros(self.M)

# Calculate expected stock prices for each node


for i in range(self.M):
self.STs[i] = self.S0 * \
(self.u**(self.N-i)) * (self.d**i)

def init_payoffs_tree(self):
"""
Returns the payoffs when the option
expires at terminal nodes

localhost:8985/doc/tree/Documents/2024/Western/Fall/Mathematics of Financial Options/Assignment 2/FM 9587 Rodrigo Gonzalez Assignment 2.ipynb 7/9
9/10/24, 8:21 p.m. FM 9587 Rodrigo Gonzalez Assignment 2

"""
if self.is_call:
return np.maximum(0, self.STs-self.K)
else:
return np.maximum(0, self.K-self.STs)

def traverse_tree(self, payoffs):


"""
Starting from the time the option expires, traverse
backwards and calculate discounted payoffs at each node
"""
for i in range(self.N):
payoffs = (payoffs[:-1]*self.qu +
payoffs[1:]*self.qd)*self.df

return payoffs

def begin_tree_traversal(self):
payoffs = self.init_payoffs_tree()
return self.traverse_tree(payoffs)

def price(self):
""" Entry point of the pricing implementation """
self.setup_parameters()
self.init_stock_price_tree()
payoffs = self.begin_tree_traversal()

# Option value converges to first node


return payoffs[0]

Using the values for the problems in this assignment

In [87]: eu_option = BinomialEuropeanOption(


80, 80, r=0.05, T=4/12, N=1, pu=0.0625, pd=0.0625, is_put=True)
print('European put option price for the exercise 1 is:', eu_option.price())

European put option price for the exercise 1 is: 1.7975367874187467

In [90]: eu_option = BinomialEuropeanOption(


40, 40, r=0.079210509, T=3/12, N=1, pu=0.125, pd=0.125, is_put=True)
print('European put option price for the exercise 2 is:', eu_option.price())

European put option price for the exercise 2 is: 2.0588235304304368

In [93]: eu_option = BinomialEuropeanOption(


50, 51, r=0.05, T=6/12, N=2, pu=0.06, pd=0.05, is_put=False)
print('European call option price for the exercise 3 is:', eu_option.price())

European call option price for the exercise 3 is: 1.6350711385184167

In [95]: eu_option = BinomialEuropeanOption(


50, 51, r=0.05, T=6/12, N=2, pu=0.06, pd=0.05, is_put=True)
print('European put option price for the exercise 4 is:', eu_option.price())

European put option price for the exercise 4 is: 1.37587665196338

In [103… (78*math.exp(0.3*math.sqrt(1/6))-80)/80

localhost:8985/doc/tree/Documents/2024/Western/Fall/Mathematics of Financial Options/Assignment 2/FM 9587 Rodrigo Gonzalez Assignment 2.ipynb 8/9
9/10/24, 8:21 p.m. FM 9587 Rodrigo Gonzalez Assignment 2

Out[103… 0.10203302569827084

In [109… (80-78*math.exp(-0.3*math.sqrt(1/6)))/78*math.exp(-0.3*math.sqrt(1/6))

Out[109… 0.12466934483941076

In [112… eu_option = BinomialEuropeanOption(


78, 80, r=0.03, T=2/12, N=2, pu=0.10203302569827084, pd=00.12466934483941076, i
print('European call option price for the exercise 5 is:', eu_option.price())

European call option price for the exercise 5 is: 4.611917044425747

localhost:8985/doc/tree/Documents/2024/Western/Fall/Mathematics of Financial Options/Assignment 2/FM 9587 Rodrigo Gonzalez Assignment 2.ipynb 9/9

You might also like