Sunteți pe pagina 1din 29

IE

420

Financial Engineering

Final Project

Martinez-Brocal Contreras, Luis


4-21-2016

IE 420

Luis Martinez-Brocal Contreras

Contents

1) .................................................................................................................................................................. 2
2) .................................................................................................................................................................. 4
3) .................................................................................................................................................................. 7
4) ................................................................................................................................................................ 12
Appendix .................................................................................................................................................... 16
Part 1 ...................................................................................................................................................... 16
Part 2 ...................................................................................................................................................... 18
Part 3 ...................................................................................................................................................... 19
Part 4 ...................................................................................................................................................... 20
Part 5 ...................................................................................................................................................... 20
Part 6 ...................................................................................................................................................... 21
Part 7 ...................................................................................................................................................... 22
Part 8 ...................................................................................................................................................... 24
Part 9 ...................................................................................................................................................... 25
Part 10 .................................................................................................................................................... 26
Part 11 .................................................................................................................................................... 27

IE 420

Luis Martinez-Brocal Contreras


For this project, it has been decided to use python as programming language. This choice has been
undertaken due to its computation speed. Also, python features some plotting functions that will provide
an easy way to show the results.

1)

It has been developed the required function to calculate the option price. Being the function prototype
as follows:
(, , , /0/1/23 , , , , , )
Where:
Option: can be either a (for American options) or e (for European options)
K: strike price of the option
s_initial: initial stock price
sigma: volatility of asset
r: free risk interest rate
q: asset continuous annual yield
N: number of steps of binomial model
Exercise: can be either p (for Puts) or c (for Calls)
The code can be found in Appendix Part 1.
This binomial function returns a vector with two values, the calculated option price (first position) and
the execution time (second position).
It has been tried to improve the performance in this function but no substantial results in execution time
have been accomplished. Even though the execution time is good and it is among expected performance
times.
To measure performance of the function, it has been created a function called performance(), that plots
execution time for a range of steps for a single option price. It has been added the performance of an
alternative version of binomial function(binomial_v2), which uses xrange() function instead of range().
The source code of this function can be seen in Appendix Part 2





2

IE 420

Luis Martinez-Brocal Contreras

The output plot from this function is:


It can be observed that execution time increase faster as step number increases. Also that there isnt any
meaningful improvement with binomial_v2(). Computational time increases in a quadratic way. This can
be explained by the next equation:
=

+ >

2

Where n is the number of steps of a binomial tree and k is the total number of nodes in that tree (with
that n number of steps). Therefore, the computational time is directly related with the number of nodes
the function has to process.
Basically, the binomial function uses four functions to work. Firstly, a function called node() figures out
the stock price of any node of the binomial tree. Then, there are a payoff_call() and payoff_put()
functions, which calculate the payoff for a given strike price and stock price option. Finally, there is a
function called backward(), which applies the neutral risk equation:
= -DF [ 0IJK + 1 0IJK ]
Binomial function implements these functions as a whole. First, it builds an array of payoffs of the nodes
in the last step of the binomial tree. Then, it goes backwards, transforming this vector until getting to the
initial step value of the tree. To calculate the array of payoffs in the last step, payoff_call() or
payoff_put() are executed according to the type of option in a loop, which gets stock price of each node
by calling the node() function.




3

IE 420

Luis Martinez-Brocal Contreras

2)

It has been developed a function second_european(being_value,decimals) that computes both
Binomial and Black-Scholes pricing model for a range of n values (number of steps). Once both prices are
equal for an accuracy of a given number of digits after decimal point (parameter decimals), it stops
iterating and returns the number of steps, price and execution time for the iteration that reaches required
accuracy. It has to be defined the initial step number from which it starts the iteration (parameter
begin_value).
The source code for this function, for the case of a 1-year European call option, with K=100, current stock
price=100, 20% of volatility, r=0.05 and q=0.04, can be found in Appendix Part 3.
It is important to highlight that a black-scholes pricing function black_scholes() has been developed for
this function, being the source code in Appendix Part 4.
Executing the following instance of the function:
second_european(50,3)
The plot obtained from this function is following:





