Skip to content
All library documents

Correcting the Drift in Lognormal Black–Scholes Simulations

Article Quant Q&A · Author: herbertmm

Summary

The document examines a Monte Carlo simulation of a European call under the Black–Scholes–Merton model. It contrasts compounding normally distributed simple returns with exponentiating normally distributed log returns, then gives the drift adjustment needed for the latter process to have the model’s expected terminal stock value. With continuously compounded risk-free rate r and volatility σ, the simulated log return should have mean r minus one half of the variance over the time step, while its standard deviation scales with volatility and the square root of elapsed time.

The response explains that exponentiation adds a positive expected-value effect, so a zero-mean normal log return does not produce a stock process with zero expected growth. The variance correction offsets that effect; the risk-free drift then gives the required expectation. The example concerns a risk-neutral Black–Scholes simulation, and does not establish that this process fits real-world returns or address other modeling choices such as dividends. The shown Monte Carlo averages are illustrative rather than a reported statistical study.

Key ideas

  • Black–Scholes assumes a lognormal terminal stock price with expected value growing at the risk-free rate under the pricing measure.
  • A normal log return with zero mean produces an upward expected price effect after exponentiation.
  • The log-return drift includes a negative half-variance adjustment alongside the risk-free rate.
  • Monte Carlo estimates should be interpreted within the model assumptions and can vary due to sampling noise.

Tags

Full text
# lognormal assumption of Black Scholes


# lognormal assumption of Black Scholes












I have recently started learning about option pricing and the Black Scholes formula, where stock prices are assumed to be lognormally distributed and returns normally distributed. While trying to do some simulations to learn more about the parameters and their behaviour I noticed that I seem to be misapplying the concept of the stock prices being lognormal. Please see the code below in python where I simulate a 30 day call option with daily price changes, where if I try to use lognormal prices I converge on about 0.4~ EV versus breakeven, which is expected, if I just use regular normally distributed returns, which would allow for negative stock prices.

```
import scipy.stats as stats
import numpy as np
import matplotlib.pyplot as plt

def black_scholes(S, K, r, T, sigma, option="call"):
    d1, d2 = d(S, K, r, T, sigma)

    if option == "call":
        return (S * stats.norm.cdf(d1, 0, 1) - K * np.exp(-r * T) * stats.norm.cdf(d2, 0, 1))
    elif option == "put":
        return (K * np.exp(-r * T) * stats.norm.cdf(-d2, 0, 1) - S * stats.norm.cdf(-d1, 0, 1))

def d(S, K, r, T, sigma):
    d1 = (np.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
    d2 = d1 - sigma * np.sqrt(T)
    return d1, d2

price = 100
strike = 105
r = 0
T = 30/365
sigma = 0.5
option = "call"

cost = black_scholes(price,strike,r,T,sigma,option) # = 3.69...

avg_gains = []
avg_gains_logn = []
for _ in range(1000):
    runs = {n:None for n in range(1000)}
    runs_logn = {n:None for n in range(1000)}
    for run in runs:
        p = price
        p_logn = price
        for _ in range(30):
            c = np.random.normal(0,sigma/np.sqrt(365))
            p *= 1+c
            p_logn *= np.exp(c)
        runs[run] = p
        runs_logn[run] = p_logn

    gains = []
    gains_logn = []
    for n, result in runs.items():
        gains.append(max(0, result - strike) - cost)
        gains_logn.append(max(0, runs_logn[n] - strike) - cost)

    avg_gains.append(sum(gains)/1000)
    avg_gains_logn.append(sum(gains_logn)/1000)

plt.plot(avg_gains)
plt.plot(avg_gains_logn)
plt.show()
print(sum(avg_gains)/1000, sum(avg_gains_logn)/1000)
```

## Answer by Kermittfrog (score 1)

https://quant.stackexchange.com/a/51846

Under the BSM model, the terminal stock price is assumed to be lognormally distributed, with expected value equal to $\mathrm{E}_t(S_T)=S_0e^{r(T-t)}$. In order to achieve this in your simulation (of your log-normal stock process), you may want to modify your code:

```
c = np.random.normal(r-0.5*sigma**2/365, sigma/np.sqrt(365)) # instead of mean=0
```

This ensures that the drift induced by the exponentiation of the logarithmic return is cancelled, i.e.

$$ \mathrm{E}\left(e^{\left(r-\frac{1}{2}\sigma^2\right)(T-t)+\sigma\sqrt{(T-t)}z_{0,1}}\right)=e^{r(T-t)} $$

In your case, $r=0$, so only the correction for the volatility is required during simulation.

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.