edgekit

Numerical methods

Most of quantitative finance has no closed form. Implied volatility is the root of an equation nobody can invert; American options have no Black-Scholes; most expectations are integrals nobody can do. What stands between the model and a number is a small set of numerical methods — root-finding, quadrature, trees, and Monte Carlo — plus the variance-reduction tricks that make Monte Carlo cheap enough to use. This chapter builds each one and races them against each other on the same option.

Intuition — accuracy is bought, and every method has a price list

Every numerical method converts compute into accuracy at a different exchange rate. Bisection buys one bit of accuracy per function call; Newton’s method roughly doubles the number of correct digits per call; a binomial tree’s error shrinks like ; crude Monte Carlo crawls at — to get one more digit you need a hundred times the paths. The craft is matching the method to the problem: fast converters when you have smoothness and derivatives, robust plodders when you have nothing, and — when you are stuck with Monte Carlo, as you usually are in high dimensions — variance reduction, which changes not the exchange rate but the constant in front of it, often by a factor of ten or more. Free accuracy, if you know the derivations.

Root-finding: bisection and Newton#

The prototype problem: find with . Bisection starts with a bracket where changes sign, evaluates the midpoint, keeps the half that still brackets the root, and repeats. The bracket halves each step, so the error after steps is linear convergence, one bit per evaluation, guaranteed for any continuous . Newton’s method is greedier: linearise at the current guess and jump to where the tangent line crosses zero,

Near a simple root the error squares each step (): quadratic convergence, doubling the correct digits per iteration — three or four steps to machine precision. The price is fragility: it needs the derivative, and a bad start can diverge. Production code hybridises — Newton steps inside a bisection-maintained bracket.

How implied_vol works
Implied volatility is exactly this problem: solve . It is a Newton solver’s dream: is vega, available in closed form, and BS price is monotonically increasing in , so the root is unique. The update is , and edgekit’s implied_vol converges in a handful of iterations — falling back to bisection where vega collapses (deep in/out-of-the-money, short expiry), precisely the regions where Newton stalls on a flat function. See Options & greeks for what the resulting surface means.

Numerical integration#

Prices are expectations, and expectations are integrals: . In one dimension, deterministic quadrature is unbeatable. The trapezoid rule joins sample points with straight lines (error for step ); Simpson’s rule fits parabolas through triples of points,

so doubling the points buys sixteen times the accuracy on smooth integrands. This is how you price a European option under any density you can evaluate — integrate payoff times density on a grid. The catch is the curse of dimensionality: a grid in dimensions needs points, hopeless for a basket of 20 assets or a path-dependent payoff over 252 steps. High dimensions belong to Monte Carlo, whose rate is slow but — crucially — dimension-independent.

Binomial trees: CRR and its convergence#

Between closed forms and Monte Carlo sit trees. The Cox-Ross-Rubinstein tree chops into steps of and lets the price jump up by or down by each step, with a risk-neutral up-probability chosen to match the risk-free drift and the volatility:

Price by backward induction: at expiry the option is worth its payoff at each terminal node; step backwards, each node’s value is the discounted expectation — and for an American option, the maximum of that and immediate exercise. That one extra is why trees matter: early exercise breaks every closed form, and the tree handles it for free. As the binomial terminal distribution converges (CLT again) to the log-normal of GBM, and the European tree price converges to Black-Scholes with error — visibly oscillating around the true value as strikes fall between or on node levels.

Binomial tree option price versus number of steps, oscillating around and converging to the Black-Scholes value, with the error envelope shrinking like one over n
CRR tree price vs steps n, against the Black-Scholes closed form (horizontal line). The tree price oscillates — even/odd step counts straddle the strike differently — inside an envelope that shrinks like 1/n. By n = 500 the error is sub-cent; the American premium is then the gap the closed form cannot see.
tree.py
import edgekit as ek

# American put on the house scenario: S=100, K=100, T=1y, r=5%, sigma=20%.
amer = ek.options.binomial_tree(100, 100, 1.0, 0.05, 0.20, n=500, kind="put", american=True)

# Same tree, European exercise — converges to Black-Scholes as n grows.
euro = ek.options.binomial_tree(100, 100, 1.0, 0.05, 0.20, n=500, kind="put", american=False)

amer - euro    # > 0: the early-exercise premium, priced by one extra max()

Monte Carlo, and why variance reduction pays#

Crude Monte Carlo prices by simulating paths and averaging discounted payoffs . The standard error is — to halve it, quadruple the paths. Variance reduction attacks instead of .

Antithetic variates#

Simulate paths in mirrored pairs: for every draw of Gaussian shocks , also run , and average the pair’s payoffs .

Derivation — variance of the pair average

For the average of two identically-distributed estimates with correlation :

Independent pairs () give — exactly what two plain paths give, no gain. But if the payoff is monotone in the shocks (a call is: bigger shocks, bigger payoff), then is anticorrelated with , , and the pair average beats two independent paths — at half the random-number cost, since each pair reuses its draws. When one path lands high, its mirror lands low; the errors cancel by construction. For payoffs that are close to linear in the shocks, and the variance nearly vanishes.

