SigmaField
Mathematical Foundations for Quant Finance
0 of 256 lessons
      1. 5.2.1 Random variables, PMFs and CDFsConcept · 25 min
      2. 5.2.2 Bernoulli, binomial and geometric distributionsConcept · 30 min
      3. 5.2.3 The Poisson distributionConcept · 30 min
      4. 5.2.4 Practice set: discrete distributionsPractice set · 25 min
      5. 5.2.5 Case study: the one-period binomial model, and counting defaultsCase study · 35 min

Level 5, Probability and statistics 5.2 Discrete random variables Lesson 5 of 5

Case studyLesson 5.2.5 in Level 5, Probability and statistics. About 35 minutes.

Case study: the one-period binomial model, and counting defaults

A portfolio of 100 loans

Each loan either defaults this year or does not: a Bernoulli trial with p=0.02p = 0.02 (lesson 5.2.2). Assume for now that the loans default independently of each other. Then the number of defaults XX is Bin⁡(100,0.02)\operatorname{Bin}(100, 0.02).

Many trials, each with a small chance: the Poisson approximation of lesson 5.2.3 applies, with λ=np=2\lambda = np = 2. Both pmfs, to four decimals:

defaults kk012345678
binomial0.13260.27070.27340.18230.09020.03530.01140.00310.0007
Poisson0.13530.27070.27070.18040.09020.03610.01200.00340.0009

A year with no defaults has probability 0.98100=0.13260.98^{100} = 0.1326. One or two defaults are the most likely counts, and the two rows never differ by more than 0.003.

Five or more defaults

Suppose the bank recovers 40% of a defaulted loan, so each default loses $600,000; desks call the 60% the loss given default. Then five or more defaults lose $3,000,000 or more.

By lesson 5.2.1, P(X≥5)=1−F(4)P(X \ge 5) = 1 - F(4). The binomial gives 0.0508 and the Poisson 0.0527. The Poisson has no upper limit and a slightly longer tail, so here it errs on the cautious side.

Try it

The first two lines print the table. The third gives P(X≥5)P(X \ge 5) as sf(4) for both distributions.

The last line is the off-by-one trap of lesson 5.2.2: binom.sf(5, …) is P(X>5)P(X > 5), which leaves out X=5X = 5.

⌘/Ctrl + Enter runs the cell

How many defaults to plan for

A risk manager asks the question the other way round: what is the smallest count exceeded in at most one year in a hundred? That is the smallest kk with F(k)≥0.99F(k) \ge 0.99, the 99% quantile of XX.

Here F(5)=0.9845F(5) = 0.9845 falls short and F(6)=0.9959F(6) = 0.9959 does not, so the answer is 6 defaults, or $3,600,000 of losses. The Poisson gives 6 as well. Case study 5.3.5 reads quantiles of daily returns the same way, as value at risk.

Try it

The cell simulates 100,000 years of the 100 loans with a fixed seed. In this run 0.0502 of the years have five or more defaults, against the exact 0.0508.

binom.ppf(0.99, …) returns the 99% quantile. The cell prints the distribution function on both sides of it, the Poisson's quantile and the loss.

⌘/Ctrl + Enter runs the cell
Check yourself
A colleague reports binom.sf(5, 100, 0.02) = 0.0155 as the probability of five or more defaults. What has gone wrong?

When defaults are not independent

Real defaults are not independent: in a recession many borrowers struggle at once. Here is a simple model of that. The year is good with probability 0.8, and then each loan defaults with probability 1%; it is bad with probability 0.2, and then 6%.

Within each kind of year the loans default independently, so XX is Bin⁡(100,0.01)\operatorname{Bin}(100, 0.01) in a good year and Bin⁡(100,0.06)\operatorname{Bin}(100, 0.06) in a bad one. The average default probability is 0.8×0.01+0.2×0.06=0.020.8 \times 0.01 + 0.2 \times 0.06 = 0.02, the same 2% as before.

