European Call option replication

An asset $$S_t$$ is evolving according to the Black-Scholes model. We want to replicate a call option on this asset by holding Delta units of the asset at every time.

I use a Monte Carlo algorithm to compute the mean cost of this replication strategy. I would expect this cost to be somewhat close, on average, to the payoff of the corresponding call option, but I find that this is not the case at all.

My question is: is there a problem with my implementation?

Here is my code: (I skip the import numpy as np and the definition of the Delta)

def make_path(spot, r, d, vol, T, N):
dt = T/(N-1)
Z = np.insert(np.random.normal(size=N-1), 0, 0)
X = np.exp((r-d-vol**2/2) * np.linspace(0,T,N) + np.cumsum(vol * math.sqrt(dt) * Z))
path = spot *  X
return path
def make_time(T,N):
return np.linspace(0,T,N)
def hedging_portfolio(path, strike, r, d, vol, T):
t = make_time(T,len(path))
alpha = delta_of_call(path[:-1], strike, r, d, vol, T-t[:-1])
cashflow = alpha * (path[1:] - path[:-1])
return np.sum(cashflow)
spot = 100
strike = 100
r = 0.0
d = 0.0
vol = 0.1
T = 1
N = 10000
path = make_path(spot,r,d,vol,T,N)
x = (hedging_portfolio(path, strike,r, d, vol, T), max(path[-1]-strike,0) - call_option(spot,strike,r,d,vol,T))
print(x)

Edit: I realized part of my mistake. First, as pointed out by Ivan, my path generation had a typo but this was not the source of the problem since r=0 in my example. The problem was that I was comparing the cost of setting up this portfolio to the final payoff, whereas I should look at the difference between the payoff and the price of the call option. I modified my code accordingly. This now works when interest rates are zero. When they are non zero, there is still a problem. The cost of setting up this portfolio should be equal to the difference between the payoff and the price of the call option.

• Why is the first term of X not inside the exponential ? – Ivan Oct 8 '19 at 11:35
• You are right this is an error though this is not quite the problem since I was looking at 0 interest rates. I will edit my question. – user11823918 Oct 8 '19 at 11:48
• Which coding language/platform has been used for this? – Ussu Oct 8 '19 at 12:24
• @user11823918 you still have the volatility there though. It’s bound to mess up your paths. – Ivan Oct 8 '19 at 13:31
• @Ivan I don't get it, why shouldn't there be a volatility term? – user11823918 Oct 9 '19 at 7:20

Ok, I found the problem. I was not discounting the value according to interest rate. The following modified code works fine for non-zero interest rate. When dividends rate are non zero, it is probably better to hedge using a forward contract instead of the asset itself. I will skip this for now.

def hedging_portfolio(path, strike, r, d, vol, T):
t = make_time(T,len(path))
dt = t[1]
alpha = delta_of_call(path[:-1], strike, r, d, vol, T-t[:-1])
cashflow = alpha * (path[1:] - path[:-1]*np.exp(r*dt))*np.exp(r*(T-t[1:]))
return np.sum(cashflow)
path = make_path(spot,r,d,vol,T,N)
x = hedging_portfolio(path, strike,r, d, vol, T)
y = max(path[-1]-strike,0) - call_option(spot,strike,r,d,vol,T)*np.exp(r*T)
print(x)
print(y)

Now $$x=y$$ as wanted.