SigmaField
Mathematical Foundations for Quant Finance
0 of 256 lessons
      1. 4.1.1 Functions of two variables: surfaces and level curvesConcept · 30 min
      2. 4.1.2 Partial derivativesConcept · 35 min
      3. 4.1.3 Practice set: partial derivativesPractice set · 20 min
      4. 4.1.4 Case study: the Greeks as partial derivativesCase study · 35 min

Level 4, Multivariable calculus and optimisation 4.1 Functions of several variables Lesson 4 of 4

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

Case study: the Greeks as partial derivatives

One value, several inputs

Take the call of case studies 2.4.6, 2.7.4 and 2.8.4: strike K=100K = 100, expiry T=0.5T = 0.5 years from today, interest rate r=0.03r = 0.03. Today the stock price is S=100S = 100 and the volatility σ=0.2\sigma = 0.2, and the call is worth $6.3710.

The strike and the expiry date are fixed by the contract. The stock price, the volatility and the date move.

Measure the date tt in years from today, so T−tT - t is the time left. Then the value is a function of three variables, V(S,σ,t)V(S, \sigma, t):

V=S N(d1)−Ke−r(T−t)N(d2)d1=ln⁡(S/K)+(r+σ2/2)(T−t)σT−td2=d1−σT−t\begin{gathered} V = S\,N(d_1) - K e^{-r(T - t)} N(d_2) \\[4pt] d_1 = \frac{\ln(S/K) + (r + \sigma^2/2)(T - t)}{\sigma\sqrt{T - t}} \\[4pt] d_2 = d_1 - \sigma\sqrt{T - t} \end{gathered}

This is case study 2.4.6's formula with T−tT - t in place of TT. NN is the standard normal distribution function and φ\varphi, below, its density (lesson 2.6.3). The rate rr can move too, so it is a fourth input.

A Greek is the sensitivity of the value to one input with the others held fixed. That is exactly a partial derivative, so each Greek is the slope of one slice of VV (lesson 4.1.1).

Rule: The Greeks as partial derivatives

Δ=∂V∂S,Γ=∂2V∂S2vega=∂V∂σ,Θ=∂V∂trho=∂V∂r\begin{gathered} \Delta = \frac{\partial V}{\partial S}, \quad \Gamma = \frac{\partial^2 V}{\partial S^2} \\[6pt] \text{vega} = \frac{\partial V}{\partial \sigma}, \quad \Theta = \frac{\partial V}{\partial t} \\[6pt] \text{rho} = \frac{\partial V}{\partial r} \end{gathered}

Delta and gamma hold σ\sigma, tt and rr fixed and move SS; vega moves only σ\sigma, theta only the date, rho only the rate. Each is a one-variable derivative of a slice.

Delta and gamma came from case study 2.7.4, and vega from case study 2.4.6. Theta and rho are new:

Greekclosed formvalueas desks quote it
Δ\DeltaN(d1)N(d_1)0.570158per $1 of stock
Γ\Gammaφ(d1)SσT−t\frac{\varphi(d_1)}{S\sigma\sqrt{T - t}}0.027772change in delta per $1
vegaST−t φ(d1)S\sqrt{T - t}\,\varphi(d_1)27.77210.2777 per vol point
Θ\Thetasee below−7.0738-7.0738−0.0194-0.0194 per day
rhoK(T−t)e−r(T−t)N(d2)K(T - t)e^{-r(T - t)}N(d_2)25.32240.2532 per point of rate

The signs say how a long call responds. It gains when the stock rises (Δ>0\Delta > 0), when volatility rises (vega >0> 0) and when rates rise (rho >0> 0). It loses value as time passes (Θ<0\Theta < 0).

Try it

greeks returns the value and the five partial derivatives at a point (S,σ,t)(S, \sigma, t), from the closed forms. The second line converts three of them to desk units: per vol point, per day and per point of rate.

⌘/Ctrl + Enter runs the cell