The law of total probability (lesson 5.1.3) splits on the kind of year:

P(X≥5∣good)=0.0034P(X≥5∣bad)=0.7232P(X≥5)=0.8×0.0034+0.2×0.7232=0.1474\begin{gathered} P(X \ge 5 \mid \text{good}) = 0.0034 \\ P(X \ge 5 \mid \text{bad}) = 0.7232 \\[6pt] P(X \ge 5) = 0.8 \times 0.0034 \\ + 0.2 \times 0.7232 = 0.1474 \end{gathered}

That is almost three times the independent 0.0508. Quiet years become more likely too: no defaults at all has probability 0.2932, against 0.1326. The 99% quantile moves from 6 defaults to 10.

Defaults among 100 loans with the same 2% average. Independent, five or more happen with probability 0.051. Clustered in bad years, the pmf is taller at 0 and has a long tail: five or more has probability 0.147.

The strength of the dependence between defaults is measured by their correlation, which module 5.5 defines. A model that assumes independence understates the chance of many defaults together, which is the event that matters most to the bank.

Try it

The first lines check the 2% average and compute the tail by total probability. np.cumsum builds the distribution function of the clustered count, and argmax finds the first kk where it reaches 0.99.

The simulation first draws the kind of year, then the defaults. In this seeded run 0.1471 of the years have five or more, and the years still average 2.0 defaults.

⌘/Ctrl + Enter runs the cell

A stock that goes up or down

The same tools price an option. Take the call of case study 2.4.6: stock price S0=100S_0 = 100, strike K=100K = 100, T=0.5T = 0.5 years, a continuous rate r=0.03r = 0.03 and volatility σ=0.2\sigma = 0.2.

In the one-period binomial model, the stock has two possible prices at TT: S0uS_0 u if it goes up, S0dS_0 d if it goes down. A common choice, which case study 5.11.4 also uses, is u=eσTu = e^{\sigma\sqrt{T}} and d=1ud = \frac{1}{u}. Here u=1.15191u = 1.15191 and d=0.868123d = 0.868123, so the stock ends at 115.19 or 86.81.

A bond pays $1 at TT and costs e−rT=0.985112e^{-rT} = 0.985112 today, by continuous discounting (case study 1.4.6). The call pays max⁡(ST−100,0)\max(S_T - 100, 0) (case study 1.1.5): 15.19 if the stock goes up, nothing if it goes down.

One step of half a year. The branch labels are the risk-neutral probabilities found below; the call's price today, 7.75, comes from replication.

Replicating the call

Case study 3.3.4 priced a payoff by copying it with assets that trade. Here two assets cover two states. With rows down and up and columns the bond and the stock, the payoff matrix is

D=(186.811115.19)D = \begin{pmatrix} 1 & 86.81 \\ 1 & 115.19 \end{pmatrix}

Hold bb bonds and Δ\Delta (delta) shares. Copying the call means b+86.81Δ=0b + 86.81\Delta = 0 and b+115.19Δ=15.19b + 115.19\Delta = 15.19. Subtracting the first equation from the second gives Δ=15.1928.38=0.5353\Delta = \frac{15.19}{28.38} = 0.5353, and then b=−46.4703b = -46.4703: borrow by selling bonds.

Rule: Replicating a one-step payoff

Δ=Cu−CdS0u−S0d,b=Cd−ΔS0dprice=ΔS0+b e−rT\begin{gathered} \Delta = \frac{C_u - C_d}{S_0 u - S_0 d}, \quad b = C_d - \Delta S_0 d \\[4pt] \text{price} = \Delta S_0 + b\,e^{-rT} \end{gathered}

CuC_u and CdC_d are the payoffs in the up and down states. Δ\Delta shares and bb bonds pay exactly CuC_u and CdC_d. By the law of one price (case study 3.3.4), the payoff costs what they cost.

