The price as a function of volatility
A call option gives the right to buy a stock at a fixed price , the strike, at a fixed date, years away. The Black–Scholes formula prices it from the stock price and the interest rate (continuous, as a decimal). It also needs the volatility , the yearly standard deviation of the stock's log returns.
The Derivatives Modelling course derives the formula, and case study 2.6.5 rebuilds it as an integral. Here, take it as given:
is the standard normal cumulative distribution (Level 5; lesson 2.6.3 meets it as an area), norm.cdf in SciPy. Everything is known except , so this is a function of one variable, .
For the option in the hook, , and :
| 0.0001 | 0.05 | 0.2 | 0.5 | 1 | 50 | |
|---|---|---|---|---|---|---|
| 1.4888 | 2.2684 | 6.3710 | 14.6840 | 28.1773 | 100.0000 |
As shrinks to 0 the price falls to , the value of the option with no uncertainty. As grows it rises towards . A market price outside that range has no implied volatility at all.
Vega: the derivative with respect to volatility
Newton's method needs the slope . Options traders call it vega. Differentiating the formula with the chain rule (lesson 2.3.3) leads, after a cancellation, to a short result:
Rule: Vega
is the standard normal density, norm.pdf in SciPy. It is always positive, so vega is too: more volatility always makes a call worth more.
Because vega is positive, rises everywhere. So each market price has at most one implied volatility, and the sign of says which side of it you are on.
Try it
At the call is worth 6.3710 and its vega is 27.7721. A central difference (lesson 2.2.2) with agrees.
The loop reproduces the table. The cell prints with f"{v:.4f}", four decimal places.
Vega 27.77 is per unit of , a move from 0 to 100% volatility. Desks quote it per vol point, one percentage point: 0.2777, so each extra point adds about 28 cents.
Newton's method for implied volatility
Solve . The step is lesson 2.4.3's, with vega as the slope:
Rule: Implied volatility by Newton
The height above the market price, divided by vega, is how far to move the volatility.
Try it
From , the first step lands on 0.222648 and the second on 0.2226413, already correct to about ten digits. The implied volatility is 22.26%.
brentq (lesson 1.3.2) confirms it from the bracket .
Two things make this easy. At the money the price curve is almost a straight line: vega barely changes, from 27.36 at 10% to 27.77 at 20% and 30%. And the start, 20%, is close to the answer.
Deep out of the money: where Newton breaks
Now take a strike of 150, 50% above the stock price, with the same , and . The call trades at $2.00. At 20% volatility the formula gives only 0.0149, and vega is 0.7564: the curve is almost flat there.
Newton's step divides the gap by that tiny slope. From 20% the first step lands on 282%, the second on , a negative volatility, and the third on 916,440,330%. The answer is 44.78%.
Try it
Three plain Newton steps from 20% for the strike-150 call. The second step is already meaningless: a volatility cannot be negative.
The shape of the curve
For this option is S-shaped. It is flat near 0, bends up, and later bends down: at 30% and at 200%. So it has an inflection point (lesson 2.4.2), and there vega, the slope, is at its largest.
Rule: A good start: the inflection point
Vega is largest at , where changes from concave up to concave down. Started there, Newton's method moves towards the answer at every step and never overshoots.
Lesson 2.4.3 explains why, with concavity. If the answer is below , the start is to its right on a rising, concave-up curve, and each tangent lies below the curve. If the answer is above, the start is to its left on a concave-down stretch, where each tangent lies above the curve.
Either way, no step jumps past the answer. For strike 150, , or 125%. From there the guesses are 0.535213, 0.456067, 0.447934 and 0.447826: four steps, all from the right.
The call price against volatility for two strikes. At strike 100 one step from 20% lands almost on the answer. At strike 150 the tangent at 20% is nearly flat and shoots past the answer, while steps from the inflection point walk down to it.
Try it
The first line checks that a grid of volatilities from 1% to 300% has its largest vega at 1.25, next to . The next two lines show changing sign, by the second central difference of lesson 2.4.2.
Then Newton's method runs from .
A safety net: keep a bracket
When , the formula gives , where the price formula divides by zero. Production code therefore also keeps a bracket, as in lesson 2.4.3. Since rises, brackets any volatility from 1% to 300%.
Try it
safe_newton from lesson 2.4.3 solves the strike-150 call on in 6 steps. brentq needs 14 iterations for the same answer.
The last lines ask for a price of 1.40 on the strike-100 call, below its floor of 1.4888. There is no sign change, and brentq refuses.
Implied volatility
Write implied_vol(price, S, K, T, r, sigma0=0.2, tol=1e-10). It returns the implied volatility of a call by Newton's method from sigma0, with the price and vega formulas above.
- Stop when a step moves by less than
tol. - If a step makes zero or negative, raise
ValueError: the start was too far from the answer.
The tests check the example above, a strike-120 call at $1.50 (about 23.60%), and that your answer reprices the option. They also try the strike-150 call at $2.00: from 20% it must raise ValueError, and from it must return about 44.78%.
See the tests
import math
from scipy.stats import norm
def _call(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_at_the_money():
"""A 6-month at-the-money call at $7.00 implies about 22.26%"""
expect_close(implied_vol(7.0, 100, 100, 0.5, 0.03), 0.22264129444955746, what="implied_vol(7.0, ...)", rel=1e-8)
def test_out_of_the_money():
"""Strike 120 at $1.50 implies about 23.60%"""
expect_close(implied_vol(1.5, 100, 120, 0.5, 0.03), 0.23596239715145917, what="implied_vol(1.5, K=120)", rel=1e-6)
def test_reprices():
"""The answer reprices the option: a 1-year call at $12.00"""
sigma = implied_vol(12.0, 100, 95, 1.0, 0.02)
expect_close(_call(100, 95, 1.0, 0.02, sigma), 12.0, what="call price at your volatility", rel=1e-9)
def test_round_trip():
"""Price an option at 35%, then recover 35%"""
price = _call(50, 55, 0.25, 0.01, 0.35)
expect_close(implied_vol(price, 50, 55, 0.25, 0.01), 0.35, what="recovered volatility", rel=1e-8)
def test_deep_out_of_the_money_good_start():
"""Strike 150 at $2.00, started at the inflection point 1.2497, implies about 44.78%"""
expect_close(implied_vol(2.0, 100, 150, 0.5, 0.03, sigma0=1.2497), 0.4478258393239575, what="implied_vol(2.0, K=150, sigma0=1.2497)", rel=1e-8)
def test_deep_out_of_the_money_bad_start():
"""Strike 150 at $2.00 from 20%: a step goes negative, so ValueError"""
try:
implied_vol(2.0, 100, 150, 0.5, 0.03)
except ValueError:
return
raise AssertionError("expected ValueError: from 20% the second Newton step gives a negative volatility")
Summary card
- The Black–Scholes call price rises with volatility, from towards . A price outside that range has no implied volatility.
- Its derivative, vega, is , usually quoted per vol point.
- Implied volatility solves by Newton's method: .
- Deep out of the money, vega is tiny at low volatility and Newton from 20% can shoot to a negative volatility. Start at the inflection point , and keep a bracket as a fallback.