Numerical Methods and Algorithms in Finance › Numerical Integration
Quantitative FinanceAll chapters Numerical Methods and Algorithms in Finance › Numerical IntegrationOne section · Sections in this chapter4 / 10 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Numerical integration approximates definite integrals when analytical solutions are unavailable. In finance, this arises when computing expected values, pricing path-dependent options, or evaluating probability distributions. Integration is the continuous analog of summation. Many financial quantities are expressed as continuous sums over possible outcomes, weighted by their probabilities.
The connection between integration and expected values makes numerical integration useful in derivatives pricing. In a specified arbitrage-free model, let be the value of the chosen positive numeraire and its associated equivalent martingale measure. For a terminal payoff with integrable under that measure, the conditional-expectation price is , where represents information available at time . Integrability concerns the numeraire-discounted payoff, not just itself. For an admissibly replicable claim, no-arbitrage fixes its replication price; in an incomplete market it need not select a unique value for a non-replicable claim. Quadrature and Monte Carlo are numerical routes to a specified expectation.
Consider the expected payoff of an option under a probability distribution :
where:
- : expected value of the option payoff
- : stock price at expiration time
- : option payoff as a function of terminal stock price
- : probability density function of the stock price at expiration
This integral accumulates the payoff at each possible terminal price, weighted by the probability density at that price. The integral runs from zero to infinity because the lognormal Black-Scholes model assigns stock prices positive, unbounded support. For simple European options under Black-Scholes, this integral has a closed form. For more complex payoffs or distributions, quadrature or simulation can approximate the expectation.
The Trapezoidal Rule
The trapezoidal rule approximates the area under a curve by dividing the interval into trapezoids. On each subinterval, it replaces the function with the straight line joining the two endpoint values and integrates that line exactly.
For an integral with equal subintervals and equally spaced points :
where:
- : step size (width of each trapezoid)
- and : function values at endpoints (each effectively weighted by )
- for : function values at interior points (coefficient 2 appears because each interior point is shared by two adjacent trapezoids)
The factor of 2 for interior points arises because each interior point is shared by two adjacent trapezoids. The area of a single trapezoid with parallel sides and is ; summing all trapezoids and collecting terms yields the formula above. The endpoints appear only once (each is the edge of only one trapezoid), while interior points appear twice (as the right edge of one trapezoid and the left edge of the next).
For a sufficiently smooth integrand with a bounded second derivative, the composite trapezoidal rule has asymptotic error . Once the grid is in that asymptotic regime, halving (approximately doubling the number of intervals) reduces the leading error by about a factor of four. This result follows from a Taylor expansion: the rule is exact for linear functions, while its leading error depends on the integrand's second derivative. Payoff kinks and other nonsmooth points require separate treatment, such as splitting the interval at the kink.
Simpson's Rule
For sufficiently smooth integrands in the asymptotic grid regime, Simpson's rule can achieve higher accuracy than the trapezoidal rule by integrating a quadratic interpolant over each pair of panels. Payoff kinks can remove that advantage unless the interval is split at the nonsmooth point. Three values at distinct abscissas uniquely determine a polynomial of degree at most two, so we fit that interpolant over each pair of panels.
For intervals (where must be even):
where:
- Odd-indexed interior points (): weighted by 4 (midpoints of parabolic segments)
- Even-indexed interior points (): weighted by 2 (shared endpoints between segments); the sum is empty for
- Endpoints and : weighted by 1
The 1-4-2-4-2-...-4-1 weighting pattern comes from integrating the quadratic interpolant exactly, equivalently matching polynomial moments through degree 3 on each two-panel block. Odd-indexed points carry weight 4 because of this moment-matching calculation; even-indexed interior endpoints receive weight 2 because adjacent blocks share them.
To understand why Simpson's rule uses these specific weights, consider integrating a parabola over an interval centered at the origin. The exact integral equals , which is precisely the Simpson's rule formula applied to three points. By choosing weights that make the formula exact for parabolas, we ensure high accuracy for any function that is approximately quadratic over each pair of sub-intervals.
For a sufficiently smooth integrand, composite Simpson's rule has error . In the asymptotic regime, halving the step size reduces that error by about a factor of 16, compared with about 4 for the trapezoidal rule. On a compatible even grid, both rules can reuse the same function evaluations with different weights.
def trapezoidal(f, a, b, n):
"""Trapezoidal rule integration."""
validate_solver_controls(1.0, n)
if not np.all(np.isfinite([a, b])) or a >= b:
raise ValueError("Require finite ordered integration bounds")
h = (b - a) / n
x = np.linspace(a, b, n + 1)
y = f(x)
return h * (0.5 * y[0] + np.sum(y[1:-1]) + 0.5 * y[-1])
def simpsons(f, a, b, n):
"""Increment a positive odd panel count to the next even count."""
validate_solver_controls(1.0, n)
if not np.all(np.isfinite([a, b])) or a >= b:
raise ValueError("Require finite ordered integration bounds")
if n % 2 != 0:
n += 1
h = (b - a) / n
x = np.linspace(a, b, n + 1)
y = f(x)
return h / 3 * (y[0] + 4 * np.sum(y[1:-1:2]) + 2 * np.sum(y[2:-1:2]) + y[-1])