The portfolio costs 0.5353×100−46.4703×0.985112=53.53−45.78=7.75120.5353 \times 100 - 46.4703 \times 0.985112 = 53.53 - 45.78 = 7.7512. So the call is worth $7.75. Desks call Δ\Delta the option's delta, the number of shares that hedges it.

Try it

D has one row per state and one column per asset, as in case study 3.3.4. np.linalg.solve finds the bonds and shares that copy the call, and prices @ h is their cost today.

⌘/Ctrl + Enter runs the cell

The risk-neutral probability

Case study 3.3.4 also found state prices, the price today of $1 paid in one state only, by solving D⊤ψ=pD^\top\boldsymbol{\psi} = \mathbf{p}. Here they are ψd=0.4749\psi_d = 0.4749 and ψu=0.5102\psi_u = 0.5102. They add up to 0.985112, the bond's price.

Divided by the bond's price, they become 1−q=0.4821 - q = 0.482 and q=0.518q = 0.518.

Both are positive and they add up to 1, so they form a pmf on the two states (lesson 5.2.1). It is a Bernoulli distribution for an up move (lesson 5.2.2). These are the risk-neutral probabilities.

Rule: One-step risk-neutral pricing

q=erT−du−dprice=e−rT(q Cu+(1−q) Cd)\begin{gathered} q = \frac{e^{rT} - d}{u - d} \\[4pt] \text{price} = e^{-rT}\left(q\,C_u + (1 - q)\,C_d\right) \end{gathered}

The price is a probability-weighted average of the payoffs, with weights qq and 1−q1 - q, discounted at the risk-free rate. It equals the cost of the replicating portfolio. qq lies between 0 and 1 only when d<erT<ud < e^{rT} < u.

The formula for qq comes from the stock's own price: q S0u+(1−q) S0d=S0erTq\,S_0 u + (1 - q)\,S_0 d = S_0 e^{rT}. With the weights qq and 1−q1 - q, the stock grows on average like money in the bond: 101.5113 at TT.

For the call, e−rT(0.518×15.19+0.482×0)=7.7512e^{-rT}(0.518 \times 15.19 + 0.482 \times 0) = 7.7512, as replication found. Lesson 5.3.1 calls such a weighted average an expectation, and later courses write the price as e−rT EQ[payoff]e^{-rT}\,\mathbb{E}^{\mathbb{Q}}[\text{payoff}], with Q\mathbb{Q} for the risk-neutral probabilities.

Try it

The cell solves D⊤ψ=pD^\top\boldsymbol{\psi} = \mathbf{p} for the state prices, divides by their sum, and compares with the formula for qq.

The last lines price the call with qq and check that the weights reproduce the stock's growth at the risk-free rate.

⌘/Ctrl + Enter runs the cell

Case study 3.3.4's three-state market had risk-neutral probabilities 0.2577, 0.4639 and 0.2784, a pmf on three states. Its exercise has a two-state market: the stock at 80 or 125 from 98.75, and the bond at 0.97. The same rule gives q=0.4845q = 0.4845 and a call price of 11.75.

Try it

The two-state market of case study 3.3.4's exercise: the bond and the stock, with no call. The call with strike 100 pays 25 in the up state only, so it costs 25 times that state's price.

⌘/Ctrl + Enter runs the cell

The real chance of an up move does not enter

Neither replication nor qq used the probability that the stock actually goes up. Suppose it is 0.6. Discounting the average payoff with that weight gives e−rT×0.6×15.19=8.9789e^{-rT} \times 0.6 \times 15.19 = 8.9789, which is not the price.

If the call traded at $8.98, you could sell it and buy the replicating portfolio for 7.7512, keeping 1.2288 today. At TT the portfolio pays exactly what the call sold owes, in both states. The view on the stock's direction is already in its price S0S_0; the option adds nothing to it.

Check yourself
An analyst thinks the stock goes up with probability 0.7, not 0.518. What is the one-step call worth?

The put, and put–call parity

