1. LEARNING OBJECTIVES
By the end of this lesson, you will be able to:
-
Understand the concept of risk-neutral pricing and the role of the martingale measure.
-
Apply the Girsanov Theorem to change from the real-world measure P to the risk-neutral measure Q.
-
Derive the risk-neutral dynamics of asset prices under Q.
-
Price European derivatives using the risk-neutral expectation formula.
-
Understand the relationship between the market price of risk and the drift adjustment.
-
Price interest rate derivatives using the forward measure.
-
Understand the concept of numeraire and change of numeraire.
-
Apply the martingale pricing framework to exotic options.
2. THE RISK-NEUTRAL PRICING FRAMEWORK
2.1 The Concept of Risk-Neutral Pricing
In the real world, investors require a risk premium for holding risky assets. Under the risk-neutral measure Q, investors are indifferent to risk, and all assets earn the risk-free rate r.
2.2 The Fundamental Theorem of Asset Pricing
In an arbitrage-free market, there exists a risk-neutral measure Q such that all discounted asset prices are martingales:
E^Q[ e^{-rt} S_t | F_0 ] = S_0
Equivalently:
E^Q[ S_t | F_0 ] = S_0 e^{rt}
2.3 The Pricing Formula
For a derivative with payoff H at time T:
V_0 = E^Q[ e^{-rT} H ]
For a derivative with payoff H at time T and price V_t at time t:
V_t = E^Q[ e^{-r(T-t)} H | F_t ]
3. DERIVING THE RISK-NEUTRAL DYNAMICS
3.1 Real-World Dynamics
Under the real-world measure P, an asset price follows:
dS_t = μ S_t dt + σ S_t dW_t^P
Where μ is the expected return (drift) and σ is the volatility.
3.2 The Market Price of Risk
The market price of risk (Sharpe ratio) is:
λ = (μ – r) / σ
This measures the excess return per unit of risk.
3.3 Applying the Girsanov Theorem
Define the Radon-Nikodym derivative:
dQ/dP = exp( -∫_0^T λ dW_t^P – (1/2) ∫_0^T λ² dt )
By Girsanov, under Q:
dW_t^Q = dW_t^P + λ dt
3.4 Risk-Neutral Dynamics
Substitute into the real-world dynamics:
dS_t = μ S_t dt + σ S_t (dW_t^Q – λ dt)
dS_t = μ S_t dt – σ S_t λ dt + σ S_t dW_t^Q
dS_t = μ S_t dt – (μ – r) S_t dt + σ S_t dW_t^Q
dS_t = r S_t dt + σ S_t dW_t^Q
Therefore, under Q, the drift is r (the risk-free rate).
3.5 The Risk-Neutral Solution
The risk-neutral solution is:
S_t = S_0 * exp( (r – (1/2) σ²) t + σ W_t^Q )
4. PRICING A EUROPEAN CALL OPTION
4.1 The Payoff
The payoff of a European call option at maturity T is:
H = max(S_T – K, 0)
4.2 The Risk-Neutral Price
V_0 = e^{-rT} E^Q[ max(S_T – K, 0) ]
4.3 Evaluating the Expectation
Under Q, S_T is log-normally distributed:
S_T = S_0 * exp( (r – (1/2) σ²) T + σ W_T^Q )
Let W_T^Q = Z * √T, where Z ~ N(0, 1).
Then:
S_T = S_0 * exp( (r – (1/2) σ²) T + σ √T Z )
The expectation is:
E^Q[ max(S_T – K, 0) ] = ∫_{d_2}^{∞} (S_0 e^{(r – (1/2)σ²)T + σ√T z} – K) * (1/√(2Ï€)) e^{-z²/2} dz
Evaluating this integral gives the Black-Scholes formula:
V_0 = S_0 N(d_1) – K e^{-rT} N(d_2)
Where:
d_1 = [ ln(S_0 / K) + (r + σ²/2) T ] / (σ √T)
d_2 = d_1 – σ √T
5. PRICING A EUROPEAN PUT OPTION
5.1 The Payoff
The payoff of a European put option at maturity T is:
H = max(K – S_T, 0)
5.2 The Risk-Neutral Price
V_0 = e^{-rT} E^Q[ max(K – S_T, 0) ]
5.3 Put-Call Parity
The put-call parity relationship is:
C – P = S_0 – K e^{-rT}
Therefore:
P = C – S_0 + K e^{-rT}
P = K e^{-rT} N(-d_2) – S_0 N(-d_1)
6. THE MARKET PRICE OF RISK AND THE RISK PREMIUM
6.1 The Market Price of Risk
The market price of risk λ is the compensation required for bearing one unit of risk:
λ = (μ – r) / σ
6.2 The Risk Premium
The risk premium is the excess return over the risk-free rate:
Risk_Premium = μ – r = λ σ
6.3 Interpreting the Market Price of Risk
-
If λ > 0, the asset is positively correlated with the market (investors require a positive risk premium).
-
If λ < 0, the asset is negatively correlated with the market (negative risk premium, e.g., gold, insurance).
-
If λ = 0, the asset is risk-neutral (no risk premium).
7. THE FORWARD MEASURE AND NUMERAIRE
7.1 The Concept of Numeraire
A numeraire is a strictly positive asset used as a reference for pricing. Under the risk-neutral measure Q, the money market account B_t = e^{rt} is the numeraire.
7.2 Change of Numeraire
We can change from one numeraire to another. The forward measure Q^T uses the zero-coupon bond P(t, T) as numeraire.
The Radon-Nikodym derivative for changing from Q to Q^T is:
dQ^T / dQ = B_T P(0, T) / B_0 = e^{rT} P(0, T)
7.3 Pricing Under the Forward Measure
Under the forward measure Q^T:
V_0 = P(0, T) * E^{Q^T}[ H | F_0 ]
Where P(0, T) is the discount factor.
7.4 Application to Interest Rate Derivatives
For interest rate derivatives (caps, floors, swaptions), the forward measure is often used because the discount factor is stochastic.
8. PRICING EXOTIC OPTIONS
8.1 Asian Options
An Asian option has a payoff based on the average price over the option’s life.
Payoff (Call):
H = max( (1/N) Σ_{i=1}^N S_{t_i} – K, 0 )
Pricing:
V_0 = e^{-rT} E^Q[ max( (1/N) Σ S_{t_i} – K, 0 ) ]
Asian options have no closed-form solution. They are priced using Monte Carlo simulation.
8.2 Barrier Options
A barrier option has a payoff that is activated or deactivated when the underlying price crosses a barrier level.
Payoff (Up-and-Out Call):
H = max(S_T – K, 0) * 1_{max_{t≤T} S_t < B}
Where B is the barrier level.
Pricing:
V_0 = e^{-rT} E^Q[ max(S_T – K, 0) * 1_{max S_t < B} ]
Barrier options have closed-form solutions (using reflection principle) for simple cases.
8.3 Lookback Options
A lookback option has a payoff based on the maximum or minimum price over the option’s life.
Payoff (Lookback Call):
H = S_T – min_{t≤T} S_t
Pricing:
V_0 = e^{-rT} E^Q[ S_T – min S_t ]
Lookback options have closed-form solutions.
8.4 Monte Carlo Pricing
For exotic options without closed-form solutions, we use Monte Carlo simulation:
-
Generate M paths of S_t under Q.
-
Compute the payoff H_m for each path.
-
Average the payoffs: H_avg = (1/M) Σ H_m.
-
Discount: V_0 = e^{-rT} H_avg.
9. THE MARTINGALE PRICING FRAMEWORK IN PRACTICE
9.1 Step-by-Step Pricing Procedure
-
Identify the Underlying:Â Determine the asset(s) driving the derivative’s payoff.
-
Specify the Dynamics:Â Specify the SDE for the underlying under the real-world measure P.
-
Choose a Numeraire:Â Typically the money market account B_t = e^{rt}.
-
Change Measure:Â Apply Girsanov to find the dynamics under Q.
-
Compute the Payoff:Â Determine the derivative’s payoff at maturity.
-
Take the Expectation:Â Compute the expected payoff under Q.
-
Discount:Â Multiply by the discount factor to get the price.
9.2 Example: Forward Contract
A forward contract obligates the holder to buy the underlying at price K at time T.
The payoff is:
H = S_T – K
The price is:
V_0 = e^{-rT} E^Q[ S_T – K ] = e^{-rT} (E^Q[S_T] – K) = e^{-rT} (S_0 e^{rT} – K) = S_0 – K e^{-rT}
The forward price is the K that makes V_0 = 0:
F_0 = S_0 e^{rT}
9.3 Example: Digital Option
A digital option pays $1 if S_T > K.
The payoff is:
H = 1_{S_T > K}
The price is:
V_0 = e^{-rT} E^Q[ 1_{S_T > K} ] = e^{-rT} P^Q(S_T > K)
Since S_T is log-normal:
P^Q(S_T > K) = N(d_2)
Therefore:
V_0 = e^{-rT} N(d_2)
10. PRACTICAL IMPLEMENTATION
A. Black-Scholes Pricing:
import numpy as np from scipy.stats import norm def black_scholes_call(S0, K, T, r, sigma): d1 = (np.log(S0 / K) + (r + 0.5 * sigma**2) * T) / (sigma * np.sqrt(T)) d2 = d1 - sigma * np.sqrt(T) return S0 * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2) def black_scholes_put(S0, K, T, r, sigma): d1 = (np.log(S0 / K) + (r + 0.5 * sigma**2) * T) / (sigma * np.sqrt(T)) d2 = d1 - sigma * np.sqrt(T) return K * np.exp(-r * T) * norm.cdf(-d2) - S0 * norm.cdf(-d1) # Example S0 = 100 K = 100 T = 1.0 r = 0.03 sigma = 0.20 call_price = black_scholes_call(S0, K, T, r, sigma) put_price = black_scholes_put(S0, K, T, r, sigma) print(f"Call Price: {call_price:.4f}") print(f"Put Price: {put_price:.4f}") print(f"Put-Call Parity: {call_price - put_price:.4f} vs {S0 - K * np.exp(-r * T):.4f}")
B. Monte Carlo Pricing Under Q:
def monte_carlo_euro_call(S0, K, T, r, sigma, n_paths, n_steps): dt = T / n_steps S = np.zeros((n_paths, n_steps + 1)) S[:, 0] = S0 for i in range(n_steps): dW = np.random.normal(0, np.sqrt(dt), n_paths) S[:, i+1] = S[:, i] + r * S[:, i] * dt + sigma * S[:, i] * dW payoffs = np.maximum(S[:, -1] - K, 0) price = np.exp(-r * T) * np.mean(payoffs) se = np.exp(-r * T) * np.std(payoffs) / np.sqrt(n_paths) return price, se # Example price_mc, se_mc = monte_carlo_euro_call(S0, K, T, r, sigma, 100000, 100) print(f"Monte Carlo Price: {price_mc:.4f} ± {se_mc:.4f}") print(f"Black-Scholes Price: {call_price:.4f}") print(f"Difference: {price_mc - call_price:.4f}")
C. Forward Price Calculation:
def forward_price(S0, T, r): return S0 * np.exp(r * T) F0 = forward_price(S0, T, r) print(f"Forward Price: {F0:.4f}") # Verify: Value of forward is 0 at inception forward_value = S0 - F0 * np.exp(-r * T) print(f"Forward Value at Inception: {forward_value:.4f}")
D. Digital Option Pricing:
def digital_call(S0, K, T, r, sigma): d2 = (np.log(S0 / K) + (r - 0.5 * sigma**2) * T) / (sigma * np.sqrt(T)) return np.exp(-r * T) * norm.cdf(d2) digital_price = digital_call(S0, K, T, r, sigma) print(f"Digital Call Price: {digital_price:.4f}")