Next, the console output that results:
'With 3000 steps,price is: 8.10200819016 and time spent for it: 2.332436
seconds, and time to find steps (seconds): 43.495758'

IE 420

Luis Martinez-Brocal Contreras

The function also returns the Black-Scholes price results at the beginning of execution, which in this case
is $8.102. Therefore, both binomial model with 3000 steps and Black-Scholes prices are equal. Regarding
the execution time, for this function, it has been made a calculation with increments of 50 steps in each
iteration, resulting the previous chart more smooth than it would be in case of calculating price for steps
increases equal to 1. Defining a higher step value would entail lower execution time but worse result
accuracy.
Since the result of steps needed for required accuracy in European options is 3000, this number will be
the initial iteration step value (parameter begin_value) for the next function, which iterates the binomial
model (for this specific option but with american type) function until the variations between successive
results is lower than 0.001, getting an accuracy of three digits after decimal point. The source code for
this function can be found in Appendix Part 5.
It is executed the following command:
second_american(3000)
The output plot is:


The output of the function in console is:
>>> second_american(3000)
N 3000 Price 8.11760286598 Change 0.0012597129208
N 3250 Price 8.11765187035 Change 0.00116279707966
N 3500 Price 8.1176938747 Change 0.00107972715656
N 3750 Price 8.1177302782 Change 0.00100773534066
'With 4000 steps,price is: 8.11776213087 and time spent for it: 17.902071
seconds Change 0.000944744063721, and time to find steps: 208.607393'

Where change is the result price variation between the current and the previous iteration (notice that
in the previous chart, y-axis values are expressed as a fix part, which is in that case +8.1175, plus a decimal
5

IE 420

Luis Martinez-Brocal Contreras

part which are the numbers in the y-axis). It will be needed to use 4000 steps to reach desired accuracy
for calculations in which American options are implied. The 0.001 accuracy has been chosen in order to
get to the same accuracy required for European options compared with Black-Scholes model. Regarding
the execution time, for this function, it has been made a calculation with increments of 250 steps. Defining
a higher step value would entail lower execution time but worse result accuracy. It is important to point
out that since there is no Black-Scholes function in the program to calculate American options price, it is
needed to do this by using the European option price results as a base reference.























IE 420

Luis Martinez-Brocal Contreras

3)

For this point, there is an American put option with K=100, time to maturity of 1 year, 20% volatility,
r=0.05 and q=0.
First, it is calculated the put prices as a function of initial stock price S for the case of a 1-year time to
maturity. Also it is required to get the initial stock price for which it first becomes optimal to early exercise
the put.
A function called third_first() has been developed for these two goals. It plots results (option price and
payoff) as a function of initial stock price and returns optimal initial stock price (with the accuracy required
for the project, which is a difference lower than 0.005 between payoff and price). The source code of this
function can be found in Appendix Part 6.
The parameters of the function are the type of option, number of steps to use (N), and end_price, which
is the value until it is desired to plot the results and it has to be greater than K (strike price) in order to be
able to find the optimal exercise point. Also it gives the option to either plot the result or not (yes or no
for plot parameter).
For this function, it has been decided to calculate intervals of $1 price variation, in order to get a
reasonable execution time along with good accuracy.
Since it is needed to plot all the points, no method has been used to reduce the time it takes to find the
optimal early exercise initial stock price.
Executing the next command:
third_first(150,4000,'yes',100,1,0.2,0.05,0,'a')

IE 420

Luis Martinez-Brocal Contreras

The resulting plot is:


Execution time to obtain the previous plot has been:
Execution time (seconds): 28.52735