The put with strike 100 pays nothing if the stock goes up and 100−86.81=13.19100 - 86.81 = 13.19 if it goes down. Its price is e−rT×0.482×13.19=6.2624e^{-rT} \times 0.482 \times 13.19 = 6.2624. Its replicating portfolio is short 0.4647 shares and long 53.53 bonds.

Put–call parity from case study 3.3.4 holds: C−P=7.7512−6.2624=1.4888C - P = 7.7512 - 6.2624 = 1.4888, and S0−Ke−rT=100−98.5112=1.4888S_0 - Ke^{-rT} = 100 - 98.5112 = 1.4888.

One step is not enough

Case study 2.4.6 priced the same call by Black–Scholes at 6.3710. The one-step price, 7.7512, is 1.3801 too high: two final prices are a crude picture of a stock over six months.

The cure is more steps. Split the half year into nn steps, each up or down with probability qq: the number of up moves is then Bin⁡(n,q)\operatorname{Bin}(n, q) (lesson 5.2.2). Case study 5.11.4 builds that tree and shows the price closing in on 6.3710 as nn grows.

Try it

The first line compares the call's price with the discounted average under the real probability 0.6. The next lines price the put, check parity and give the put's shares and bonds.

The last line is the Black–Scholes price of case study 2.4.6.

⌘/Ctrl + Enter runs the cell

Try it

The first line is the bad quote: erTe^{rT}, then the "probability" qq it implies. The second shows nan from a probability typed as 2. The third is the uu that σ=20\sigma = 20 gives.

⌘/Ctrl + Enter runs the cell
Exercise

One-step binomial pricing

Write two functions.

  1. risk_neutral_q(u, d, r, T) returns q=erT−du−dq = \frac{e^{rT} - d}{u - d}. Raise ValueError unless 0<d<erT<u0 < d < e^{rT} < u: otherwise the bond or the stock wins in both states, and qq is not a probability.
  2. one_step(S0, u, d, r, T, payoff) prices a payoff paid at TT, given as a function of the final stock price. It returns (price, shares, bonds): the price today and the replicating portfolio, with bonds that pay 1 at TT. It raises ValueError in the same cases.

The tests use this case study's call and put, put–call parity, and the stock and the bond themselves. They add a payoff of 1 when the stock ends above 100, case study 3.3.4's two-state market, and moves that allow an arbitrage.

See the tests
import math

U = math.exp(0.2 * math.sqrt(0.5))  # the call of case study 2.4.6: sigma = 0.2, T = 0.5
D = 1 / U


def call(S):
    return max(S - 100, 0)


def put(S):
    return max(100 - S, 0)


def test_q():
    """With u = e^(0.2√0.5), d = 1/u, r = 3% and T = 0.5, q is about 0.5180"""
    expect_close(risk_neutral_q(U, D, 0.03, 0.5), 0.5179585268029778, what="risk_neutral_q", rel=1e-9)


def test_call():
    """The one-step call costs 7.7512: 0.5353 shares and −46.4703 bonds"""
    price, shares, bonds = one_step(100, U, D, 0.03, 0.5, call)
    expect_close(price, 7.751159552620581, what="price of the call", rel=1e-9)
    expect_close(shares, 0.5352965311073328, what="shares", rel=1e-9)
    expect_close(bonds, -46.47034688926673, what="bonds", rel=1e-9)


def test_put_and_parity():
    """The put costs 6.2624, short 0.4647 shares, and C − P = S₀ − Ke^(−rT)"""
    p, shares, bonds = one_step(100, U, D, 0.03, 0.5, put)
    expect_close(p, 6.26235351292685, what="price of the put", rel=1e-9)
    expect_close(shares, -0.4647034688926673, what="shares in the put's portfolio", rel=1e-9)
    c = one_step(100, U, D, 0.03, 0.5, call)[0]
    expect_close(c - p, 100 - 100 * math.exp(-0.015), what="C - P", rel=1e-9)


