Delta is not constant
A delta hedge is exact only for an instant. As soon as the stock moves, the option's delta changes and the hedge is wrong. Gamma is the rate of change of delta with the stock: gamma = d(delta)/dS, the second derivative of the price. A long call or put has positive gamma. In Black–Scholes it is pdf(d1) / (S * sigma * sqrt(T)), the same for calls and puts, where pdf is the bell-curve density. A large gamma means the hedge goes stale quickly and must be adjusted often.
import math
def norm_pdf(x):
return math.exp(-0.5 * x * x) / math.sqrt(2 * math.pi)
def d1(spot, strike, rate, sigma, t):
return (math.log(spot / strike) + (rate + 0.5 * sigma ** 2) * t) / (sigma * math.sqrt(t))
def gamma(spot, strike, rate, sigma, t):
return norm_pdf(d1(spot, strike, rate, sigma, t)) / (spot * sigma * math.sqrt(t))
for spot in (80, 90, 100, 110, 120):
print(spot, round(gamma(spot, 100, 0.05, 0.2, 1), 5))
# 80 0.0186
# 90 0.02182
# 100 0.01876
# 110 0.01289
# 120 0.0075 gamma peaks near the strike and fades far from itGamma grows as expiry nears
For an at-the-money option gamma rises sharply as expiry approaches: 0.019 with a year to go, 0.039 with three months, 0.141 with a week. Near expiry the option is nearly a coin toss between worthless and worth the full move, so delta swings from 0 to 1 over a tiny price range. This is why traders who are short options near expiry (short gamma) sleep badly: the hedge needs constant adjusting and a jump hurts. You can also estimate gamma for any model by the second difference (f(S + h) - 2 f(S) + f(S - h)) / h², exact for a parabola.
for t in (1, 0.25, 0.02):
print(t, round(gamma(100, 100, 0.05, 0.2, t), 5))
# 1 0.01876
# 0.25 0.03929
# 0.02 0.14087 a week before expiry the at-the-money gamma is 7 times larger
def numerical_gamma(price_function, spot, bump):
return (price_function(spot + bump) - 2 * price_function(spot) + price_function(spot - bump)) / bump ** 2
price = lambda s: bs_call(s, 100, 0.05, 0.2, 1) # bs_call as in the previous topic
print(round(numerical_gamma(price, 100, 0.5), 5)) # 0.01876 the same as the formulaWhat gamma earns
Because delta changes with the stock, a long option gains more than delta alone predicts, whichever way the stock moves. A $5 rise lifts delta from 0.637 to 0.637 + 0.01876 * 5 = 0.731. The profit of a move is delta * move + 0.5 * gamma * move²: the second term is the gamma profit for a long option (a loss for a short one). It grows with the square of the move, so large moves, either way, favour the long-gamma side. That profit is not free: the holder pays for it through the option's premium and its time decay.
g = gamma(100, 100, 0.05, 0.2, 1)
delta = call_delta(100, 100, 0.05, 0.2, 1) # as in the delta topic
print(round(delta, 4), round(delta + g * 5, 4)) # 0.6368 0.7306 the delta after a $5 rise
print(round(call_delta(105, 100, 0.05, 0.2, 1), 4)) # 0.7237 the exact delta at 105 (gamma is a first-order guide)
move = 5
true_gain = bs_call(105, 100, 0.05, 0.2, 1) - bs_call(100, 100, 0.05, 0.2, 1)
print(round(true_gain - delta * move, 4), round(0.5 * g * move ** 2, 4)) # 0.2232 0.2345 what delta missed, and what gamma explains# Dollar gamma: how many dollars of stock the delta hedge changes for a 1% move of the stock at 100
print(round(g * 100 ** 2 / 100, 3)) # 1.876- Gamma =
pdf(d1) / (S * sigma * sqrt(T)), the second derivative of the price; the same for calls and puts, largest near the strike and near expiry. - Numerical gamma
(f(S + h) - 2 f(S) + f(S - h)) / h²; delta after a movedelta + gamma * move. - A move pays
delta * move + 0.5 * gamma * move²: a long option gains from big moves either way, and pays for it in time decay.
Next up: vega, the sensitivity to volatility, the input nobody can observe directly.
Lab · what's graded
- Measure how fast delta changes with
gamma25 pts - Measure the curvature of any price with
numerical_gamma25 pts - Update the delta after a move with
delta_after_move25 pts - Price the benefit of curvature with
gamma_pnl25 pts