And the console output shows (using the same function arguments but with function third_first_fast(),
which is explained in the next paragraph) that the optimal stock initial price for early exercise is:
= $81.38
The computational time that has been needed to find this stock price using this fast version of the function
is the one shown in the console output:
Execution time (seconds): 215
81.38

The second part of this exercise is to find the initial stock prices for which it first becomes optimal to early
exercise puts with time to maturity from one month to twelve months, with intervals of one month. It has
been done by using two functions, one called third_second() which finds for the time to maturity range
the optimal exercise stock initial prices. To find each of these prices another function(third_first_fast) has
been developed, which finds the initial stock price as third_first() function does but in a more accurate
and fast way, in order to avoid long execution times with third_second() function. Source code of these
two functions can be found in Appendix Part 7.
Using last_price variable value in third_second() function (in order to assign last_price value to
begin_price parameter in third_first_fast() function, which is executed from third_second()), makes
it to gets the results much faster. This is because, for each time to maturity, third_first_fast() doesnt
start looking up the optimal point from the strike price value (only the first time to maturity iteration is
calculated starting from strike price value). Instead of that, it starts from the last optimal price that results
from the previous time to maturity, since optimal points are sequential. Also, using third_first_fast, two
decimal digits results are obtained for early boundary plot. This extra accuracy is achieved by using a
8

IE 420

Luis Martinez-Brocal Contreras

numerical method that once it is close to the optimal value, it automatically reduces the search interval
until finding it with that new accuracy.

Next, there is the table with the optimal early exercise initial stock prices for each of the time to maturity
range values (0, 1, ,12):

Time to
maturity
[months]
Initial
Stock
Price [$]

10

11

12

100

91.30

88.91

87.35

86.17

85.23

84.45

83.78

83.19

82.66

82.19

81.77

81.38


The first optimal price, which is for 0 months of time to maturity, equals for all cases from now on (parts
three and four of this report) to the strike price, since it would be the price to exercise an option in the
maturity date.
Executing the command:
third_second(1,12,4000,100,0.2,0.05,0)
The resulting plot is (which is the early exercise boundary):



Finally, it will be computed the put prices as a function of stock initial prices for the same case but with a
continuous yield of 4%:
9

IE 420

Luis Martinez-Brocal Contreras


The optimal initial stock price for 1-year to time to maturity is:
= $74.31
And the time spent to find it: 240 seconds
It can be observed that prices are lower with a higher yield of the asset. The intuition behind this change
is that in order to compensate the yield (q) that the asset will generate until maturity, the price of the
stock has to be low enough in order to get greater payoff. That means that selling earlier, one will get less
yield benefits from asset since you own it for less time, then one has to compensate this loss by getting
a bigger benefit from exercising the option.
Next, there is the table with the optimal early exercise initial stock prices for each of the value from the
time to maturity range:
Time to
1
2
3
4
5
6
7
8
9
10
maturity 0
[months]
Initial
Stock 100 88.87 85.47 83.21 81.49 80.10 78.94 77.93 77.04 76.26 75.55
Price [$]






10

11

12

74.9

74.31

IE 420

Luis Martinez-Brocal Contreras

Also the new early exercise boundary for q=4%:


Clearly, the boundary is lower in each of the maturities because of the previous explanation.
Finally, it can be observed both boundary plots (with q value of 0% and 4%) in the same graph and their
difference:


To plot this multiple graph third_second_multiple() has been used. Its source code can be found in
Appendix Part 10.

11

IE 420

Luis Martinez-Brocal Contreras

4)

In this part, it is required to plot the American call prices as a function of initial stock price. Namely, for
this case, it will be used K=100, 1-year time to maturity, 20% volatility, r=0.05, q=0.04. The function for
this end can be found in Appendix Part 8.
All the parameters are the type of call option and also it is required the end_price until which it plots,
which has to be way bigger than strike price to make possible to find optimal exercise initial stock price.
Also, it gives the option to either plot or not (by introducing yes or no). An important detail for this
function is that even knowing that end_price has to be greater than strike price, it is unknown by how
much. Then, in order to plot it properly and find the optimal early exercise point, it will be needed to firstly
execute the function fourth_first_fast() and find the price of the optimal early exercise point. Once the
value is known, end_price will be defined with a greater value than the calculated one.
Using the command:
fourth_first(150,4000,'yes',100,1,0.2,0.05,0.04,'a')

