SigmaField
Mathematical Foundations for Quant Finance
0 of 256 lessons
      1. 4.2.1 The gradient and directional derivativesConcept · 30 min
      2. 4.2.2 The multivariable chain rule and the total differentialConcept · 35 min
      3. 4.2.3 Practice set: gradients and the chain rulePractice set · 20 min
      4. 4.2.4 Case study: attributing P&L to risk factorsCase study · 35 min

Level 4, Multivariable calculus and optimisation 4.2 Gradient and chain rule Lesson 4 of 4

Case studyLesson 4.2.4 in Level 4, Multivariable calculus and optimisation. About 35 minutes.

Case study: attributing P&L to risk factors

Splitting a change among its inputs

Case study 4.1.4 wrote the call's value as a function of three inputs, V(S,σ,t)V(S, \sigma, t). They are the stock price SS, the volatility σ\sigma and the date tt, in years from today.

The strike is K=100K = 100, expiry is T=0.5T = 0.5 years away and the rate is r=0.03r = 0.03. Today S=100S = 100 and σ=0.2\sigma = 0.2, and the call is worth $6.3710.

The Greeks are its partial derivatives. Delta Δ=∂V∂S=0.570158\Delta = \frac{\partial V}{\partial S} = 0.570158, vega =∂V∂σ=27.7721= \frac{\partial V}{\partial \sigma} = 27.7721 (0.2777 per vol point) and theta Θ=∂V∂t=−7.0738\Theta = \frac{\partial V}{\partial t} = -7.0738 per year, or −0.0194-0.0194 per calendar day.

Case study 4.1.4 used them to estimate a change from given moves. P&L attribution runs the other way. The profit or loss (P&L) has happened, and the desk wants to know how much of it each input caused.

Rule: P&L attribution, first order

ΔV≈Δ⋅ΔS+vega⋅Δσ+Θ⋅Δtunexplained=ΔV−the parts\begin{gathered} \Delta V \approx \Delta \cdot \Delta S + \text{vega} \cdot \Delta\sigma \\ + \Theta \cdot \Delta t \\[6pt] \text{unexplained} = \Delta V - \text{the parts} \end{gathered}

This is the total differential of lesson 4.2.2, one term per input. Each part is a Greek, taken at the start of the day, times the move in its own input. ΔV\Delta V is the actual change, found by repricing.

As in case study 2.7.4, Δ\Delta on its own is delta, while ΔS\Delta S means the change in SS. For the night of the hook, per option:

inputmoveGreekpart
stockΔS=−2\Delta S = -2Δ=0.570158\Delta = 0.570158−1.1403-1.1403
volatilityΔσ=0.01\Delta\sigma = 0.01vega =27.7721= 27.77210.2777
timeΔt=1365\Delta t = \frac{1}{365}Θ=−7.0738\Theta = -7.0738−0.0194-0.0194
explained−0.8820-0.8820
actual, by repricing−0.8274-0.8274
unexplained0.0546

Times 100 options, these are the hook's numbers. The stock caused the loss, volatility gave back about a quarter of it, and time cost about 2 cents an option. The unexplained part is 6.6% of the loss.

Try it

V is case study 4.1.4's value, with the date tt as an input, and greeks returns delta, gamma, vega and theta per year. The cell splits the night's change into its three parts.

The last line is the same split for 100 options.

⌘/Ctrl + Enter runs the cell

What the unexplained part is

Lesson 4.2.2 found that the total differential misses by about the square of the steps. Here the large step is the stock's, and its square brings in gamma. Case study 2.7.4's gamma term is 12Γ(ΔS)2=12×0.027772×22=0.0555\frac{1}{2}\Gamma(\Delta S)^2 = \frac{1}{2} \times 0.027772 \times 2^2 = 0.0555.

That is almost all of the unexplained 0.0546. With a gamma line added, the gap shrinks to −0.0009-0.0009, case study 4.1.4's error.

What is left mixes the moves: vega itself changes when SS moves, and case study 4.3.4 measures that. So desks report four lines, delta, gamma, vega and theta, and the unexplained remainder.