Slices and level curves of the value

Hold tt and rr fixed, and VV is a function of two variables, SS and σ\sigma. It has a surface and a contour map, like the functions of lesson 4.1.1.

Slices. Fix σ\sigma and let SS move: that is case study 2.7.4's curve, and delta is its slope. At S=100S = 100 the slices for 10%, 20% and 30% volatility give 3.6065, 6.3710 and 9.1494. The steps of 10 vol points add 2.7645 and 2.7784, close to vega's 27.7721×0.1=2.777227.7721 \times 0.1 = 2.7772.

Level curves. The value rises with SS and with σ\sigma. So along a level curve, a lower stock price must come with a higher volatility. The curve through today's point passes (95,29.38%)(95, 29.38\%) and (90,37.97%)(90, 37.97\%).

The call's value as slices, one for each volatility, and as a contour map. Along the bold level curve the value stays at $6.37: a lower stock price needs a higher volatility, and above $104.88 no volatility is low enough.

Each point on that curve is an implied volatility, as in case study 2.4.6. If the stock were at $95 and the call still traded at $6.37, the market would be pricing 29.38% volatility.

To the right the curve ends. It meets σ=0\sigma = 0 at S=6.3710+100e−0.015=104.88S = 6.3710 + 100e^{-0.015} = 104.88.

Case study 2.4.6 showed that the value never falls below S−Ke−rTS - Ke^{-rT}, its value with no uncertainty. With the stock at $105 that floor is 6.4888, so no volatility gives $6.37.

Try it

The first line prints the three slices at S=100S = 100 and the steps between them. brentq (lesson 1.3.2) then finds the volatility that keeps the value at $6.3710 with the stock at $95 and at $90.

The last line gives where the level curve meets σ=0\sigma = 0, then the call's value on a $105 stock at 0.01% volatility.

⌘/Ctrl + Enter runs the cell
Check yourself
Overnight the stock jumps from $100 to $106. Can a fall in volatility leave the call worth $6.37?

Theta: the passage of time

Hold SS and σ\sigma fixed and let the date move on. The time left T−tT - t shrinks, and the value changes at the rate Θ=∂V∂t\Theta = \frac{\partial V}{\partial t}. For a call it has two parts:

Θ=−S φ(d1) σ2T−t−rKe−r(T−t)N(d2)=−5.5544−1.5193=−7.0738\begin{gathered} \Theta = -\frac{S\,\varphi(d_1)\,\sigma}{2\sqrt{T - t}} - rKe^{-r(T - t)}N(d_2) \\[4pt] = -5.5544 - 1.5193 = -7.0738 \end{gathered}

The first part comes from volatility: less time left means less chance of the large move the option pays for. The second is about the strike, paid at expiry. As expiry comes closer, its present value Ke−r(T−t)Ke^{-r(T - t)} grows, and that lowers the call's value.

With r≥0r \ge 0 both parts are negative, so a call's theta is negative. The first part is also −12σ2S2Γ-\frac{1}{2}\sigma^2S^2\Gamma, since Sφ(d1)σ2T−t=12σ2S2⋅φ(d1)SσT−t\frac{S\varphi(d_1)\sigma}{2\sqrt{T - t}} = \frac{1}{2}\sigma^2S^2 \cdot \frac{\varphi(d_1)}{S\sigma\sqrt{T - t}}. An option with a lot of gamma pays for it with a lot of theta.

Per day

−7.0738-7.0738 is per year, an awkward unit for something that happens daily. Desks divide by 365 for a calendar day, −0.0194-0.0194, or by 252 for a trading day, −0.0281-0.0281. So with nothing else moving, the call loses about 2 cents a day.

Repricing agrees. Moving the date one day forward changes the value by −0.019402-0.019402, against Θ÷365=−0.019380\Theta \div 365 = -0.019380. The small gap is the forward difference's error (lesson 2.8.1): theta itself changes over the day.