The resulting plot:


And the console output shows (using the same function arguments but with function fourth_first_fast())
that the optimal stock initial price for early exercise is:
= $152.04
The second part of this exercise is to find the initial stock prices for which it first becomes optimal to early
exercise calls with time to maturity from one month to twelve months, with intervals of one month. It has
been done by two functions, one called fourth_second() which finds for the time to maturity range the
12

IE 420

Luis Martinez-Brocal Contreras

optimal exercise stock initial price. To find each of these prices, another function fourth_first_fast has
been developed, which finds the initial stock price as fourth_first() function does but in a more accurate
and fast way, in order to avoid long execution times with fourth_second() function. The source code for
these two functions can be found in Appendix Part 9. This two functions are analogous to the third section
of the report function but adapted, in order to do the same but with call options instead of put options.
These two functions are also optimized like in the third section of the report (using the same methods),
in order to get better accuracy and execution time by using the fourth_first_fast() function along with
storing last_price variable in fourth_second() function to use it as begin_price in each time to maturity
iteration.
Executing the command:
fourth_second(1,12,4000,100,0.2,0.05,0.04)
The optimal early exercise price values for the time to maturity range are:
Time to maturity
[months]
Initial Stock Price
[$]

100

125.06

128.74

132.28

135.46

138.28

140.80


Time to maturity
[months]
Initial Stock Price [$]

10

11

12

143.07

145.15

147.06

148.83

150.49

152.04



The resulting plot is (which is the early exercise boundary):



13

IE 420

Luis Martinez-Brocal Contreras


Finally, it will be computed the call prices as a function of stock initial prices for the same case but with a
continuous yield of the asset of 8%:


The optimal initial stock price for 1-year time to maturity is:
= 126.02$
It can be observed that the optimal initial stock price is lower than in the previous case with lower yield
for any given time to maturity value (as it will be checked in the next plots). The intuition behind this is
that early exercise will provide more yield from the asset since one have it since earlier (then more time).
So if one has a call option for an asset with higher yield, then that person will be willing to exercise it with
a lower payoff in order to start getting the yield from the asset sooner. So the lower gain in option exercise
must be justified by the earning the asset will provide with the extra tenure time by early exercising.
The optimal early exercise price values for the time to maturity range are:
Time to maturity
[months]
Initial Stock Price
[$]

100

110.54

113.93

116.27

118.08

119.57

120.84


Time to maturity
[months]
Initial Stock Price
[$]




14

10

11

12

121.94

122.92

123.81

124.62

125.35

126.02

IE 420

Luis Martinez-Brocal Contreras

The new early exercise boundary (q=0.08):


Clearly, the boundary is lower in each of the maturities because of the previous explanation.
Finally, it can be observed both boundaries (with q value of 4% and 8%) in the same graph and their
difference:


To plot this multiple graph fourth_second_multiple() has been used. Its source code can be found in
Appendix Part 11.

15

IE 420

Luis Martinez-Brocal Contreras

Appendix

Part 1

from
from
from
from

__future__ import division


math import exp
math import sqrt
datetime import datetime

#function figures out stock price in tree nodes


def node(n,j,u,d,s_initial):
return (u**j)*(d**(n-j))*s_initial
#function calculates payoff for a given node in stock price tree if option is
a call
def payoff_call(k,s):
return max(0,(s-k))
#function calculates payoff for a given node in stock price tree if option is
a put
def payoff_put(k,s):
return max(0,(k-s))
#function calculates backward payoff node of tree branch
def backward(e1,e2,p,r,delta):
return exp(-r*delta)*((p*e1)+(1-p)*e2)