Big moves

The unexplained part of the first-order split grows like the square of the stock move. Here is the same night, volatility up a point and one day passing, with other stock moves:

stock movefirst-order unexplainedgamma lineleft after gamma
−10-101.381.3886−0.0087-0.0087
−5-50.3440.3472−0.0032-0.0032
−2-20.05460.0555−0.0009-0.0009
−1-10.01340.0139−0.0005-0.0005
+1+10.01170.0139−0.0022-0.0022
+2+20.04990.0555−0.0056-0.0056
+5+50.31260.3472−0.0346-0.0346
+10+101.18841.3886−0.2002-0.2002

Doubling the move, from $1 to $2 or $5 to $10, multiplies it by about 4. It is positive both ways: a long call's value bends up, so the straight-line estimate always comes out low (case study 2.7.4). After the gamma line, the rest grows faster still, and reaches 20 cents on a $10 rise.

Close to expiry

Gamma grows as expiry nears (case study 2.7.4), and the unexplained part with it. Take a one-week call at the same strike, worth $1.1352, with Γ=0.1438\Gamma = 0.1438. On a night with a $5 fall and volatility up a point, the first-order split leaves 1.49 unexplained: more than the option is worth.

The gamma line, 1.80, now overshoots, and −0.31-0.31 is still left. For short-dated options near the strike, desks reprice rather than trust the lines.

The P&L that delta, vega and theta leave unexplained, as the stock move grows. It grows like the square of the move, and much faster with a week to expiry, where gamma is about five times larger. A gamma line removes most of it at six months but not at one week.

Volatility moves leave much less unexplained for this call, because its value is almost a straight line in σ\sigma (case study 2.4.6). A jump of ten vol points with the stock unchanged leaves only −0.0063-0.0063.

Try it

split returns the first-order unexplained part and the gamma line for a stock move dS, with volatility up a point and one day passing. T is the time to expiry today.

The first loop prints the table. Then the one-week call, and a ten-point volatility jump on its own.

⌘/Ctrl + Enter runs the cell

Attribution by repricing

Many risk systems split the P&L a second way: they reprice with one input moved at a time, the others left at yesterday's values. This is case study 2.8.4's bump-and-reprice, with the day's actual moves as the bumps.

moved alonestockvolatilitytimesumactual
change in value−1.0840-1.08400.2778−0.0194-0.0194−0.8257-0.8257−0.8274-0.8274

The stock's line now includes the bend: it is the delta part plus 0.0563, close to the gamma line. What is left, −0.0017-0.0017, is only the effect of the moves together.

Some systems instead move the inputs one after another, each from where the last left off. Then the parts add up exactly to the actual change, but the split depends on the order:

  • Stock first, then volatility: the stock −1.0840-1.0840, volatility 0.2763.
  • Volatility first, then stock: volatility 0.2778, the stock −1.0855-1.0855.

The difference, 0.0015, is the mixed effect once more. Volatility moved after the stock fell, when vega was only 0.2763 per point. No order is the right one, so a desk picks one and keeps it, and its reports stay comparable from day to day.

Try it

The first line moves each input alone and adds the three changes. The next two lines move them in turn, in the two orders; in both, time moves last.

The last line is vega per vol point with the stock at $98.

⌘/Ctrl + Enter runs the cell
Check yourself
Two systems split the same day's P&L by repricing the inputs one after another. One moves the stock first, the other volatility first. What differs between their reports?

A small book

A book of options is attributed the same way, line by line. Take two positions, each option on one share:

  • long 100 of the six-month calls;
  • short 100 one-month calls with the same strike, 100.
optionvaluedeltagammavega per pointtheta per day
six-month6.37100.57020.02780.2777−0.0194-0.0194
one-month2.42710.52880.06890.1149−0.0419-0.0419

A book's Greek is the sum of quantity times Greek, because the derivative of a sum is the sum of the derivatives (lesson 2.3.1). A short position enters with quantity −100-100. So the book has delta 4.14, gamma −4.11-4.11, vega 16.29 per point and theta 2.25 per day.

