Discounting the expected call values at the risk-free rate yields:
Another Example: Call with K = $95
Stock tree:
Call with strike $95:
Apply the same backward induction to fill in the intermediate and initial values.
Two-Period Example in Code
S =100K =95u =0.05# up return per periodr =0.03# interest rate per periodn =2# number of periodsd =1/(1+u) -1# down return per periodp = (r-d) / (u-d) # risk-neutral prob# Terminal stock prices and call payoffsx = [S*(1+u)**(n-2*i) for i inrange(n+1)]v = np.maximum(0, np.array(x)-K)# Backward inductionwhilelen(v) >1: v = (p*v[:-1] + (1-p)*v[1:]) / (1+r)print(f"Risk-neutral prob p = {p:.4f}")print(f"Call value (K={K}): ${v[0]:.2f}")
Risk-neutral prob p = 0.7951
Call value (K=95): $10.62
American Options: Early Exercise
At each intermediate node, compare continuation vs. immediate exercise:
Total nodes = \(\frac{(N+1)(N+2)}{2}\) (much less than \(2^N\) paths)
Backward induction is efficient: work one time step at a time
Interactive N-Period Trees
Figure 1: Experiment with N-period binomial trees: adjust interest rates, up/down factors, number of periods, and compare European vs. American option pricing.
Vectorized Implementation
import numpy as npdef binomial_american(S0, K, r, sigma, T, N, option_type='put'): dt = T / N u = np.exp(sigma * np.sqrt(dt)) d =1/ u p = (np.exp(r * dt) - d) / (u - d) disc = np.exp(-r * dt)# Terminal payoffs j = np.arange(N +1) S = S0 * u**j * d**(N - j) V = np.maximum(K - S, 0) if option_type =='put'else np.maximum(S - K, 0)# Backward inductionfor i inrange(N -1, -1, -1): j = np.arange(i +1) S = S0 * u**j * d**(i - j) V = disc * (p * V[1:i+2] + (1-p) * V[0:i+1]) exercise = np.maximum(K - S, 0) if option_type =='put'else np.maximum(S - K, 0) V = np.maximum(V, exercise)return V[0]print(f"American put: {binomial_american(100, 105, 0.05, 0.2, 1, 100, 'put'):.4f}")print(f"American call: {binomial_american(100, 105, 0.05, 0.2, 1, 100, 'call'):.4f}")
American put: 8.7476
American call: 8.0262
How the Algorithm Works
Vectorization: NumPy arrays compute all nodes at each time step simultaneously
Memory efficiency: Only store option values for the current time step
Backward induction logic:
Start with payoffs at maturity
At each prior step: discounted expected value of next period
Compare to immediate exercise (American feature)
Take the maximum
Parameter Calibration and Convergence
Parameter Calibration: CRR
Cox-Ross-Rubinstein parameters match the continuous-time limit:
\[u = \mathrm{e}^{\sigma\sqrt{\Delta t}}, \quad d = \frac{1}{u}, \quad p = \frac{\mathrm{e}^{(r-q)\Delta t} - d}{u - d}\]
\(\sigma\) = volatility of the underlying
\(q\) = dividend yield
Tree recombines:\(ud = 1\)
Converges to geometric Brownian motion as \(\Delta t \to 0\)
Convergence to Black-Scholes
Figure 2: Binomial model (blue dots) converges to the Black-Scholes limit (red line) as the number of time steps increases. Deviations are the same for calls and puts, reflecting put-call parity.
Summary: Key Takeaways
Replication: Option payoffs can be replicated with stock + borrowing
No-arbitrage pricing: Option value = cost of replicating portfolio
Risk-neutral probabilities: Value = discounted expected payoff under artificial probabilities
Backward induction: Work from maturity to today, comparing continuation vs. exercise at each node