QF-Learn

The binomial option pricing model, step by step

The binomial option pricing model values an option by letting the stock move only up or down in each time step, building a tree of possible prices, and working backwards from expiry to today. In each step the option is worth its discounted expected value under the risk-neutral probability.

John Cox, Stephen Ross and Mark Rubinstein published it in 1979. It is the easiest way to see why options have the price they do, and unlike Black-Scholes it handles American options, which can be exercised early.

One step, by hand

A stock is at 100. In one year it will be at either 120 or 80. A call with strike 100 then pays 20 or 0. The risk-free rate is 5%. What is the call worth today?

Build a portfolio that pays the same in both cases. Buy Δ shares and borrow B: it pays 120Δ − Be0.05 if the stock goes up and 80Δ − Be0.05 if down. Matching 20 and 0 gives Δ = 20/40 = 0.5 shares and a loan worth 38.05 today. The portfolio costs 0.5 × 100 − 38.05 = 11.95, so the call must cost 11.95 too, or there is a free profit.

The same price comes from a probability. The risk-neutral probability of an up move is:

p = (erΔt − d) / (u − d) = (e0.05 − 0.8) / (1.2 − 0.8) = 0.6282

and the call is the discounted expected payoff: e−0.05 × (0.6282 × 20 + 0.3718 × 0) = 11.95.

Python
from math import exp

S, K, r, T = 100, 100, 0.05, 1.0
u, d = 1.2, 0.8                         # the stock ends at 120 or 80
p = (exp(r * T) - d) / (u - d)          # risk-neutral probability of "up"
call_up, call_down = max(S * u - K, 0), max(S * d - K, 0)
price = exp(-r * T) * (p * call_up + (1 - p) * call_down)
print(f"p = {p:.4f}")
print(f"call = {price:.4f}")

# The same price from a replicating portfolio: delta shares plus borrowing
delta = (call_up - call_down) / (S * u - S * d)
borrow = exp(-r * T) * (delta * S * d - call_down)
print(f"delta = {delta:.2f} shares, borrow {borrow:.4f}")
print(f"cost of replicating portfolio = {delta * S - borrow:.4f}")
Output
p = 0.6282
call = 11.9508
delta = 0.50 shares, borrow 38.0492
cost of replicating portfolio = 11.9508

Notice what is missing: nobody’s view of whether the stock will rise. The real-world probability never enters. That is the central idea of derivatives pricing.

Growing the tree

With many small steps, Cox, Ross and Rubinstein set the up and down factors from the volatility so the tree matches geometric Brownian motion:

u = eσ√Δt,   d = 1/u,   p = (erΔt − d) / (u − d)

Start at the last column, where each node’s value is the payoff. Step back one column at a time: each node is e−rΔt × (p × up value + (1 − p) × down value). For an American option, also compare with exercising now and keep the larger.

Python
from math import exp, sqrt


def crr_price(S, K, T, r, sigma, steps, kind="call", american=False):
    """Cox-Ross-Rubinstein binomial tree."""
    dt = T / steps
    u = exp(sigma * sqrt(dt))
    d = 1 / u
    p = (exp(r * dt) - d) / (u - d)          # risk-neutral up probability
    disc = exp(-r * dt)
    sign = 1 if kind == "call" else -1
    # option values at expiry, from the lowest node up
    values = [max(sign * (S * u**j * d**(steps - j) - K), 0.0) for j in range(steps + 1)]
    for i in range(steps - 1, -1, -1):
        for j in range(i + 1):
            cont = disc * (p * values[j + 1] + (1 - p) * values[j])
            if american:
                cont = max(cont, sign * (S * u**j * d**(i - j) - K))
            values[j] = cont
    return values[0]


for steps in (1, 2, 10, 100, 1000):
    print(f"{steps:>5} steps: call = {crr_price(100, 100, 1, 0.05, 0.2, steps):.4f}")
print("Black-Scholes: call = 10.4506")
print(f"European put = {crr_price(100, 100, 1, 0.05, 0.2, 1000, 'put'):.4f}")
print(f"American put = {crr_price(100, 100, 1, 0.05, 0.2, 1000, 'put', american=True):.4f}")
Output
1 steps: call = 12.1623
    2 steps: call = 9.5405
   10 steps: call = 10.2534
  100 steps: call = 10.4306
 1000 steps: call = 10.4486
Black-Scholes: call = 10.4506
European put = 5.5715
American put = 6.0896
Binomial price converging to Black-ScholesThe binomial price of a one-year at-the-money call zig-zags around the Black-Scholes value of 10.4506 and closes in on it as the number of steps grows from 1 to 60.101112102030405060Number of stepsCall priceBinomial (CRR) priceBlack-Scholes 10.4506
The tree’s price oscillates between odd and even step counts while it converges.

American options and early exercise

With 1,000 steps the European put is worth 5.5715 and the American put 6.0896. The difference, about 0.52, is the value of being allowed to exercise early: when the stock falls far enough, taking the strike now and earning interest on it beats waiting. For a call on a stock with no dividends, early exercise is never optimal, so American and European calls are worth the same.

The tree also checks put-call parity: the European prices from the same tree satisfy it, and the American ones only satisfy its inequality version.

Learn this on your phone, one short lesson at a time

QF-Learn turns topics like this into five-minute lessons with quizzes, finance games and certificates. It is free, and it is coming to Android and iOS. Leave your email and you will be first to get it.