Gaussian Quadrature
Gauss-Legendre quadrature chooses both the evaluation points (called nodes or abscissas) and their weights rather than fixing equally spaced points.
With function evaluations, a quadrature rule has node positions and weights. Gauss-Legendre quadrature chooses both so that the rule is exact for every polynomial through degree . By contrast, an interpolatory rule on fixed generic nodes is guaranteed exact only through degree , although symmetry can increase that degree.
For Gauss-Legendre quadrature on :
where:
- : number of quadrature points
- : nodes (abscissas), roots of the -th degree Legendre polynomial
- : weights, computed to make the formula exact for polynomials up to degree
Example values:
- For : nodes at , weights
- For : nodes at , weights
The two- and three-node examples above are equally spaced. For , the nodes are not equally spaced; as increases, they become denser toward the interval endpoints. Their placement is determined by Legendre orthogonality and the requirement that an -point Gauss-Legendre rule be exact through degree . Describing the endpoint density as boundary-error control can be a useful heuristic, but it is not the derivation of the nodes.
An -point Gauss-Legendre rule is exact for polynomials of degree up to . For a nonpolynomial integrand, that degree of exactness does not by itself specify the approximation error; high accuracy follows when the integrand is sufficiently well approximated by polynomials on the interval.
from scipy.integrate import fixed_quad
def gaussian_quad(f, a, b, n=5):
"""Gaussian quadrature integration using scipy."""
validate_solver_controls(1.0, n)
if not np.all(np.isfinite([a, b])) or a >= b:
raise ValueError("Require finite ordered integration bounds")
result, _ = fixed_quad(f, a, b, n=n)
return result
def gaussian_quad_split(f, a, split, b, n=5):
"""Apply fixed Gauss-Legendre quadrature on each side of a known kink."""
if not np.isfinite(split) or not a < split < b:
raise ValueError("split must lie strictly inside the integration interval")
return gaussian_quad(f, a, split, n) + gaussian_quad(f, split, b, n)Let's compare these methods on a financial example: computing the expected payoff of a call option under lognormal terminal prices generated by normally distributed log returns.
def option_payoff_integrand(S, S0, K, mu, sigma, T):
"""Integrand for expected call payoff under lognormal distribution."""
if (
not np.all(np.isfinite([S0, K, mu, sigma, T]))
or S0 <= 0
or K < 0
or sigma <= 0
or T <= 0
):
raise ValueError("Require finite inputs, S0 > 0, K >= 0, sigma > 0, and T > 0")
S = np.asarray(S, dtype=float)
if not np.all(np.isfinite(S)):
raise ValueError("Terminal prices must be finite")
scalar_input = S.ndim == 0
S = np.atleast_1d(S)
result = np.zeros_like(S, dtype=float)
positive = S > 0
if not np.any(positive):
return result[0] if scalar_input else result
S_positive = S[positive]
log_S = np.log(S_positive)
log_S0 = np.log(S0)
mean = log_S0 + (mu - 0.5 * sigma**2) * T
std = sigma * np.sqrt(T)
density = np.exp(-0.5 * ((log_S - mean) / std) ** 2) / (
S_positive * std * np.sqrt(2 * np.pi)
)
payoff = np.maximum(S_positive - K, 0)
result[positive] = payoff * density
return result[0] if scalar_input else result
# Parameters
S0 = 100
K = 100
r = 0.05
sigma = 0.2
T = 1.0
# Integration bounds (lognormal distribution has support on (0, inf))
# We truncate at approximately 5 standard deviations
lower = S0 * np.exp((r - 0.5 * sigma**2) * T - 5 * sigma * np.sqrt(T))
upper = S0 * np.exp((r - 0.5 * sigma**2) * T + 5 * sigma * np.sqrt(T))
integrand = lambda S: option_payoff_integrand(S, S0, K, r, sigma, T)Expected Call Option Payoff (undiscounted): Black-Scholes reference: 10.986396 Adaptive quadrature: 10.986342 Adaptive error estimate: 1.220e-13 Trapezoidal Rule: n=10: 11.521192 (error: 0.534850) n=100: 10.990093 (error: 0.003751) n=1000: 10.986380 (error: 0.000038) Simpson's Rule: n=10: 11.748733 (error: 0.762392) n=100: 10.992715 (error: 0.006373) n=1000: 10.986405 (error: 0.000064) Gaussian Quadrature (split at strike; n per subinterval): n=5: 10.819934 (error: 0.166408) n=10: 10.986347 (error: 0.000005) n=20: 10.986342 (error: 0.000000)
This payoff integrand has a kink at the strike, so classical smooth-integrand orders do not directly describe an unsplit calculation. Against the tighter adaptive reference on the truncated interval, trapezoid with 1000 panels is slightly more accurate than Simpson with 1000 panels. Splitting at the kink lets Gauss-Legendre with 20 points per subinterval differ from that reference by less than here. The adaptive error estimate is not an exact error bound. The omitted upper tail contributes about to the undiscounted full-support expectation, so accurate quadrature on these bounds does not imply equally accurate full-support pricing. Rankings can also change when truncation and discretization errors cancel.

