Optimized Python Code for CRR The Python code below is optimized in a manner consistent with Broadie and Detemple (1996) and Haug (1997) who apply a one-dimensional dynamic binomial tree. This approach takes the option values at the last column and stores them in a dynamic vector Opt(j) for j = 0, 1, … , n. After moving one step back, the values in the re-dimensioned Opt(j) for j = 0, 1, …, n - 1 will be replaced by the option values of the corresponding nodes at the penultimate column. This dynamic use of memory continues until we reach the apex node in the lattice. The code below for Cox Ross and Rubinstein is adapted from https://github.com/tienusss/Option_Calculations # adapted from Haug but need to adjust for greeks (this code originally developed for Leisen reimer) # I think it is ok s*u*d = s for CRR that is the only difference # https://github.com/tienusss/Option_Calculations # Import packages import numpy as np # Defined functions def CRRBinomial(OutputFlag, AmeEurFlag, CallPutFlag, S, X, T, r, c, v, n): # This functions calculates CRR price, delta and gamma for of American and European options # This code is based on "The complete guide to Option Pricing Formulas" by Espen Gaarder Haug (2007) # Translated from a VBA code # OutputFlag: # "P" Returns the options price # "d" Returns the options delta # "a" Returns an array containing the option value, delta and gamma # AmeEurFlag: # "a" Returns the American option value # "e" Returns the European option value # CallPutFlag: # "C" Returns the call value # "P" Returns the put value # S is the share price at time t # X is the strike price # T is the time to maturity in years (days/365) # r is the risk-free interest rate # c is the cost of carry rate # v is the volatility # n determines the stepsize # Creates a list with values from 0 up to n (which will be used to determine to exercise or not) n_list = np.arange(0, (n + 1), 1) # Checks if the input option is a put or a call, if not it returns an error if CallPutFlag == 'C': z = 1 elif CallPutFlag == 'P': z = -1 else: return 'Call or put not defined' # Calculates the stepsize in years dt = T / n # The up and down factors u = np.exp(v*np.sqrt(dt)) d = 1./u p = (np.exp((c)*dt)-d) / (u-d) df = np.exp(-r * dt) # Creates the most right column of the tree max_pay_off_list = [] for i in n_list: i = i.astype('int') max_pay_off = np.maximum(0, z * (S * u ** i * d ** (n - i) - X)) max_pay_off_list.append(max_pay_off) # The binominal tree for j in np.arange(n - 1, 0 - 1, -1): for i in np.arange(0, j + 1, 1): i = i.astype(int) # Need to be converted to a integer if AmeEurFlag == 'e': max_pay_off_list[i] = (p * max_pay_off_list[i + 1] + (1 - p) * max_pay_off_list[i]) * df elif AmeEurFlag == 'a': max_pay_off_list[i] = np.maximum((z * (S * u ** i * d ** (j - i) - X)), (p * max_pay_off_list[i + 1] + (1 - p) * max_pay_off_list[i]) * df) if j == 2: gamma = ((max_pay_off_list[2] - max_pay_off_list[1]) / (S * u ** 2 - S * u * d) - ( max_pay_off_list[1] - max_pay_off_list[0]) / (S * u * d - S * d ** 2)) / ( 0.5 * (S * u ** 2 - S * d ** 2)) if j == 1: delta = ((max_pay_off_list[1] - max_pay_off_list[0])) / (S * u - S * d) price = max_pay_off_list[0] # Put all the variables in the list variable_list = [delta, gamma, price] # Return values if OutputFlag == 'P': return price elif OutputFlag == 'd': return delta elif OutputFlag == 'g': return gamma elif OutputFlag == 'a': return variable_list else: return 'Indicate if you want to return P, d, g or a' #Body of the script # CRRBinomial(OutputFlag, AmeEurFlag, CallPutFlag, S, X, T, r, c, v, n) S = 100 X = 100 T = 1. r = 0.05 c = 0.05 v = 0.2 n = 100 Eur_call_result = CRRBinomial('P', 'e', 'C', S, X, T, r, c, v, n) American_call_result = CRRBinomial('P', 'a', 'C', S, X, T, r, c, v, n) Eur_put_result = CRRBinomial('P', 'e', 'P', S, X, T, r, c, v, n) American_put_result = CRRBinomial('P', 'a', 'P', S, X, T, r, c, v, n) #Print the output of the results print('The price of the European call option is equal to ' +str(Eur_call_result)) print('The price of the American call option is equal to ' +str(American_call_result)) print('The price of the European put option is equal to ' +str(Eur_put_result)) print('The price of the American put option is equal to ' +str(American_put_result)) |