Itô's Lemma and Stochastic Calculus › Code Implementation
Quantitative FinanceAll chapters Itô's Lemma and Stochastic Calculus › Code ImplementationOne section · Sections in this chapter6 / 11 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Let's implement simulations to verify our analytical results from Itô's Lemma.
import numpy as np
np.random.seed(42)
def simulate_gbm(S0, mu, sigma, T, n_steps, n_paths):
"""
Simulate geometric Brownian motion paths using Euler-Maruyama discretization.
Parameters:
-----------
S0 : float - Initial price
mu : float - Drift rate
sigma : float - Volatility
T : float - Time horizon
n_steps : int - Number of time steps
n_paths : int - Number of simulation paths
Returns:
--------
t : array - Time points
S : array - Simulated price paths (n_steps+1 x n_paths)
W : array - Brownian motion paths (n_steps+1 x n_paths)
"""
dt = T / n_steps
t = np.linspace(0, T, n_steps + 1)
# Generate random increments
dW = np.random.normal(0, np.sqrt(dt), (n_steps, n_paths))
# Build Brownian motion paths
W = np.zeros((n_steps + 1, n_paths))
W[1:, :] = np.cumsum(dW, axis=0)
# Simulate price paths using Euler-Maruyama
S = np.zeros((n_steps + 1, n_paths))
S[0, :] = S0
for i in range(n_steps):
S[i + 1, :] = S[i, :] * (1 + mu * dt + sigma * dW[i, :])
return t, S, WVerifying the GBM Solution
We derived that . Let's compare the Euler-Maruyama simulation with the exact solution.
import numpy as np
# Parameters
S0 = 100
mu = 0.10 # 10% annual drift
sigma = 0.20 # 20% annual volatility
T = 1.0 # 1 year
n_steps = 252 # Daily steps
n_paths = 10000
# Simulate
t, S_euler, W = simulate_gbm(S0, mu, sigma, T, n_steps, n_paths)
# Compute exact solution at terminal time
S_exact = S0 * np.exp((mu - 0.5 * sigma**2) * T + sigma * W[-1, :])
# Calculate statistics for comparison
euler_mean = np.mean(S_euler[-1, :])
exact_mean = np.mean(S_exact)
euler_std = np.std(S_euler[-1, :])
exact_std = np.std(S_exact)
euler_median = np.median(S_euler[-1, :])
exact_median = np.median(S_exact)
euler_p5 = np.percentile(S_euler[-1, :], 5)
exact_p5 = np.percentile(S_exact, 5)
euler_p95 = np.percentile(S_euler[-1, :], 95)
exact_p95 = np.percentile(S_exact, 95)Comparison of Euler-Maruyama vs Exact GBM Solution at T=1 ============================================================ Statistic Euler-Maruyama Exact ------------------------------------------------------------ Mean................ 110.3381 110.3435 Std Dev............. 22.1806 22.1897 Median.............. 108.2752 108.2616 5th Percentile...... 77.9855 77.9685 95th Percentile..... 150.0485 150.0308
The Euler-Maruyama approximation closely matches the exact solution, with small differences due to the discretization error.


Verifying the Log-Return Distribution
Itô's Lemma tells us that .
import numpy as np
from scipy import stats
# Compute log returns from exact solution
log_returns = np.log(S_exact / S0)
# Theoretical parameters
theoretical_mean = (mu - 0.5 * sigma**2) * T
theoretical_std = sigma * np.sqrt(T)
# Simulated statistics
sim_mean = np.mean(log_returns)
sim_std = np.std(log_returns)
# Normality test
_, p_value = stats.shapiro(np.random.choice(log_returns, 5000, replace=False))Log-Return Distribution Analysis ================================================== Theoretical (from Itô's Lemma): Mean: 0.080000 Std Dev: 0.200000 Simulated: Mean: 0.078533 Std Dev: 0.199612 Shapiro-Wilk normality test p-value: 0.7918 (High p-value supports normality)
The simulated log-returns match the theoretical distribution predicted by Itô's Lemma, and the Shapiro-Wilk test confirms normality.


Visualizing the Itô Correction
The Itô correction has a significant impact, especially for high volatility. Let's visualize this.
import numpy as np
sigmas = np.linspace(0, 0.8, 100)
mu_fixed = 0.10
# Expected simple return (approximately mu*T for small dt)
expected_simple_return = mu_fixed
# Expected log return
expected_log_return = mu_fixed - 0.5 * sigmas**2
This graph illustrates why high-volatility assets can have positive expected returns but negative expected log-returns. For example, with and , the expected log-return is only . At , the expected log-return becomes negative despite the positive drift! This phenomenon has large implications for long-term investing and helps explain why highly volatile assets can be poor long-term investments even when their expected single-period returns are positive.
Verifying the Exponential Martingale
We showed that is a martingale. Let's verify that .
import numpy as np
# Simulate the exponential martingale
sigma_m = 0.3
T_m = 2.0
n_paths_m = 50000
# Generate terminal Brownian motion values
W_T = np.random.normal(0, np.sqrt(T_m), n_paths_m)
# Compute Y_T
Y_T = np.exp(sigma_m * W_T - 0.5 * sigma_m**2 * T_m)
# Also compute without the correction (not a martingale)
Y_T_wrong = np.exp(sigma_m * W_T)
# Compute statistics
mean_Y_T = np.mean(Y_T)
mean_Y_T_wrong = np.mean(Y_T_wrong)
theoretical_wrong = np.exp(0.5 * sigma_m**2 * T_m)Exponential Martingale Verification ================================================== With Itô correction (true martingale): E[Y_T] = 0.998446 (should be 1.0) Without correction (not a martingale): E[exp(σW_T)] = 1.092474 Theoretical: exp(½σ²T) = 1.094174
The exponential martingale with the correction has expected value 1, while the uncorrected version has expected value . This difference is precisely the Itô correction at work. The correction term in the exponent exactly compensates for the convexity of the exponential function, so the process has no drift.