Practical Integration in Finance
Integration arises throughout quantitative finance in several key areas:
Under a specified equivalent martingale measure for the money-market numeraire and a constant deterministic short rate, the assigned price of a terminal payoff that is integrable under can be written as a discounted expectation:
where:
- : current value of the derivative
- : discount factor from expiration to today
- : expectation under the risk-neutral probability measure
- : derivative's payoff at expiration, typically a function of the underlying asset price
For a replicable claim, every admissible pricing measure agrees with its replication price, so no-arbitrage makes this value unique. In an incomplete market, different admissible measures can assign different expectation prices to a non-replicable payoff; the pricing model or measure must then be specified.
With stochastic rates or intermediate cash flows, the corresponding expression uses a stochastic discount factor or a chosen numeraire and conditional expectations. When the resulting expectations lack closed forms, numerical integration is one possible computational method.
Value at Risk (VaR) is a quantile of a loss distribution:
where:
- : Value at Risk at confidence level
- : portfolio loss (positive values = losses)
- : confidence level (typically 95% or 99%)
- : infimum (smallest value satisfying the condition)
This definition gives the lower -quantile of the loss distribution for . The loss distribution must correspond to a specified time horizon; VaR is not the maximum possible loss or an expected tail loss.
For a specified parametric distribution, a model quantile can be evaluated with its inverse CDF; for example, scipy.stats.norm.ppf evaluates a normal quantile. For historical or simulated loss samples, numpy.quantile computes a sample quantile directly from the supplied values rather than by numerically integrating a density.
Probability transforms in copula models and risk aggregation can involve integrating joint densities to compute marginal distributions or dependence measures. Analytic marginal distributions and sample-based methods are alternatives that need not perform numerical density integration.