The book hardly notices small stock moves, gains when volatility rises, and earns time decay, since the one-month option decays faster. In exchange it is short gamma: large stock moves either way cost it money. This mix is called a calendar spread.

Here is its night, in dollars:

linelong six-monthshort one-monthbook
delta−114.03-114.03105.75−8.28-8.28
vega27.77−11.49-11.4916.29
theta−1.94-1.944.192.25
explained−88.20-88.2098.4610.26
actual−82.74-82.7485.122.38
unexplained5.46−13.34-13.34−7.88-7.88
gamma line5.55−13.78-13.78−8.23-8.23

The two delta lines almost cancel, and the first-order split says the book made $10.26, mostly from volatility. It made $2.38. The unexplained part, −$7.88, is more than three times the profit, and negative, because the book is short gamma. The gamma line, −$8.23, accounts for it.

On a bigger day the gap swamps the split. After a $5 fall with volatility up a point, the three lines say −$2.16, but the book loses $49.48; the gamma line is −$51.43. A short-gamma book needs its gamma line every day.

Try it

Each position is a quantity, a strike and a time to expiry. The first line is the book's Greeks: delta, gamma, vega per point and theta per day, each the sum of quantity times Greek.

Then each position's night, in the order of the table's lines, and the book's totals. The last line is the $5 fall.

⌘/Ctrl + Enter runs the cell
Check yourself
A book is short gamma, with delta near zero. The stock jumps 6% overnight and nothing else changes much. What does its first-order attribution show?
Exercise

Explain a day's P&L

Write pnl_explain(S0, S1, sigma0, sigma1, days, K, T, r, qty=1) for a position of qty Black–Scholes calls, each on one share. S0 and sigma0 are yesterday's stock price and volatility, S1 and sigma1 today's, and T is yesterday's time to expiry in years. Return a dictionary with:

  1. "delta", "gamma", "vega" and "theta": the four lines Δ⋅ΔS\Delta \cdot \Delta S, 12Γ(ΔS)2\frac{1}{2}\Gamma(\Delta S)^2, vega⋅Δσ\text{vega} \cdot \Delta\sigma and Θ⋅Δt\Theta \cdot \Delta t, times qty. Use yesterday's Greeks, with Θ\Theta per year and Δt=\Delta t = days / 365;
  2. "actual": the change in the position's value, by repricing with T−ΔtT - \Delta t left;
  3. "unexplained": the actual change minus the four lines.

Raise ValueError if a price, a volatility, K or T is not positive, if days is negative, or if the option expires within days.

The tests use the night of this case study, the short one-month position, a weekend with nothing moving, and inputs that should be refused.

See the tests
import math

from scipy.stats import norm


def _call(S, K, tau, r, sigma):
    d1 = (math.log(S / K) + (r + sigma**2 / 2) * tau) / (sigma * math.sqrt(tau))
    return S * norm.cdf(d1) - K * math.exp(-r * tau) * norm.cdf(d1 - sigma * math.sqrt(tau))


def _raises_value_error(f, *args, **kwargs):
    try:
        f(*args, **kwargs)
    except ValueError:
        return True
    return False


def _night(qty=1, T=0.5):
    return pnl_explain(100, 98, 0.2, 0.21, 1, 100, T, 0.03, qty=qty)


def test_returns_all_lines():
    """The answer has the six keys delta, gamma, vega, theta, actual and unexplained"""
    out = _night()
    assert isinstance(out, dict), f"expected a dictionary, got {type(out).__name__}"
    missing = {"delta", "gamma", "vega", "theta", "actual", "unexplained"} - set(out)
    assert not missing, f"missing keys: {sorted(missing)}"


def test_night_lines():
    """On the night (stock 100 to 98, volatility 20% to 21%, one day) the lines are −1.1403, 0.0555, 0.2777 and −0.0194"""
    out = _night()
    expect_close(out["delta"], -1.140316, what="delta line", rel=1e-5)
    expect_close(out["gamma"], 0.055544, what="gamma line", rel=1e-4)
    expect_close(out["vega"], 0.277721, what="vega line", rel=1e-5)
    expect_close(out["theta"], -0.019380, what="theta line", rel=1e-3)