Close to expiry

At the money, theta grows as expiry nears, like gamma in case study 2.7.4. Here it is per day, with SS and σ\sigma fixed:

time left6 months1 month1 week1 day
value6.37102.42711.13520.4217
theta per day−0.0194-0.0194−0.0419-0.0419−0.0829-0.0829−0.2129-0.2129

With a day left the call loses half its value overnight, if nothing moves. At T−t=0T - t = 0 the formula divides by zero: at expiry the value is the payoff, with its corner at the strike.

Try it

theta_parts returns the two parts of theta and −12σ2S2Γ-\frac{1}{2}\sigma^2S^2\Gamma. The second line is theta per calendar day and per trading day.

Then the one-day repricing and a central difference in tt, and the slope in TT, the time to expiry. The loop repeats the table.

⌘/Ctrl + Enter runs the cell

The slope in the time to expiry TT is +7.0738+7.0738: the same number with the opposite sign. More time to expiry is worth more, and time passing takes it away. Check which of the two a system reports before adding it to anything.

Rho, and all five by bumping

Rho is the slope in rr, with SS, σ\sigma and tt fixed: K(T−t)e−r(T−t)N(d2)=25.3224K(T - t)e^{-r(T - t)}N(d_2) = 25.3224. Desks quote it per percentage point of rate, 0.2532: each point of rate is worth about 25 cents.

It is positive because a higher rate makes the strike, paid later, cheaper today. For a six-month option it is small; it grows with the time left.

Case study 2.8.4 checked delta, gamma and vega by bump-and-reprice: move one input a little, reprice and divide. The same works for theta and rho. Each bump moves one input and holds the others fixed, so it is a finite difference of a slice (lesson 4.1.2).

Greekclosed formbumpedbump
delta0.5701580.570054stock ±\pm$1
gamma0.0277720.027762stock ±\pm$1
vega per vol point0.2777210.277717σ±0.01\sigma \pm 0.01
theta per day−0.019380-0.019380−0.019402-0.019402one day forward
rho per point0.2532240.253212r±0.01r \pm 0.01

The first three rows are case study 2.8.4's. All five agree to about 0.1% or better; theta's one-sided bump is the least accurate, as lesson 2.8.1 predicts.

Try it

closed holds the five closed forms in desk units. bumped reprices the call with one input moved each time. The stock moves by $1, the volatility by one point, the date by one day and the rate by one point.

The last column is each bump's error as a share of the closed form.

⌘/Ctrl + Enter runs the cell

Overnight: adding vega and theta

Case study 2.7.4's estimate moved only SS. When σ\sigma and tt move too, add one term for each, using its own partial derivative:

Rule: Delta–gamma–vega–theta estimate

ΔV≈Δ⋅ΔS+12Γ (ΔS)2+vega⋅Δσ+Θ⋅Δt\begin{gathered} \Delta V \approx \Delta \cdot \Delta S + \tfrac{1}{2}\Gamma\,(\Delta S)^2 \\[4pt] + \text{vega} \cdot \Delta\sigma + \Theta \cdot \Delta t \end{gathered}

ΔS\Delta S is in dollars, Δσ\Delta\sigma a decimal (0.01 for one vol point) and Δt\Delta t in years (1365\frac{1}{365} for a day). With vega per vol point and theta per day, use points and days instead.

Each error below is the repriced change minus the estimate, as in case study 2.7.4.

stock ($), vol (points), daysrepriceddelta–gammawith vega and thetaerror
0, 0, 1 day−0.0194-0.01940−0.0194-0.01940.0000
0, 0, 3 days−0.0583-0.05830−0.0581-0.0581−0.0002-0.0002
−2-2, +1+1, 1 day−0.8274-0.8274−1.0848-1.0848−0.8264-0.8264−0.0009-0.0009
+5+5, −2-2, 1 day2.65303.19792.62310.0298
−5-5, +3+3, 1 day−1.7205-1.7205−2.5036-2.5036−1.6899-1.6899−0.0307-0.0307
−10-10, +5+5, 1 day−3.1602-3.1602−4.3130-4.3130−2.9437-2.9437−0.2165-0.2165

