The sensitivity to the stock
A trader who owns options needs to know what happens to the account when the stock moves. Delta is the answer: the change in the option price per one-unit move in the stock, dC/dS. A call has a delta between 0 and 1, a put between -1 and 0. In the Black–Scholes model the call delta is simply N(d1) and the put delta N(d1) - 1. An at-the-money one-year call with delta 0.64 gains about 64 cents when the stock rises by a dollar. Delta is also read as roughly the probability that the option finishes in the money.
import math
def norm_cdf(x):
return 0.5 * (1 + math.erf(x / math.sqrt(2)))
def d1(spot, strike, rate, sigma, t):
return (math.log(spot / strike) + (rate + 0.5 * sigma ** 2) * t) / (sigma * math.sqrt(t))
def call_delta(spot, strike, rate, sigma, t):
return norm_cdf(d1(spot, strike, rate, sigma, t))
for spot in (80, 90, 100, 110, 120):
delta = call_delta(spot, 100, 0.05, 0.2, 1)
print(spot, round(delta, 4), round(delta - 1, 4)) # the call delta and the put delta
# 80 0.2219 -0.7781
# 90 0.4298 -0.5702
# 100 0.6368 -0.3632
# 110 0.7958 -0.2042
# 120 0.8965 -0.1035 deep in the money: the call moves almost one for one with the stockMeasuring delta by bumping
A closed formula exists only for simple options. For any pricing model you can estimate delta numerically: price the option with the stock slightly higher and slightly lower and divide by the distance. The central difference (f(S + h) - f(S - h)) / (2h) is more accurate than the one-sided difference, and exact for a parabola. The same function works for a Monte Carlo price or a binomial tree, so this "bump and reprice" is the universal way to get sensitivities. Choose h small, but not so small that rounding noise dominates (1% of the stock price is a typical start).
def bs_call(spot, strike, rate, sigma, t):
d_1 = d1(spot, strike, rate, sigma, t)
return spot * norm_cdf(d_1) - strike * math.exp(-rate * t) * norm_cdf(d_1 - sigma * math.sqrt(t))
def numerical_delta(price_function, spot, bump):
return (price_function(spot + bump) - price_function(spot - bump)) / (2 * bump)
price = lambda s: bs_call(s, 100, 0.05, 0.2, 1) # any function of the spot price will do
print(round(numerical_delta(price, 100, 0.01), 6)) # 0.636831
print(round(call_delta(100, 100, 0.05, 0.2, 1), 6)) # 0.636831 the same as the formulaHedging with delta
Delta turns an option position into an equivalent stock position. One call contract on 100 shares with delta 0.64 behaves like owning 64 shares for small moves. To remove the exposure, take the opposite position: with 10 long call contracts, sell 10 * 100 * 0.6368 = 637 shares. The hedged book is delta-neutral: a small move in the stock leaves its value almost unchanged. The hedge is only right for the current price, so it must be adjusted as the stock and the delta move. How often to rebalance is a trade-off between risk and trading costs.
def hedge_shares(contracts, delta, multiplier=100):
return -contracts * multiplier * delta
delta = call_delta(100, 100, 0.05, 0.2, 1)
print(round(hedge_shares(10, delta), 1)) # -636.8 long 10 call contracts: sell about 637 shares
print(round(hedge_shares(-10, delta), 1)) # 636.8 short 10 call contracts: buy about 637 shares
# After a $1 move the options gain about delta * 1 each and the shares lose about the same
print(round(bs_call(101, 100, 0.05, 0.2, 1) - bs_call(100, 100, 0.05, 0.2, 1), 4)) # 0.6461 close to delta, not exactly# Delta as expiry approaches: at the money it stays near 0.5, in the money it goes to 1, out of the money to 0
for t in (1, 0.25, 0.02):
print(t, [round(call_delta(spot, 100, 0.05, 0.2, t), 4) for spot in (90, 100, 110)])
# 1 [0.4298, 0.6368, 0.7958]
# 0.25 [0.1898, 0.5695, 0.8704]
# 0.02 [0.0001, 0.5197, 0.9997]- Call delta
N(d1)in (0, 1); put deltaN(d1) - 1in (-1, 0): the stock-equivalent of one option. - Numerical delta
(f(S + h) - f(S - h)) / (2h)works for any pricing model; keephsmall but above rounding noise. - Hedge shares =
-contracts * multiplier * deltamakes the book delta-neutral for small moves; rebalance as delta changes.
Next up: gamma, the sensitivity of delta itself, which says how fast a hedge goes stale.
Lab · what's graded
- Measure a call's sensitivity to the stock with
call_delta25 pts - Derive the put's delta with
put_delta25 pts - Bump the price to measure delta with
numerical_delta25 pts - Neutralise the position with
hedge_shares25 pts