def test_night_actual_and_unexplained():
    """On the night the call loses 0.8274 and about 0.0009 is left unexplained"""
    out = _night()
    expect_close(out["actual"], _call(98, 100, 0.5 - 1 / 365, 0.03, 0.21) - _call(100, 100, 0.5, 0.03, 0.2), what="actual change", rel=1e-9)
    expect_close(out["unexplained"], -0.000934, what="unexplained", rel=1e-2)


def test_lines_add_up():
    """The four lines and the unexplained part add up to the actual change"""
    out = pnl_explain(50, 53, 0.3, 0.27, 2, 55, 0.25, 0.01, qty=7)
    total = out["delta"] + out["gamma"] + out["vega"] + out["theta"] + out["unexplained"]
    expect_close(total, out["actual"], what="sum of the lines and the unexplained part", rel=1e-12, abs_tol=1e-12)


def test_short_position():
    """Short 100 one-month calls: the delta line is +105.75 and the gamma line −13.78 on the night"""
    out = _night(qty=-100, T=1 / 12)
    expect_close(out["delta"], 105.749, what="delta line", rel=1e-4)
    expect_close(out["gamma"], -13.78, what="gamma line", rel=1e-3)
    expect_close(out["vega"], -11.486, what="vega line", rel=1e-3)
    expect_close(out["actual"], 100 * (_call(100, 100, 1 / 12, 0.03, 0.2) - _call(98, 100, 1 / 12 - 1 / 365, 0.03, 0.21)), what="actual change", rel=1e-9)


def test_weekend():
    """Over a weekend with nothing moving, only theta counts: three days of it, and almost nothing unexplained"""
    out = pnl_explain(100, 100, 0.2, 0.2, 3, 100, 0.5, 0.03)
    expect_close(out["delta"], 0.0, what="delta line", abs_tol=1e-12)
    expect_close(out["vega"], 0.0, what="vega line", abs_tol=1e-12)
    expect_close(out["theta"], 3 * -0.019380, what="theta line", rel=1e-3)
    assert abs(out["unexplained"]) < 0.001, f"expected almost nothing unexplained, got {out['unexplained']}"


def test_expires_within_days():
    """An option with one week left cannot be explained over 8 days: ValueError"""
    assert _raises_value_error(pnl_explain, 100, 98, 0.2, 0.21, 8, 100, 1 / 52, 0.03), "expected ValueError: the option expires within 8 days"


def test_bad_inputs():
    """A zero volatility, a negative price or negative days: ValueError"""
    assert _raises_value_error(pnl_explain, 100, 98, 0.2, 0.0, 1, 100, 0.5, 0.03), "expected ValueError for sigma1 = 0"
    assert _raises_value_error(pnl_explain, 100, -98, 0.2, 0.21, 1, 100, 0.5, 0.03), "expected ValueError for S1 = −98"
    assert _raises_value_error(pnl_explain, 100, 98, 0.2, 0.21, -1, 100, 0.5, 0.03), "expected ValueError for days = −1"

Summary card

  • P&L attribution splits an actual change in value among the inputs that moved. The total differential gives one line per input: Δ⋅ΔS\Delta \cdot \Delta S, vega ⋅Δσ\cdot \Delta\sigma and Θ⋅Δt\Theta \cdot \Delta t, with the Greeks from the start of the day.
  • The unexplained part is the actual change minus the lines. For the first-order split it is mostly 12Γ(ΔS)2\frac{1}{2}\Gamma(\Delta S)^2, so desks add a gamma line; what remains mixes the moves.
  • The unexplained part grows like the square of the move, and fast near expiry, where gamma is large. It has the sign of gamma: positive for a long option, negative for a short-gamma book.
  • Repricing one input at a time also splits the P&L. Moving the inputs in turn makes the lines add up exactly, but the split depends on the order.
  • A book's Greeks are the sums of quantity times Greek. Keep the conventions fixed: start-of-day Greeks, theta per calendar day, vega per vol point, signs for the holder.

Free further reading

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