© Maciej J. Capinski, Tomasz Zastawniak
Initially import all the modules we will be using for our notebook
import math
import numpy as np
import numpy.random as npr
# from pylab import plt, mpl
import sys
import os
if __name__== "__main__":
print("Hi there")
input("Provide a character: ")
Hi there
--------------------------------------------------------------------------- KeyboardInterrupt Traceback (most recent call last) ~/anaconda3/lib/python3.6/site-packages/ipykernel/kernelbase.py in _input_request(self, prompt, ident, parent, password) 884 try: --> 885 ident, reply = self.session.recv(self.stdin_socket, 0) 886 except Exception: ~/anaconda3/lib/python3.6/site-packages/jupyter_client/session.py in recv(self, socket, mode, content, copy) 802 try: --> 803 msg_list = socket.recv_multipart(mode, copy=copy) 804 except zmq.ZMQError as e: ~/anaconda3/lib/python3.6/site-packages/zmq/sugar/socket.py in recv_multipart(self, flags, copy, track) 469 """ --> 470 parts = [self.recv(flags, copy=copy, track=track)] 471 # have first part already, only loop while more to receive zmq/backend/cython/socket.pyx in zmq.backend.cython.socket.Socket.recv() zmq/backend/cython/socket.pyx in zmq.backend.cython.socket.Socket.recv() zmq/backend/cython/socket.pyx in zmq.backend.cython.socket._recv_copy() ~/anaconda3/lib/python3.6/site-packages/zmq/backend/cython/checkrc.pxd in zmq.backend.cython.checkrc._check_rc() KeyboardInterrupt: During handling of the above exception, another exception occurred: KeyboardInterrupt Traceback (most recent call last) <ipython-input-2-7d983df3fa32> in <module> 1 if __name__== "__main__": 2 print("Hi there") ----> 3 input("Provide a character: ") ~/anaconda3/lib/python3.6/site-packages/ipykernel/kernelbase.py in raw_input(self, prompt) 858 self._parent_ident, 859 self._parent_header, --> 860 password=False, 861 ) 862 ~/anaconda3/lib/python3.6/site-packages/ipykernel/kernelbase.py in _input_request(self, prompt, ident, parent, password) 888 except KeyboardInterrupt: 889 # re-raise KeyboardInterrupt, to truncate traceback --> 890 raise KeyboardInterrupt 891 else: 892 break KeyboardInterrupt:
# Directory where we will save our plots
directory = "./images"
if not os.path.exists(directory):
os.makedirs(directory)
if __name__== "__main__":
S0 = float(input("Enter S_0: "))
U = float(input("Enter U: "))
D = float(input("Enter D: "))
R = float(input("Enter R: "))
# making sure that 0<S0, -1<D<U, -1<R
if (S0 <= 0.0 or U <= -1.0 or D <= -1.0 or U <= D or R <= -1.0):
print("Illegal data ranges")
print("Terminating program")
sys.exit()
# checking for arbitrage
if (R >= U or R <= D):
print("Arbitrage exists")
print("Terminating program")
sys.exit()
print("Input data checked")
print("There is no arbitrage\n")
# compute risk-neutral probability
print("q = ", (R - D) / (U - D))
# compute stock price at node n=3,i=2
n = 3; i = 2
print("n = ", n)
print("i = ", i)
print("S(n,i) = ", S0* math.pow(1 + U,i) * math.pow(1 + D, n - i))
--------------------------------------------------------------------------- KeyboardInterrupt Traceback (most recent call last) ~/anaconda3/lib/python3.6/site-packages/ipykernel/kernelbase.py in _input_request(self, prompt, ident, parent, password) 884 try: --> 885 ident, reply = self.session.recv(self.stdin_socket, 0) 886 except Exception: ~/anaconda3/lib/python3.6/site-packages/jupyter_client/session.py in recv(self, socket, mode, content, copy) 802 try: --> 803 msg_list = socket.recv_multipart(mode, copy=copy) 804 except zmq.ZMQError as e: ~/anaconda3/lib/python3.6/site-packages/zmq/sugar/socket.py in recv_multipart(self, flags, copy, track) 469 """ --> 470 parts = [self.recv(flags, copy=copy, track=track)] 471 # have first part already, only loop while more to receive zmq/backend/cython/socket.pyx in zmq.backend.cython.socket.Socket.recv() zmq/backend/cython/socket.pyx in zmq.backend.cython.socket.Socket.recv() zmq/backend/cython/socket.pyx in zmq.backend.cython.socket._recv_copy() ~/anaconda3/lib/python3.6/site-packages/zmq/backend/cython/checkrc.pxd in zmq.backend.cython.checkrc._check_rc() KeyboardInterrupt: During handling of the above exception, another exception occurred: KeyboardInterrupt Traceback (most recent call last) <ipython-input-4-a1a06ba97b6b> in <module> 1 if __name__== "__main__": ----> 2 S0 = float(input("Enter S_0: ")) 3 U = float(input("Enter U: ")) 4 D = float(input("Enter D: ")) 5 R = float(input("Enter R: ")) ~/anaconda3/lib/python3.6/site-packages/ipykernel/kernelbase.py in raw_input(self, prompt) 858 self._parent_ident, 859 self._parent_header, --> 860 password=False, 861 ) 862 ~/anaconda3/lib/python3.6/site-packages/ipykernel/kernelbase.py in _input_request(self, prompt, ident, parent, password) 888 except KeyboardInterrupt: 889 # re-raise KeyboardInterrupt, to truncate traceback --> 890 raise KeyboardInterrupt 891 else: 892 break KeyboardInterrupt:
# computing risk-neutral probability
def RiskNeutProb(U, D, R):
return (R - D) / (U - D)
# computing the stock price at node n,i
def S(S0, U, D, n, i):
return S0 * math.pow(1 + U,i) * math.pow(1 + D, n - i)
def isValidInput(S0, U, D, R):
# making sure that 0<S0, -1<D<U, -1<R
if (S0 <= 0.0 or U <= -1.0 or D <= -1.0 or U <= D or R <= -1.0):
print("Illegal data ranges")
print("Terminating program")
return 0
# checking for arbitrage
if (R >= U or R <= D):
print("Arbitrage exists")
print("Terminating program")
return 0
return 1
# inputting, displaying and checking model data
def GetInputData():
#entering data
params = ("S0", "U", "D", "R")
S0, U, D, R = [float(input("Enter %s: " % (var))) for var in params]
if not isValidInput(S0, U, D, R):
return 0
print("Input data checked")
print("There is no arbitrage\n")
d = locals().copy()
return d
if __name__== "__main__":
# compute risk-neutral probability
print("q = ", RiskNeutProb(U, D, R))
output = GetInputData()
if output == 0:
sys.exit()
# Update our parameters
locals().update(output)
# compute stock price at node n=3,i=2
n = 3; i = 2
print("n = ", n)
print("i = ", i)
print("S(n,i) = ", S(S0,U,D,n,i))
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-5-74dfc56e9700> in <module> 39 if __name__== "__main__": 40 # compute risk-neutral probability ---> 41 print("q = ", RiskNeutProb(U, D, R)) 42 43 output = GetInputData() NameError: name 'U' is not defined
# Binomial Model (Parent class) ---------------------------------------------------
class BinModel:
def __init__(self, S0=100, U=0.1, D=-0.1, R=0):
self.S0 = S0
self.U = U
self.D = D
self.R = R
def RiskNeutProb(self):
return (self.R - self.D) / (self.U - self.D)
def S(self, n, i):
return self.S0 * math.pow(1 + self.U, i) * math.pow(1 + self.D, n - i)
# European Option class ------------------------------------------------------------------
class EurOption():
def PriceByCRR(self, Model, N=3):
q = Model.RiskNeutProb();
Price = np.zeros(N + 1)
for i in range(0, N + 1):
Price[i] = self.Payoff(Model.S(N, i))
for n in range(N - 1, -1, -1):
for i in range(0, n + 1):
Price[i] = (q * Price[i+1] + (1 - q) * Price[i]) / (1 + Model.R);
return Price[0]
# American Option class
class AmOption():
def PriceBySnell(self, Model, N=3):
q=Model.RiskNeutProb()
Price = np.zeros(N + 1)
for i in range(0, N + 1):
Price[i] = self.Payoff(Model.S(N, i))
for n in range(N - 1, -1, -1):
for i in range(0, n + 1):
ContVal = (q * Price[i+1] + (1 - q) * Price[i]) / (1 + Model.R)
Price[i] = self.Payoff(Model.S(n,i))
if (ContVal > Price[i]):
Price[i] = ContVal
return Price[0]
class AsianOption()
def PriceAsian(self, Model, N=3):
q = Model.RiskNeutProb();
Price = np.zeros(N + 1)
for i in range(0, 2 * N + 1):
Price[i] = self.Payoff(Model.S(N, i))
for n in range(N - 1, -1, -1):
for i in range(0, n + 1):
Price[i] = (q * Price[i+1] + (1 - q) * Price[i]) / (1 + Model.R);
return Price[0]
# Payoff Classes ----------------------------------------------------------------------------
class Call(EurOption, AmOption):
def __init__(self, K=1):
self.K = K
def Payoff(self, z):
if (z > self.K):
return z - self.K
return 0
class Put(EurOption, AmOption):
def __init__(self, K=1):
self.K = K
def Payoff(self, z):
if (z < self.K):
return self.K - z
return 0
class Digital_Call(EurOption, AmOption):
def __init__(self, K=1):
self.K = K
def Payoff(self, z):
if self.K < z:
return 1
return 0
class BullSpread(EurOption, AmOption):
def __init__(self, K1=1, K2 = 2):
self.K1 = K1
self.K2 = K2
def Payoff
model = BinModel(S0=10, U=0.2, D=-0.1, R=0.1)
Option1 = Digital_Call(K=22)
Option1.PriceByCRR(model, N=6)
0.19822404128088741
PriceByCRR()
function in EurOption
Class to compute the time $0$ price of a European option using the Cox–Ross–Rubinstein (CRR) formula:Include the ability to price digital calls in the program developed in the present section by adding the new payoff Class DigitCall
just as was done for calls and puts.
BullSpread
and BearSpread
of the EurOption
and AmOption
classes defined in our current program. The payoffs of a bull spread and a bear spread, which depend on two parameters $K1 < K2$, are given by:and $$h^{bear}(z)=\begin{cases} K_{2}-K_{1} & \textrm{if }z\leq K_{1},\\ K_{2}-z & \textrm{if }K_{1}<z<K_{2}\\ 0 & \textrm{if }K_{2}<z, \end{cases}$$
and payoff, $$C(N)=max\{A_{N},0\}$$
Add a new Class AsianOption
to price an Asian style Call Option.