def binomial(option,k,T,s_initial,sigma,r,q,N,exercise):
startTime = datetime.now()
delta=T/N
# Gets the value variable in order to do just once the calculation for
u and d
value=sigma*sqrt(delta)
u=exp(value)
d=exp(-value)
free_risk_p=(exp((r-q)*delta)-d)/(u-d)
payoff_vector=list()
if option=='c':
for j in range(N,-1,-1):

16

IE 420

Luis Martinez-Brocal Contreras

payoff_vector.append(payoff_call(k,node(N,j,u,d,s_initial)))
if exercise=='a':
for x in range(N-1,-1,-1):
for y in range(0,x+1):
payoff_vector[y]=max(payoff_call(k,node(x,xy,u,d,s_initial)),backward(payoff_vector[y],payoff_vector[y+1],free_risk_p,r,
delta))
elif exercise=='e':
for x in range(N-1,-1,-1):
for y in range(0,x+1):
payoff_vector[y]=backward(payoff_vector[y],payoff_vector[y+1],free_ris
k_p,r,delta)
else:
print ('Wrong exercise type')
elif option=='p':
for j in range(N,-1,-1):
payoff_vector.append(payoff_put(k,node(N,j,u,d,s_initial)))
if exercise=='a':
for x in range(N-1,-1,-1):
for y in range(0,x+1):
payoff_vector[y]=max(payoff_put(k,node(x,xy,u,d,s_initial)),backward(payoff_vector[y],payoff_vector[y+1],free_risk_p,r,
delta))
elif exercise=='e':
for x in range(N-1,-1,-1):
for y in range(0,x+1):
payoff_vector[y]=backward(payoff_vector[y],payoff_vector[y+1],free_ris
k_p,r,delta)

17

IE 420

Luis Martinez-Brocal Contreras

else:
print ('Wrong exercise type')
else:
print('Wrong option type')
time = datetime.now()-startTime
return [payoff_vector[0],time.total_seconds()]

Part 2

#measures performance of binomial function from 1 step to n
def performance(n):

startTime = datetime.now()
steps_x=list()
performance_y=list()
performance_z=list()
for x in range(1,n+100,100):
result = binomial('c',100,1,100,0.2,0.05,0.04,x,'e')
result2 = binomial_v2('c',100,1,100,0.2,0.05,0.04,x,'e')
performance_y.append(result[1])
performance_z.append(result2[1])
steps_x = range(1,n+100,100)
time = datetime.now()-startTime
plt.xlabel('Number of Steps')
plt.ylabel('Seconds')
plt.title('Performance')
plt.plot(steps_x, performance_y,'-',label='Binomial v1')
plt.plot(steps_x, performance_z,'-',label='Binomial v2')
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.show()
print('Execution time (seconds): ' + str(time.total_seconds()))
return

18

IE 420

Luis Martinez-Brocal Contreras


Part 3

'''iterates until binomial price is equal with three decimal
digits accuracy to the black scholes price'''
def second_european(begin_value,decimals):
startTime = datetime.now()
prices_y=list()
z=0
x=begin_value
black_scholes_price = black_scholes('c',100,1,100,0.2,0.05,0.04)
black_scholes_price=floor(black_scholes_price * (10**decimals)) /
float(10**decimals)
print(black_scholes_price)
while z==0:
result = binomial('c',100,1,100,0.2,0.05,0.04,x,'e')
prices_y.append(result[0])
if (result[0]-black_scholes_price)<0.0009 and (result[0]black_scholes_price)>=0:
steps_x = range(begin_value,x+50,50)
print('Found! -> N ' + str(x) + ' Price ' +
str(result[0]))
break
else:
print('N ' + str(x) + ' Price ' + str(result[0]))
x=x+50
time = datetime.now()-startTime
plt.xlabel('Number of Steps')
plt.ylabel('Price[$]')
plt.title('Prices convergence')
plt.plot(steps_x, prices_y,'-',label='Price for N steps')
plt.plot([begin_value,x,],
[black_scholes_price,black_scholes_price],'-',label='Black-Scholes Price')
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.show()

