CONTENTS

Monte Carlo Pricing (Basic)

Motivation: why this matters in quant finance

Risk-neutral valuation says the price of any European-style payoff XX is

V0=erTEQ[X(ST)].V_0 = e^{-rT}\,\mathbb{E}^{\mathbb{Q}}[X(S_T)].
For Black-Scholes vanillas, this expectation has a closed form. For almost everything else — basket options, path-dependent payoffs (Asians, lookbacks, barriers), models with stochastic volatility or jumps, multi-asset products, models calibrated to vol surfaces with no analytic solution — there is no closed form, and the integral has to be computed numerically.
Monte Carlo is the workhorse: simulate NN sample paths under Q\mathbb{Q}, compute the payoff on each, average and discount. The error converges as O(N1/2)O(N^{-1/2}) — slow, but independent of the dimension of the problem, which is why it dominates over deterministic quadrature in any setting with more than a few state variables.

This note develops the basic technique: how to discretise an SDE under Q\mathbb{Q}, generate paths, estimate the price, and quantify the standard error. Variance-reduction techniques that improve on the basic method are covered in the antithetic, control variate, importance sampling, and quasi-MC lessons.

The informal idea

Three steps.

  1. Simulate. Generate NN independent realisations ST(1),ST(2),,ST(N)S^{(1)}_T, S^{(2)}_T, \dots, S^{(N)}_T of the underlying at maturity (or paths if path-dependent).
  2. Evaluate. Compute payoffs Xi=X(ST(i))X_i = X(S^{(i)}_T).
  3. Average and discount.
V^0=erT1Ni=1NXi.\hat V_0 = e^{-rT} \cdot \frac{1}{N}\sum_{i=1}^N X_i.

By the law of large numbers, V^0V0\hat V_0 \to V_0 as NN \to \infty. By the CLT, the standard error is

SE(V^0)=erTσXN,\text{SE}(\hat V_0) = e^{-rT} \cdot \frac{\sigma_X}{\sqrt{N}},

where σX\sigma_X is the (estimated) standard deviation of the discounted payoff. A 95% confidence interval is V^0±1.96SE\hat V_0 \pm 1.96 \cdot \text{SE}.

Formal statement

Let XX be a payoff with finite second moment under Q\mathbb{Q}, and let X1,,XNX_1, \dots, X_N be i.i.d. Q\mathbb{Q}-distributed copies. The Monte Carlo estimator is

V^0=erTXˉN,XˉN=1Ni=1NXi.\hat V_0 = e^{-rT} \bar X_N, \quad \bar X_N = \frac{1}{N}\sum_{i=1}^N X_i.
Properties.
  • Unbiased: EQ[V^0]=V0\mathbb{E}^{\mathbb{Q}}[\hat V_0] = V_0.
  • Consistent: V^0V0\hat V_0 \to V_0 a.s. by the strong law.
  • Asymptotically normal: N(XˉNE[X])/σXN(0,1)\sqrt{N}(\bar X_N - \mathbb{E}[X])/\sigma_X \to N(0,1) in distribution.
  • MSE: E[(V^0V0)2]=e2rTσX2/N\mathbb{E}[(\hat V_0 - V_0)^2] = e^{-2rT}\sigma_X^2/N.

The standard deviation σX\sigma_X is estimated from the sample as σ^X=1N1(XiXˉN)2\hat\sigma_X = \sqrt{\frac{1}{N-1}\sum (X_i - \bar X_N)^2}.

Convergence rate. The error decays as O(N1/2)O(N^{-1/2}), which means: to halve the error, multiply NN by 4. To gain one decimal digit (factor 10 reduction), multiply NN by 100. This is slow compared to deterministic methods but does not deteriorate with dimension.

Algorithm: pricing a European call under Black-Scholes

Under Q\mathbb{Q}, ST=S0exp((rσ2/2)T+σTZ)S_T = S_0\exp((r - \sigma^2/2)T + \sigma\sqrt{T}Z) with ZN(0,1)Z \sim N(0,1).

For a European call with strike KK:

import numpy as np def mc_european_call(S0, K, T, r, sigma, N=100_000, seed=42): rng = np.random.default_rng(seed) Z = rng.standard_normal(N) ST = S0 * np.exp((r - 0.5 * sigma**2) * T + sigma * np.sqrt(T) * Z) payoff = np.maximum(ST - K, 0.0) discounted = np.exp(-r * T) * payoff price = discounted.mean() se = discounted.std(ddof=1) / np.sqrt(N) return price, se S0, K, T, r, sigma = 100, 100, 1.0, 0.05, 0.2 price, se = mc_european_call(S0, K, T, r, sigma, N=100_000) print(f"MC price: {price:.4f} ± {1.96*se:.4f} (95% CI)") # MC price: 10.4287 ± 0.0901 (95% CI)

The closed-form Black-Scholes price is 10.450610.4506 — well within the confidence interval.

Algorithm: path-dependent payoffs

For payoffs depending on the path {St}t[0,T]\{S_t\}_{t\in[0,T]} — Asians (average), lookbacks (max/min), barriers (hitting times) — discretise the time axis and simulate the path.
For geometric Brownian motion, the exact discretisation is
Stk+1=Stkexp((rσ2/2)Δt+σΔtZk),S_{t_{k+1}} = S_{t_k}\exp((r - \sigma^2/2)\Delta t + \sigma\sqrt{\Delta t}Z_k),

