Methods: how the probabilities are calculated
What OptionsCone calculates, and how. The full source code is on GitHub; the file names below point to where each step lives.
Data
Option chains, stock prices and earnings dates come from Yahoo Finance through the yfinance library. Option quotes are delayed by about 15 minutes. Every download is archived together with Yahoo's market state; the chart uses the newest download taken during the regular US session, because quotes outside it are mostly placeholders.
The risk-free rate is the 13-week US Treasury bill yield (^IRX). Future dividends are projected from the payout history: the last payment is carried forward at the observed frequency.
Which contracts are used
Contracts with fewer than 10 days to expiry are dropped: their price is mostly intrinsic value and tick size, and the implied volatility says little. So are contracts with an absolute delta below 0.05, whose few-cent quotes are noise.
Hard checks remove quotes that are impossible: no bid or no ask, an ask below the bid, a mid below one cent, a price below intrinsic value or above its theoretical maximum, and an implied volatility outside 1% to 300%.
Soft checks flag quotes that are doubtful without removing them: a spread wider than 25% of the mid, a bid of one cent, a put-call parity error larger than the half spread, a forward inconsistent with the rest of the expiry, and thin open interest. A contract that fails the price checks keeps its place on the chart but borrows the implied volatility of the nearest strike that passes; its dot is drawn hollow. Open interest alone never disqualifies a price.
Calls are used above spot and puts below, so every contract on the chart is out of the money. Those are the liquid quotes, and they carry little early-exercise premium. (src/quality.py, src/chain.py)
Implied volatility and Greeks
Listed US equity options are American. Each contract's volatility is solved from its bid-ask mid on a Cox-Ross-Rubinstein binomial tree with 160 steps, using Brent's root-finding method. Discrete dividends enter by the escrowed-dividend method: the present value of the dividends before expiry is taken out of the spot price, and the tree runs on the remainder.
Delta and gamma are read from the nodes of the same tree: delta is the slope between the two nodes after the first step, gamma the change in that slope across the three nodes after the second. They are shown for comparison with a broker; brokers use their own dividend and rate assumptions, so small differences are normal. (src/american.py)
Probability of touch
The probability that the price reaches strike K at any time before expiry T, for a lognormal price with the contract's own implied volatility σ and the risk-neutral log drift
μ = r − σ²/2
For a strike below spot S, with x = ln(K/S):
P(touch) = N( (x − μT) / σ√T ) + (K/S)2μ/σ² · N( (x + μT) / σ√T )
and the mirror image for a strike above spot:
P(touch) = N( (−x + μT) / σ√T ) + (K/S)2μ/σ² · N( (−x − μT) / σ√T )
This is the standard first-passage (reflection principle) result. With no drift, the touch probability is exactly twice the probability of finishing beyond the strike; with drift it is close to that. A touch counts even if the price moves back afterwards, so it is never lower than the expiry probability. (src/barrier.py)
Probability at expiry
The risk-neutral probability of finishing beyond the strike, with the same volatility and drift:
d2 = ( ln(S/K) + (r − σ²/2) T ) / σ√T
P(above K at expiry) = N(d2) P(below K at expiry) = N(−d2)
Both implied probabilities use the same assumptions, so touch and expiry are directly comparable.
Delta is not a probability
A call's delta is N(d1), and d1 = d2 + σ√T. The gap between delta and the probability of expiring in the money therefore grows with volatility and time. On a stock with 80% volatility and three months to go, σ√T is 0.4, and a 0.30 delta put can have a 40% or higher chance of expiring in the money. Delta remains the right number for hedging; for odds, use N(d2), or better the touch probability if the question is whether a level will be reached.
Bootstrap models (5y, 10y)
The implied probabilities describe what the market charges for risk. The bootstrap models show a different view, from the stock's own history:
- Blocks. Paths are built from the daily returns of the last 5 or 10 years. Blocks of 20 consecutive trading days are drawn at random, with replacement, and joined until the longest expiry is covered. Drawing single days would destroy volatility clustering; month-long blocks keep calm and turbulent stretches intact, and fat tails and skew carry over.
- Intraday range. Each simulated day carries the high and low of the real day it came from, relative to that day's close. A touch is counted when a simulated low (for strikes below spot) or high (above) reaches the strike, so the intraday range is observed, not inferred from closing prices.
- Drift kept. The realized trend of the window stays in the returns.
- 10,000 paths per window. Near a probability of 27%, the counting noise is about 0.4 percentage points, far below the difference between the two windows.
- One run per window to the longest expiry, read off at every shorter one, so probabilities can never fall with maturity.
Touch is the share of paths whose low (high) reaches the strike by expiry; expire is the share whose final close is beyond it. These are historical frequencies. They contain only moves that happened in the sample, and they ignore everything the market knows today, such as an upcoming earnings date. (src/montecarlo.py, charts/export_data.py)
Model-free implied volatility
The badge above each expiry is computed with the Cboe VIX method, applied to that expiry alone and left at its own maturity:
σ² = (2/T) Σ (ΔKi/Ki²) erT Q(Ki) − (1/T) (F/K0 − 1)²
Only out-of-the-money quotes contribute, each wing stops after two consecutive zero bids, the forward F comes from put-call parity at the strike where call and put prices are closest, and K0 is the first strike at or below F. No pricing model is inverted, so the result can differ from an at-the-money implied volatility. The ratio below the badge divides it by realized volatility. (src/varswap.py)
Realized volatility
Close-to-close volatility over the last year, exponentially weighted with a six-week half-life and annualized with 252 trading days. Close-to-close includes overnight gaps, which is the movement an option pays out on. Returns are weighted around zero rather than around their mean. (src/realized.py)
Drawing the cone
Probability coloring is interpolated between the listed strikes and expiries, in log price. Where an expiry does not list a strike, the probability is computed from the volatility of its nearest listed strike so the field stays continuous; no dot is drawn there. The color ramp is adjusted so that perceived lightness falls evenly with probability.
Implied volatility, open interest, spread and time value per day are painted outward from each contract: each point takes the strongest contract within reach, so a large position stays visible as a block instead of being averaged away. The two seller maps, implied vs realized and premium per unit risk, are differences and ratios and are blended instead: each point is the average of the contracts around it, weighted by inverse distance, so every contract shows its own value at its own position and a high value does not spill onto its neighbors.
All maps fade out beyond the outermost listed strikes, past the last expiry, and where they run into the top or bottom of the chart, so the cone ends softly; only transparency changes there, never the color. The strike range follows the expiry that reaches furthest on each side. Probability uses a fixed 0 to 100% scale, implied volatility a linear scale over the values shown, and open interest, spread, time value per day and premium per unit risk a logarithmic scale, with spread inverted so that darker means tighter. Implied vs realized is centered on zero.
Time value per day is the mid divided by the days to expiry. Every contract shown is out of the money, so its whole price is time value; per day it is an average over the remaining life, since decay speeds up towards expiry.
Implied vs realized is the implied touch probability minus the realized one from the 10-year bootstrap: blue where the market prices in a higher probability than the stock realized (a potential opportunity for sellers), red where lower. Touch rather than expire, because it rests on volatility more than on the trend the history happened to have. The bootstrap does not know the earnings calendar: about one in three of its 20-day blocks contains a past earnings reaction, whatever the dates. For an expiry that ends before the next report, history therefore overstates the risk and the map leans red; for one that spans the report, the market prices the event and the map leans blue.
Premium per unit risk is the mid divided by the average intrinsic value at the worst point of each 10-year path before expiry: for a short put the lowest low, for a short call the highest high, with paths that never reach the strike counted as zero. It is left out where fewer than 50 of the 10,000 paths reach the strike. It uses the mid; a seller receives the bid, which on far out-of-the-money contracts is noticeably lower.
For each expiry and model, the contour marks the listed strike whose probability is closest to the target, separately above and below spot. A filled marker is within 5 percentage points of the target.
Limits
- The implied model assumes a lognormal price with constant volatility per contract. Real prices jump, especially around earnings.
- Implied probabilities are risk-neutral. They include the market's price for risk and are not real-world odds.
- The bootstrap ignores the earnings calendar, so comparisons for expiries just before a report lean towards history overstating the risk.
- The bootstrap only knows the chosen years. A stock that changed its business, or a period without a crash, gives a narrow picture.
- Free data can be delayed, incomplete or wrong. The checks catch much of that, not all of it.
All probabilities are estimates. They are not forecasts and not financial advice.