The function below works perfectly and only needs one thing:
Removal of the for loop that creates the 1000 element array arr.
Can you help me get rid of that for loop?
Code is below
#Test with european call
import numpy as np
T = 1
N = 1000
sigma = 0.5
r = 0.02
S = 1
K = 0.7
u = np.exp(sigma*np.sqrt(T/N))
d = 1/uarr = np.zeros(N+1)
arr[0] = S*np.power(u,N)coeff = np.exp(-r*(T/N))
p = (np.exp(r*(T/N))-d)/(u-d) for i in range(1, N+1):arr[i] = arr[i-1] * (d/u) def get_payoff(S=arr, K=K): payoff = np.maximum((S - K), 0)return payoffpayoff = get_payoff()def binomial_tree(payoff,S,K,T,r,sigma,N):for i in range(0, N):upper_vector = np.delete(payoff, N - i)lower_vector = np.delete(payoff, 0)payoff = coeff*(p*upper_vector + (1-p)*lower_vector) return payoff[0]print(binomial_tree(payoff,1,0.7,1,0.02,0.5,1000))
I am note sure if you can omit that loop in an efficient way, but when we do not use np.delete()
but just use the indices to shrink payoff
in every iteration I already got a big speed increase on my machine:
# ...
arr = np.full(N+1, d/u)
arr[0] = S*np.power(u, N)
arr[1:] = arr[0] * np.cumprod(arr[1:])def get_payoff(s, k):return np.maximum((s - k), 0)payoff = get_payoff(arr, K)def binomial_tree(payoff,S,K,T,r,sigma,N):for i in range(0, N):payoff = coeff*(p*payoff[:-1] + (1-p)*payoff[1:])return payoff[0]
Note that I also changed the generation of arr
to be without a loop and changed the name of the payload()
function so that it does not interfere with the variable name.
EDIT
I asked a similar question because I thought your formula was interesting and the answer from Frank Yellin also applies here (so all credits to him):
import numpy as np
from scipy.stats import binombinomial = binom(p=p, n=N)
pmf = binomial(np.arange(N+1))
res = coeff**n*np.sum(payoff * pmf)
In this form it is also clearer what is calculated in your loop:
the expected value of the binomial distributed random variable payoff.