Control variates#

Pair each payoff with a correlated quantity whose true mean you know — for options, the terminal price itself: under the risk-neutral measure. Then estimate with the corrected average

Whatever luck pushed the simulated above its known mean also pushed up; subtracting times the observable error removes the shared luck. Minimising over gives the optimal coefficient and the payoff:

The same as an OLS slope, and the same as a regression’s unexplained variance — this is regression, applied to simulation error. With , variance drops ; at , .

Low-discrepancy sequences#

Random points clump and leave voids — that irregularity is the . Quasi-Monte Carlo abandons randomness for sequences engineered to fill space evenly. The Halton sequence builds coordinate by reflecting the integers written in base (the -th prime) about the decimal point: in base 2 the sequence runs — each new point landing in the largest remaining gap. Integration error for such sequences obeys the Koksma-Hlawka bound,

which is nearly in modest dimension — a square-root improvement in the exponent, worth orders of magnitude at large . The factor is the warning label: as grows the advantage fades (in practice QMC still wins well past the bound’s pessimism, because payoffs concentrate their variance in a few effective dimensions). Push Halton uniforms through the inverse normal CDF and you have evenly-spaced Gaussians ready for any path simulator from Simulating markets.

Log-log plot of pricing error versus number of paths for crude Monte Carlo, antithetic variates, control variates, and Halton quasi-Monte Carlo, showing parallel one-half slopes with lower constants and a steeper slope for quasi-Monte Carlo
Error vs n for pricing the same option, log-log. Crude MC falls with slope −1/2; antithetic and control variates run parallel but lower — same rate, smaller constant, with the control variate's drop set by 1−rho². The Halton line falls with slope near −1: a different exchange rate entirely.
Scenario — one option, four methods

Price the European call with , , , . Black-Scholes says — the target. A CRR tree is within a cent by steps (error ). Crude Monte Carlo with paths: the discounted payoff has , so the standard error is — a penny and a half of noise per dollar of option. Antithetic pairing ( for this payoff) cuts the variance by , standard error to roughly . A control variate on ( at the money) multiplies variance by : standard error , a path saving. Halton quasi-normals at the same land within about a cent. Moral: before buying compute, spend ten lines of code — the tricks stack, and together they buy a effective speed-up.

variance_reduction.py
import numpy as np
import edgekit as ek

S0, K, T, r, sigma = 100.0, 100.0, 1.0, 0.05, 0.20
n = 10_000
disc = np.exp(-r * T)

def terminal(z):                       # exact GBM terminal price from N(0,1) draws
    return S0 * np.exp((r - 0.5 * sigma**2) * T + sigma * np.sqrt(T) * z)

# 1) Antithetic: second half of draws is the negation of the first.
z = ek.sim.antithetic(n)[:, 0]
pay = disc * np.maximum(terminal(z) - K, 0.0)
est_anti = pay.mean()

# 2) Control variate: S_T has known risk-neutral mean S0 * e^{rT}.
st = terminal(np.random.default_rng(11).standard_normal(n))
y = disc * np.maximum(st - K, 0.0)
cv = ek.sim.control_variate(y, st, S0 * np.exp(r * T))
cv["estimate"], cv["beta"], cv["var_reduction"]

# 3) Quasi-Monte Carlo: Halton points -> normals -> paths.
zq = ek.sim.quasi_normals(n)[:, 0]      # norm_ppf(halton), evenly spaced draws
est_qmc = (disc * np.maximum(terminal(zq) - K, 0.0)).mean()

Choosing a method#

MethodError rateBest forBreaks down when
Newton root-findingquadratic (digits double)implied vol, yields — smooth monotone fflat vega / bad start; keep a bisection bracket
Simpson quadratureO(h^4)1-D expectations with known densitydimension > ~3 (grid explodes)
CRR binomial treeO(1/n)American / early-exercise featurespath-dependence, many state variables
MC + variance reductionO(1/sqrt(n)), smaller constanthigh dimensions, any payoffcontrol poorly correlated; payoff non-monotone (antithetic)
Quasi-MC (Halton)~O((log n)^d / n)smooth payoffs, moderate dlarge d; naive error bars (points are not random)
!Quasi-random points have no standard error
A Halton estimate comes with no honest confidence interval — the points are deterministic, so the usual is meaningless (and flattered by the even spacing). Practice randomises the sequence (a random shift or scramble per replication) to recover error bars. And all variance reduction shares one caveat: it sharpens the estimate of the model’s price. If the model is GBM and reality has jumps and fat tails, you now have a beautifully precise wrong answer — the gap that Monte-Carlo methods stress-tests with fatter-tailed generators.

Next: what happens when the object you estimate is an entire matrix — and most of its eigenvalues are noise. Random matrix theory.