def test_stock_and_bond():
    """The stock's own payoff costs S₀ (1 share, 0 bonds); a payoff of 1 costs e^(−rT) (1 bond)"""
    price, shares, bonds = one_step(100, U, D, 0.03, 0.5, lambda S: S)
    expect_close((price, shares, bonds), (100.0, 1.0, 0.0), what="(price, shares, bonds) of the stock", abs_tol=1e-9)
    price, shares, bonds = one_step(100, U, D, 0.03, 0.5, lambda S: 1.0)
    expect_close((price, shares, bonds), (math.exp(-0.015), 0.0, 1.0), what="(price, shares, bonds) of the bond", abs_tol=1e-9)


def test_case_study_334():
    """Case study 3.3.4's two-state market (stock 80 or 125 from 98.75, bond 0.97): the call costs 11.75"""
    price, shares, bonds = one_step(98.75, 125 / 98.75, 80 / 98.75, -math.log(0.97), 1.0, call)
    expect_close(price, 11.75, what="price of the call", rel=1e-9)
    expect_close(shares, 25 / 45, what="shares", rel=1e-9)
    expect_close(bonds, -80 * 25 / 45, what="bonds", rel=1e-9)


def test_digital():
    """A payoff of 1 when the stock ends above 100 costs e^(−rT)·q = 0.5102"""
    price, _, _ = one_step(100, U, D, 0.03, 0.5, lambda S: 1.0 if S > 100 else 0.0)
    expect_close(price, 0.5102471289728264, what="price of the digital payoff", rel=1e-9)


def test_bond_beats_stock():
    """u = 1.01 and d = 0.99 with e^(rT) = 1.0151: the bond beats the stock in both states, so ValueError"""
    try:
        risk_neutral_q(1.01, 0.99, 0.03, 0.5)
    except ValueError:
        return
    raise AssertionError("expected ValueError: q would be 1.2557, not a probability")


def test_stock_beats_bond():
    """u = 1.2 and d = 1.05 with e^(rT) = 1.0151: the stock beats the bond in both states, so ValueError"""
    try:
        one_step(100, 1.2, 1.05, 0.03, 0.5, call)
    except ValueError:
        return
    raise AssertionError("expected ValueError: q would be negative")


def test_bad_moves():
    """d at or above u, or d at or below 0, raises ValueError"""
    for u, d in ((1.1, 1.1), (0.9, 1.1), (1.2, 0.0), (1.2, -0.5)):
        try:
            risk_neutral_q(u, d, 0.03, 0.5)
        except ValueError:
            continue
        raise AssertionError(f"expected ValueError for u = {u}, d = {d}")

Summary card

  • With independent defaults, each with probability pp, the number of defaults among nn loans is Bin⁡(n,p)\operatorname{Bin}(n, p), close to Poisson⁡(np)\operatorname{Poisson}(np) when pp is small. For 100 loans at 2%, five or more has probability 0.0508 (Poisson 0.0527), and the 99% quantile is 6 defaults.
  • With the same 2% average but defaults clustered in bad years, five or more has probability 0.1474: independence understates joint defaults.
  • One-period binomial model: the stock ends at S0uS_0 u or S0dS_0 d. A payoff is copied by Δ=Cu−CdS0u−S0d\Delta = \frac{C_u - C_d}{S_0u - S_0d} shares and bonds, and its price is e−rT(qCu+(1−q)Cd)e^{-rT}(qC_u + (1 - q)C_d) with q=erT−du−dq = \frac{e^{rT} - d}{u - d}.
  • The real probability of an up move does not enter the price; qq is a probability only when d<erT<ud < e^{rT} < u.
  • For the call of case study 2.4.6, one step gives 7.7512 against Black–Scholes 6.3710; more steps (case study 5.11.4) close the gap.

Free further reading

Optional. This lesson covers what you need; these add more examples and practice. All are free to read.