19

IE 420

Luis Martinez-Brocal Contreras

return 'With ' + str(x) + ' steps,price is: ' + str(result[0]) + ' and
time spent for it: ' + str(result[1]) + ' seconds, and time to find steps
(seconds): ' + str(time.total_seconds())

Part 4

from
from
from
from
from

__future__ import division


math import exp
math import sqrt
scipy import stats
numpy import log

def black_scholes(option,k,T,s_initial,sigma,r,q):
d1=(log(s_initial/k)+T*(r-q+0.5*(sigma**2)))/(sigma*sqrt(T))
d2=d1-sigma*sqrt(T)
if option=='c':
result = s_initial*exp(-q*T)*stats.norm(0,1).cdf(d1)-k*exp(r*T)*stats.norm(0,1).cdf(d2)
if option=='p':
result = -s_initial*exp(-q*T)*stats.norm(0,1).cdf(-d1)+k*exp(r*T)*stats.norm(0,1).cdf(-d2)
return result

Part 5

#iterates until price changes in binomial model are lower than 0.001
def second_american(begin_value):
startTime = datetime.now()
prices_y=list()
z=0
x=begin_value
while z==0:
result = binomial('c',100,1,100,0.2,0.05,0.04,x,'a')
prices_y.append(result[0])
if fabs((result[0]-binomial('c',100,1,100,0.2,0.05,0.04,x1,'a')[0]))<=0.00099 and x>(begin_value+50):
steps_x = range(begin_value,x+250,250)

20

IE 420

Luis Martinez-Brocal Contreras

