Euler–Maruyama vs Milstein: The Term That Matters
Discretizing a Stochastic Differential Equation
Most stochastic differential equations have no closed-form solution, so we simulate them on a grid. Given
$(1)$
we step forward in time with increments of the Brownian motion. But how well a scheme tracks the true path is not obvious, and the answer separates two classic methods by a full order of accuracy. This post measures that gap directly.
The right yardstick here is strong convergence — how close the numerical path stays to the exact path driven by the same Brownian motion:
$(2)$
The exponent $\gamma$ is the strong order. Bigger is better: halving $\Delta t$ cuts the error by $2^{\gamma}$.
A Test Equation We Can Grade
Geometric Brownian motion, $a(x)=\lambda x$ and $b(x)=\mu x$, has an exact solution driven by the same path:
$(3)$
So for any simulated path we can compute the true endpoint from $W_T$ and measure the error exactly — no reference discretization needed.
Euler–Maruyama: the Obvious Scheme
The direct analogue of the Euler method: freeze the coefficients over each step and add a Gaussian Brownian increment $\Delta W \sim \mathcal{N}(0, \Delta t)$.
Algorithm — Euler–Maruyama Step
input: X0, drift a(x), diffusion b(x), step Dt, number of steps L
X <- X0
for n = 1 .. L:
draw dW ~ Normal(0, Dt)
X <- X + a(X)*Dt + b(X)*dW
return X
Simple and cheap — but its strong order is only $\gamma = \tfrac{1}{2}$. The culprit is the term it silently drops.
Milstein: One More Term, Twice the Order
The Itô–Taylor expansion of the increment carries a second-order piece that Euler ignores. Because $\Delta W^2$ has mean $\Delta t$ (not zero), that piece contributes at first order. Milstein’s scheme keeps it:
$(4)$
Algorithm — Milstein Step
input: X0, a(x), b(x), b'(x), step Dt, number of steps L
X <- X0
for n = 1 .. L:
draw dW ~ Normal(0, Dt)
X <- X + a(X)*Dt + b(X)*dW + 0.5*b(X)*b_prime(X)*(dW*dW - Dt)
return X
The price is one extra term and the requirement that you know the derivative $b'(x)$ of the diffusion — for GBM, $b(x)=\mu x$ so $b'(x)=\mu$. The payoff is strong order $\gamma = 1$.
The Experiment
Simulate both schemes on the same Brownian paths at a range of step sizes, and measure the strong error against the exact solution:
Python 3.13 — Strong Convergence of Euler–Maruyama and Milstein
import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
rng = np.random.default_rng(1)
lam, mu, X0, T = 1.0, 0.5, 1.0, 1.0 # dX = lam*X dt + mu*X dW (GBM)
N = 2**12; dt = T/N; M = 2000 # fine grid, M paths
dW = rng.normal(0.0, np.sqrt(dt), size=(M, N))
Xtrue = X0*np.exp((lam - 0.5*mu**2)*T + mu*dW.sum(axis=1)) # exact endpoint
def strong_err(scheme, R): # R = coarsening factor
L = N // R; Dt = R*dt
dWc = dW[:, :L*R].reshape(M, L, R).sum(axis=2) # coarse increments
X = np.full(M, float(X0))
for j in range(L):
dWj = dWc[:, j]
if scheme == "euler":
X = X + lam*X*Dt + mu*X*dWj
else: # milstein: b=mu*X, b'=mu
X = X + lam*X*Dt + mu*X*dWj + 0.5*mu**2*X*(dWj**2 - Dt)
return Dt, np.mean(np.abs(X - Xtrue))
dts, ee, me = [], [], []
for R in [2**p for p in range(1, 9)]:
Dt, e = strong_err("euler", R); dts.append(Dt); ee.append(e)
_, m = strong_err("milstein", R); me.append(m)
se = np.polyfit(np.log(dts), np.log(ee), 1)[0] # measured slopes
sm = np.polyfit(np.log(dts), np.log(me), 1)[0]
NAVY, TEAL = "#1e3a5f", "#2a9d8f"
fig, ax = plt.subplots(figsize=(10, 5), facecolor="white")
ax.semilogy(dts, ee, "o-", color=NAVY, lw=1.6, ms=7, label=f"Euler-Maruyama (order {se:.2f})")
ax.semilogy(dts, me, "s-", color=TEAL, lw=1.6, ms=7, label=f"Milstein (order {sm:.2f})")
ax.set_xlabel(r"time step $\Delta t$")
ax.set_ylabel(r"strong error $\mathbb{E}\,|X_T^{\Delta t} - X_T|$")
ax.set_title("Strong convergence on GBM: Euler-Maruyama vs Milstein")
ax.legend(framealpha=0.7)
ax.spines[["top", "right"]].set_visible(False)
ax.grid(True, which="major", axis="y", alpha=0.25)
fig.tight_layout(pad=1.5)
fig.savefig("fig_1.png", dpi=150, bbox_inches="tight")

What the Slopes Say
The fitted slopes come out Euler $\approx 0.54$ and Milstein $\approx 0.99$ — right on the theoretical $\tfrac{1}{2}$ and $1$. That is not a cosmetic difference: at $\Delta t = 10^{-3}$ the Milstein error is already an order of magnitude smaller, and the gap widens as the grid refines. One extra term, evaluated at no meaningful extra cost, buys a full order of strong accuracy.
When Each One Wins
Milstein is the clear choice for a scalar SDE whenever you can write down $b'(x)$ — which is most of the time. Euler–Maruyama keeps its place for two honest reasons: it needs no derivative of the diffusion, and in the multidimensional case Milstein’s correction involves iterated Itô integrals (Lévy areas) that are awkward to simulate, so the simple scheme is often what survives contact with a real model. And if you only care about weak convergence — expectations of payoffs rather than pathwise accuracy — both schemes are order one, and the picture changes again. But for tracking a path, the lesson of the plot is blunt: the term Euler drops is the term that matters.
Need a reliable numerical implementation for your problem? Get in touch.