The hook's night is the third row. Delta–gamma alone misses by 26 cents; with vega and theta the estimate is within a tenth of a cent.

A sell-off usually comes with rising volatility, as in the last two rows. There, ignoring vega would miss by 83 cents and $1.39.

What is left grows when both moves are large. It comes from vega changing with SS: with the stock at $95, vega is 26.34, not 27.77, so three vol points are worth about 4 cents less than the estimate assumes. Case study 4.3.4 finds that at the money most of this change is of degree 3 in the moves.

Lesson 4.2.2 explains why the separate terms can simply be added: the total differential. Case study 4.2.4 uses it to split a day's profit and loss among the inputs, and case study 4.3.4 adds the mixed second-order terms.

Try it

The loop reprices the call after each scenario, with the date moved by the number of days. It prints the repriced change, the delta–gamma estimate, the full estimate and its error.

The last line compares vega at $95 and at $100, and the cost of that difference over three vol points.

⌘/Ctrl + Enter runs the cell
Check yourself
A trader is short one six-month call. Over a weekend the stock price and the volatility do not move. Roughly what does the position make or lose?
Exercise

The Greeks of a call, in desk units

Write two functions for a Black–Scholes call, with norm.cdf and norm.pdf from scipy.stats. Here T is the time left in years.

  1. call_greeks(S, K, T, r, sigma) returns a dictionary with keys "value", "delta", "gamma", "vega", "theta" and "rho". Quote vega per vol point, theta per calendar day (divide by 365) and rho per percentage point. Raise ValueError if S, K, T or sigma is not positive.
  2. overnight_change(S, K, T, r, sigma, dS, dsigma, days=1) returns the estimate Δ⋅dS+12Γ (dS)2+vega⋅dσ+Θ⋅dt\Delta \cdot dS + \frac{1}{2}\Gamma\,(dS)^2 + \text{vega} \cdot d\sigma + \Theta \cdot dt. Here dsigma is a decimal (0.01 for one vol point) and dtdt is days / 365. Raise ValueError if days is negative, or not shorter than the time left.

The tests use the six-month call above and compare every Greek with bump-and-reprice for another option. They try the hook's night, a weekend with nothing moving, and inputs that divide by zero.

See the tests
import math

from scipy.stats import norm


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


def test_delta_gamma():
    """The six-month call has delta 0.570158 and gamma 0.027772"""
    g = call_greeks(100, 100, 0.5, 0.03, 0.2)
    expect_close(g["value"], 6.3710279, what="value", rel=1e-6)
    expect_close(g["delta"], 0.5701581, what="delta", rel=1e-6)
    expect_close(g["gamma"], 0.0277721, what="gamma", rel=1e-5)


def test_vega_per_vol_point():
    """Vega is quoted per vol point: 0.2777 for the six-month call"""
    expect_close(call_greeks(100, 100, 0.5, 0.03, 0.2)["vega"], 0.2777213, what="vega per vol point", rel=1e-5)


def test_theta_per_day():
    """Theta is per calendar day and negative: -0.0194 for the six-month call"""
    expect_close(call_greeks(100, 100, 0.5, 0.03, 0.2)["theta"], -7.0737698 / 365, what="theta per day", rel=1e-5)


def test_rho_per_point():
    """Rho is per percentage point of rate: 0.2532 for the six-month call"""
    expect_close(call_greeks(100, 100, 0.5, 0.03, 0.2)["rho"], 0.2532239, what="rho per point", rel=1e-5)