change=fabs(result[0]binomial('c',100,1,100,0.2,0.05,0.04,x-1,'a')[0])
break
elif x>1:
change=fabs(result[0]binomial('c',100,1,100,0.2,0.05,0.04,x-1,'a')[0])
print('N ' + str(x) + ' Price ' + str(result[0]) + '
Change ' + str(change))
x=x+250
time = datetime.now()-startTime

plt.xlabel('Number of Steps')
plt.ylabel('Price[$]')
plt.title('Prices convergence')
plt.plot(steps_x, prices_y,'-',label='Price for N steps')
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.show()
return 'With ' + str(x) + ' steps,price is: ' + str(result[0]) + ' and
time spent for it: ' + str(result[1]) + ' seconds' + ' Change ' + str(change)
+ ', and time to find steps (seconds): ' + str(time.total_seconds())


Part 6

'''Third exercise of project, plots option (european or american) put
price vs stock initial price, and returns first optimal early exercise
stock initial price(for american option), also plots option payoff'''
def third_first(end_price,n,plot,k,maturity,sigma,r,q,exercise):
startTime = datetime.now()
steps_x=range(1,end_price,1)
price_a=list()
payoff_y=list()
a=0
b=0
found=0
for x in steps_x:
result = binomial('p',k,maturity,x,sigma,r,q,n,exercise)
price_a.append(result[0])
payoff = max(0,k-x)
payoff_y.append(payoff)

21

IE 420

Luis Martinez-Brocal Contreras

if exercise=='a':
if fabs(payoff - result[0])<0.005 and x<k:
found=1
a=x
b=result[0]
time = datetime.now()-startTime

if plot=='yes':
plt.xlabel('Initial price of stock[$]')
plt.ylabel('Option price[$]')
plt.title('Option Price vs Stock Price')
plt.plot(steps_x, price_a,'-',label='Put Option')
plt.plot(steps_x,payoff_y,'--',label='Put Payoff')
if exercise=='a' and found==1:
plt.plot(a,b,'o',label='Optimal Point for Early
Excercise')
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.show()
print('Execution time (seconds): ' + str(time.total_seconds()))
return a


Part 7

'''returns optimal early exercise option stock initial price for an american
put in a faster and more accurate way than function third_first, it doesn't
plot results,
and is the one used in function third_second'''
def third_first_fast(begin_price,n,k,maturity,sigma,r,q,exercise):
startTime = datetime.now()
if begin_price==0:
x=k
else:
x=begin_price
price_a=list()
payoff_y=list()
a=0
b=1

22

IE 420

Luis Martinez-Brocal Contreras

found=0
while True:
result = binomial('p',k,maturity,x,sigma,r,q,n,exercise)
price_a.append(result[0])
payoff = max(0,k-x)
payoff_y.append(payoff)
if fabs(payoff - result[0])<0.005:
a=x
if b==1:
x=x+1
b=0.1
elif b==0.1:
x=x+0.1
b=0.01
else:
break
else:
x=x-b
print(x)
time = datetime.now()-startTime
print('Execution time (seconds): ' + str(time.total_seconds()))
return a

#maturities in months / plots early exercise boundary for put options


def third_second(initial_maturity,final_maturity,n,k,sigma,r,q):
startTime = datetime.now()
maturities = range(initial_maturity,final_maturity+1,1)
optimal_points = list()
last_price=0 #last maturity optmal initial price is stored in order to
improve execution time
for i in maturities:
result=third_first_fast(last_price,n,k,i/12,sigma,r,q,'a')
last_price=result
optimal_points.append(result)
time = datetime.now()-startTime
plt.xlabel('Time to Maturity[months]')
plt.ylabel('Optimal stock price for early exercise')

23

IE 420

Luis Martinez-Brocal Contreras

plt.title('Early Exercise Boundary')


plt.plot([0]+maturities, [k]+optimal_points,'-')
plt.show()
print('Execution time (seconds): ' + str(time.total_seconds()))
return


Part 8

'''fourth exercise of project, plots call (european and american)
option price vs stock initial price and , and returns first optimal early
exercise stock initial price (for american option), also plot option
payoff'''
def fourth_first(end_price,n,plot,k,maturity,sigma,r,q,exercise):
startTime = datetime.now()
steps_x=range(1,end_price*10,1)
steps_x[:] = [x / 10 for x in steps_x]
price_a=list()
payoff_y=list()
a=0
b=0
found=0
for x in steps_x:
result = binomial('c',k,maturity,x,sigma,r,q,n,exercise)
price_a.append(result[0])
payoff = max(0,x-k)
payoff_y.append(payoff)
if exercise=='a':
if fabs(payoff - result[0])<0.005 and x>k and a==0:
found=1
a=x
b=result[0]
time = datetime.now()-startTime

if plot=='yes':
plt.xlabel('Initial price of stock[$]')
plt.ylabel('Option price[$]')

24

IE 420

Luis Martinez-Brocal Contreras

plt.title('Option Price vs Stock Price')


plt.plot(steps_x, price_a,'-',label='Call Option')
plt.plot(steps_x,payoff_y,'--',label='Call Payoff')
if exercise=='a' and found==1:
plt.plot(a,b,'o',label='Optimal Point for Early
Excercise')
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.show()
print('Execution time (seconds): ' + str(time.total_seconds()))
return a

Part 9

'''returns optimal early exercise stock initial price for an american call
in a faster and more accurate way than function third_first, it doesn't plot
results,
and is the one used in function fourth_second'''
def fourth_first_fast(begin_price,n,k,maturity,sigma,r,q,exercise):
startTime = datetime.now()
if begin_price==0:
x=k-1
else:
x=begin_price-1
price_a=list()
payoff_y=list()
a=0
b=1
c=0
found=0
while True:
x=x+b
print(x)
result = binomial('c',k,maturity,x,sigma,r,q,n,exercise)
price_a.append(result[0])
payoff = max(0,x-k)
payoff_y.append(payoff)
if fabs(payoff - result[0])<0.005 and b>0:
a=x
if b==1:
x=x-1

25

IE 420

Luis Martinez-Brocal Contreras

b=0.1
elif b==0.1:
x=x-0.1
b=0.01
elif b==0.01:
break
time = datetime.now()-startTime
print('Execution time (seconds): ' + str(time.total_seconds()))
return a

#maturities in months / plots early exercise boundary for call options


def fourth_second(initial_maturity,final_maturity,n,k,sigma,r,q):
startTime = datetime.now()
maturities = range(initial_maturity,final_maturity+1,1)
optimal_points = list()
#last maturity optmal initial price is stored in order to improve execution
time
last_price=0
for i in maturities:
result=fourth_first_fast(last_price,n,k,i/12,sigma,r,q,'a')
last_price=result
optimal_points.append(result)
time = datetime.now()-startTime
plt.xlabel('Time to Maturity[months]')
plt.ylabel('Optimal stock price for early exercise')
plt.title('Early Exercise Boundary')
plt.plot([0]+maturities, [k]+optimal_points,'-')
plt.show()
print('Execution time (seconds): ' + str(time.total_seconds()))
return

Part 10

#maturities in months / plots early exercise boundary for put options
(multiple plots)
def third_second_multiple(initial_maturity,final_maturity,n,k,sigma,r,q1,q2):

26

IE 420

Luis Martinez-Brocal Contreras

startTime = datetime.now()
maturities = range(initial_maturity,final_maturity+1,1)
optimal_points1 = list()
optimal_points2 = list()
last_price1=0 #last maturity optmal initial price is stored in order
to improve execution time
last_price2=0
for i in maturities:
result=third_first_fast(last_price1,n,k,i/12,sigma,r,q1,'a')
last_price1=result
optimal_points1.append(result)
for j in maturities:
result=third_first_fast(last_price2,n,k,j/12,sigma,r,q2,'a')
last_price2=result
optimal_points2.append(result)
time = datetime.now()-startTime
plt.xlabel('Time to Maturity[months]')
plt.ylabel('Optimal stock price for early exercise')
plt.title('Early Exercise Boundary')
plt.plot([0]+maturities, [k]+optimal_points1,'-',label="Early Exercise
Boundary (q=" + str(q1) + ")")
plt.plot([0]+maturities, [k]+optimal_points2,'-',label="Early Exercise
Boundary (q=" + str(q2) + ")")
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.show()
print('Execution time (seconds): ' + str(time.total_seconds()))
return

Part 11

#maturities in months / plots early exercise boundary for call options
(multiple plots)
def
fourth_second_multiple(initial_maturity,final_maturity,n,k,sigma,r,q1,q2):
startTime = datetime.now()
maturities = range(initial_maturity,final_maturity+1,1)

27

IE 420

Luis Martinez-Brocal Contreras

optimal_points1 = list()
optimal_points2 = list()
#last maturity optmal initial price is stored in order to improve execution
time
last_price1=0
last_price2=0
for i in maturities:
result=fourth_first_fast(last_price1,n,k,i/12,sigma,r,q1,'a')
last_price1=result
optimal_points1.append(result)
for j in maturities:
result=fourth_first_fast(last_price2,n,k,j/12,sigma,r,q2,'a')
last_price2=result
optimal_points2.append(result)
time = datetime.now()-startTime
plt.xlabel('Time to Maturity[months]')
plt.ylabel('Optimal stock price for early exercise')
plt.title('Early Exercise Boundary')
plt.plot([0]+maturities, [k]+optimal_points1,'-',label="Early Exercise
Boundary (q=" + str(q1) + ")")
plt.plot([0]+maturities, [k]+optimal_points2,'-',label="Early Exercise
Boundary (q=" + str(q2) + ")")
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.show()
print('Execution time (seconds): ' + str(time.total_seconds()))
return

28

S-ar putea să vă placă și