with independent ZkN(0,1)Z_k \sim N(0,1). No discretisation error — the multiplicative log-normal structure means each step is exactly the GBM increment.

def mc_asian_call(S0, K, T, r, sigma, M=50, N=100_000, seed=42): rng = np.random.default_rng(seed) dt = T / M Z = rng.standard_normal((N, M)) increments = (r - 0.5 * sigma**2) * dt + sigma * np.sqrt(dt) * Z log_paths = np.log(S0) + np.cumsum(increments, axis=1) paths = np.exp(log_paths) avg = paths.mean(axis=1) payoff = np.maximum(avg - K, 0.0) discounted = np.exp(-r * T) * payoff return discounted.mean(), discounted.std(ddof=1) / np.sqrt(N) price, se = mc_asian_call(100, 100, 1.0, 0.05, 0.2, M=50, N=100_000) print(f"Asian call: {price:.4f} ± {1.96*se:.4f}") # Asian call: 5.7720 ± 0.0467

Algorithm: SDEs without closed-form increments

For more general SDEs dSt=μ(St,t)dt+σ(St,t)dWtdS_t = \mu(S_t,t)dt + \sigma(S_t,t)dW_t, Euler-Maruyama gives
Stk+1=Stk+μ(Stk,tk)Δt+σ(Stk,tk)ΔtZk.S_{t_{k+1}} = S_{t_k} + \mu(S_{t_k},t_k)\Delta t + \sigma(S_{t_k},t_k)\sqrt{\Delta t}Z_k.

Strong convergence rate O(Δt)O(\sqrt{\Delta t}), weak convergence rate O(Δt)O(\Delta t). For options pricing, weak convergence is what matters.

For Heston (stochastic vol), Euler is unstable for the variance process; Andersen's QE scheme or Lord-Koekkoek-Dijk's truncation is preferred. For jump-diffusions, simulate Poisson arrivals and inject jumps. These are model-specific corrections to the basic recipe.

Key properties

  • Dimensional independence. Convergence rate O(N1/2)O(N^{-1/2}) does not depend on the dimension. A 100-asset basket option converges at the same rate as a 1-asset option (per sample), though each sample is more expensive.
  • Bias from discretisation. For non-GBM models discretised by Euler, MC includes both Monte Carlo error (O(N1/2)O(N^{-1/2})) and discretisation bias (O(Δt)O(\Delta t)). The true error decomposes; total compute scales as NMN \cdot M.
  • Variance reduction. Antithetic variates, control variates, importance sampling, stratified sampling, and quasi-MC all aim to reduce σX\sigma_X without increasing NN.
  • Greeks via MC. Greeks (delta, vega, etc.) can be computed by bumping inputs, by pathwise derivatives (when payoff is differentiable), or by likelihood-ratio estimators (when not). All have trade-offs in bias/variance.
  • Confidence interval \ne tolerance. A 95% CI half-width of \0.10doesnotmeanthepriceiscorrecttodoes not mean the price is correct to$0.10itsastatisticalbound.Foradeterministicguaranteeyoudneed— it's a statistical bound. For a deterministic guarantee you'd needN$ much larger or to use QMC.

Worked example: 95% CI sample size

Target: estimate a Black-Scholes ATM call price of magnitude \sim\10towithinto within\pm $0.05$ at 95% confidence.

Empirical \sigma_X \approx \15$ for ATM call (sample std of discounted payoff).

Need 1.96σX/N0.05N(1.9615/0.05)2=5882/0.0025= 346,0001.96 \cdot \sigma_X/\sqrt{N} \le 0.05 \Rightarrow N \ge (1.96 \cdot 15 / 0.05)^2 = 588^2/0.0025 = ~346,000.

So roughly N=350,000N = 350{,}000 paths give a \pm\0.059595% CI. To halve the CI to\pm$0.025,need, need N = 1.4M$. Slow.

This is exactly why variance reduction is mandatory for production pricing — naive MC at N=107N = 10^7 for a complex multi-asset model takes minutes per pricing, which kills any iterative use (calibration, real-time risk).

Common confusions and pitfalls

  • Using P\mathbb{P} instead of Q\mathbb{Q}. Pricing must be under the risk-neutral measure. Real-world drift gives wrong prices.
  • Forgetting the discount factor. V0=erTEQ[X]V_0 = e^{-rT}\mathbb{E}^{\mathbb{Q}}[X], not EQ[X]\mathbb{E}^{\mathbb{Q}}[X].
  • Random seed. Reproducibility matters — set seeds explicitly. Don't use np.random.seed and the default global RNG; use a Generator.
  • Discretisation bias. For path-dependent options on Black-Scholes, exact GBM discretisation has zero bias. For Heston, Euler can produce negative variance — kills the simulation. Use a proper scheme.
  • Antithetic doesn't always help. If the payoff is monotone in ZZ, antithetic gives big variance reduction. For symmetric payoffs (straddles, butterflies), antithetic provides little benefit.
  • Reporting "exact" prices. Always report the SE alongside the point estimate. A point estimate without uncertainty is misleading.
  • In-the-money paths only. For deeply OTM options, most paths contribute zero — variance per sample is dominated by rare ITM paths. Importance sampling fixes this.

Where this goes next

Exercises

Test your understanding with 3 exercises for this lesson.