def test_matches_bumps():
    """Every Greek matches bump-and-reprice for a one-year call at strike 110"""
    S, K, T, r, s = 95, 110, 1.0, 0.04, 0.3
    g = call_greeks(S, K, T, r, s)
    h, k = 0.01, 1e-4
    expect_close(g["delta"], (_value(S + h, K, T, r, s) - _value(S - h, K, T, r, s)) / (2 * h), what="delta", rel=1e-6)
    expect_close(g["gamma"], (_value(S + h, K, T, r, s) - 2 * _value(S, K, T, r, s) + _value(S - h, K, T, r, s)) / h**2,
                 what="gamma", rel=1e-4)
    expect_close(g["vega"], (_value(S, K, T, r, s + k) - _value(S, K, T, r, s - k)) / (2 * k) / 100, what="vega per vol point", rel=1e-6)
    expect_close(g["theta"], -(_value(S, K, T + k, r, s) - _value(S, K, T - k, r, s)) / (2 * k) / 365, what="theta per day", rel=1e-6)
    expect_close(g["rho"], (_value(S, K, T, r + k, s) - _value(S, K, T, r - k, s)) / (2 * k) / 100, what="rho per point", rel=1e-6)


def test_hook_night():
    """The stock falls $2, volatility rises one point, a day passes: the estimate is -0.8264"""
    expect_close(overnight_change(100, 100, 0.5, 0.03, 0.2, -2, 0.01, days=1), -0.8264308, what="overnight_change", rel=1e-5)


def test_weekend():
    """With nothing moving, a weekend costs three days of theta"""
    expect_close(overnight_change(100, 100, 0.5, 0.03, 0.2, 0, 0, days=3), -0.0581406, what="overnight_change over 3 days", rel=1e-5)


def test_bad_inputs():
    """T = 0 and sigma = 0 raise ValueError: the formulas divide by zero"""
    for args in [(100, 100, 0.0, 0.03, 0.2), (100, 100, 0.5, 0.03, 0.0)]:
        try:
            call_greeks(*args)
        except ValueError:
            continue
        raise AssertionError(f"expected ValueError for call_greeks{args}")


def test_days_past_expiry():
    """A move of 200 days on a six-month call raises ValueError"""
    try:
        overnight_change(100, 100, 0.5, 0.03, 0.2, 0, 0, days=200)
    except ValueError:
        return
    raise AssertionError("expected ValueError: 200 days is past expiry")

Summary card

  • An option's value is a function of several inputs, V(S,σ,t)V(S, \sigma, t) and the rate rr. Each Greek is a partial derivative in one of them, the others held fixed.
  • Δ=∂V∂S\Delta = \frac{\partial V}{\partial S}, Γ=∂2V∂S2\Gamma = \frac{\partial^2 V}{\partial S^2}, vega =∂V∂σ= \frac{\partial V}{\partial \sigma}, Θ=∂V∂t\Theta = \frac{\partial V}{\partial t}, rho =∂V∂r= \frac{\partial V}{\partial r}. For a long call all are positive except theta.
  • Theta =−Sφ(d1)σ2T−t−rKe−r(T−t)N(d2)= -\frac{S\varphi(d_1)\sigma}{2\sqrt{T - t}} - rKe^{-r(T - t)}N(d_2), quoted per day: −0.0194-0.0194 for the six-month call. It grows near expiry at the money, like gamma.
  • Bump-and-reprice confirms all five; theta's one-day bump is a forward difference.
  • Along a level curve of VV in SS and σ\sigma the value stays fixed. A lower stock price needs a higher volatility, and the floor S−Ke−rTS - Ke^{-rT} ends the curve.
  • Overnight, ΔV≈Δ⋅ΔS+12Γ(ΔS)2+vega⋅Δσ+Θ⋅Δt\Delta V \approx \Delta \cdot \Delta S + \frac{1}{2}\Gamma(\Delta S)^2 + \text{vega} \cdot \Delta\sigma + \Theta \cdot \Delta t. What remains comes mostly from terms that mix the moves.

Free further reading

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