Numerical Methods and Algorithms in Finance › Numerical Integration

Michael BrenndoerferNovember 1, 202515 min read
Quantitative FinanceAll chapters
Part 1 of 15Mathematical Foundations
Chapter 8Numerical Methods and Algorithms in Finance › Numerical Integration
Reading section 4 of 10 · Numerical Integration · 15 minSection 4 of 10 · 15 min

Book contents

Section 4 of 10 · 15 min read

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 NtN_t be the value of the chosen positive numeraire and QN\mathbb{Q}^N its associated equivalent martingale measure. For a terminal payoff HH with H/NTH/N_T integrable under that measure, the conditional-expectation price is NtEQN[H/NT∣Ft]N_t\mathbb{E}^{\mathbb{Q}^N}[H/N_T\mid\mathcal{F}_t], where Ft\mathcal{F}_t represents information available at time tt. Integrability concerns the numeraire-discounted payoff, not just HH 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 p(ST)p(S_T):

E[Payoff]=∫0∞Payoff(ST)⋅p(ST) dST\mathbb{E}[\text{Payoff}] = \int_0^{\infty} \text{Payoff}(S_T) \cdot p(S_T) \, dS_T

where:

  • E[Payoff]\mathbb{E}[\text{Payoff}]: expected value of the option payoff
  • STS_T: stock price at expiration time TT
  • Payoff(ST)\text{Payoff}(S_T): option payoff as a function of terminal stock price
  • p(ST)p(S_T): 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 ∫abf(x) dx\int_a^b f(x) \, dx with nn equal subintervals and n+1n+1 equally spaced points x0=a,x1,...,xn=bx_0 = a, x_1, ..., x_n = b:

∫abf(x) dx≈h2[f(x0)+2∑i=1n−1f(xi)+f(xn)]\int_a^b f(x) \, dx \approx \frac{h}{2}\left[f(x_0) + 2\sum_{i=1}^{n-1}f(x_i) + f(x_n)\right]

where:

  • h=b−anh = \frac{b-a}{n}: step size (width of each trapezoid)
  • f(x0)f(x_0) and f(xn)f(x_n): function values at endpoints (each effectively weighted by 12\frac{1}{2})
  • f(xi)f(x_i) for i=1,…,n−1i = 1, \ldots, n-1: 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 f(xi)f(x_i) and f(xi+1)f(x_{i+1}) is h2(f(xi)+f(xi+1))\frac{h}{2}(f(x_i) + f(x_{i+1})); 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 O(h2)O(h^2). Once the grid is in that asymptotic regime, halving hh (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 nn intervals (where nn must be even):

∫abf(x) dx≈h3[f(x0)+4∑i=1,3,…,n−1f(xi)+2∑i=2,4,…,n−2f(xi)+f(xn)]\int_a^b f(x) \, dx \approx \frac{h}{3}\left[f(x_0) + 4\sum_{\substack{i=1,3,\ldots,n-1}}f(x_i) + 2\sum_{\substack{i=2,4,\ldots,n-2}}f(x_i) + f(x_n)\right]

where:

  • Odd-indexed interior points (i=1,3,…,n−1i = 1, 3, \ldots, n-1): weighted by 4 (midpoints of parabolic segments)
  • Even-indexed interior points (i=2,4,…,n−2i = 2, 4, \ldots, n-2): weighted by 2 (shared endpoints between segments); the sum is empty for n=2n=2
  • Endpoints f(x0)f(x_0) and f(xn)f(x_n): 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 p(x)=ax2+bx+cp(x) = ax^2 + bx + c over an interval [−h,h][-h, h] centered at the origin. The exact integral equals h3[p(−h)+4p(0)+p(h)]\frac{h}{3}[p(-h) + 4p(0) + p(h)], 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 O(h4)O(h^4). 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.

In[24]:
Code
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])
Out[25]:
Visualization
Visualization of the trapezoidal rule using trapezoids under a curved function.
Trapezoidal rule approximates the area under the curve using straight-line segments between points.
Visualization of Simpson's rule using parabolic segments under the same function.
Simpson's rule uses parabolic arcs that better capture curvature, achieving higher accuracy.

Gaussian Quadrature

Gauss-Legendre quadrature chooses both the evaluation points (called nodes or abscissas) and their weights rather than fixing equally spaced points.

With nn function evaluations, a quadrature rule has nn node positions and nn weights. Gauss-Legendre quadrature chooses both so that the rule is exact for every polynomial through degree 2n−12n-1. By contrast, an interpolatory rule on fixed generic nodes is guaranteed exact only through degree n−1n-1, although symmetry can increase that degree.

For Gauss-Legendre quadrature on [−1,1][-1, 1]:

∫−11f(x) dx≈∑i=1nwif(xi)\int_{-1}^{1} f(x) \, dx \approx \sum_{i=1}^{n} w_i f(x_i)

where:

  • nn: number of quadrature points
  • xix_i: nodes (abscissas), roots of the nn-th degree Legendre polynomial Pn(x)P_n(x)
  • wiw_i: weights, computed to make the formula exact for polynomials up to degree 2n−12n-1

Example values:

  • For n=2n = 2: nodes at x=±1/3≈±0.577x = \pm 1/\sqrt{3} \approx \pm 0.577, weights w=1w = 1
  • For n=3n = 3: nodes at x=0,±3/5≈±0.775x = 0, \pm\sqrt{3/5} \approx \pm 0.775, weights w=8/9,5/9,5/9w = 8/9, 5/9, 5/9

The two- and three-node examples above are equally spaced. For n≥4n \geq 4, the nodes are not equally spaced; as nn increases, they become denser toward the interval endpoints. Their placement is determined by Legendre orthogonality and the requirement that an nn-point Gauss-Legendre rule be exact through degree 2n−12n-1. Describing the endpoint density as boundary-error control can be a useful heuristic, but it is not the derivation of the nodes.

An nn-point Gauss-Legendre rule is exact for polynomials of degree up to 2n−12n-1. 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.

In[26]:
Code
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.

In[27]:
Code
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)
Out[29]:
Console
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 10−810^{-8} here. The adaptive error estimate is not an exact error bound. The omitted upper tail contributes about 5.47×10−55.47\times10^{-5} 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.

Out[30]:
Visualization
Log-log plot of absolute integration error for trapezoidal, Simpson, and split Gaussian quadrature, with two faint dashed lines labeled as smooth-integrand O(n^-2) and O(n^-4) reference slopes rather than fitted rates for the kinked payoff.
Convergence for a call-payoff integral. Fixed Gauss-Legendre quadrature is applied separately on each side of the strike kink; the comparison is specific to this integrand and truncation interval. The faint dashed guides show the smooth-integrand reference slopes $O(n^{-2})$ and $O(n^{-4})$; they are not fitted rates for this kinked payoff.

Practical Integration in Finance

Integration arises throughout quantitative finance in several key areas:

Under a specified equivalent martingale measure Q\mathbb{Q} for the money-market numeraire and a constant deterministic short rate, the assigned price of a terminal payoff that is integrable under Q\mathbb{Q} can be written as a discounted expectation:

V0=e−rTEQ[Payoff]V_0 = e^{-rT} \mathbb{E}^{\mathbb{Q}}[\text{Payoff}]

where:

  • V0V_0: current value of the derivative
  • e−rTe^{-rT}: discount factor from expiration to today
  • EQ\mathbb{E}^{\mathbb{Q}}: expectation under the risk-neutral probability measure
  • Payoff\text{Payoff}: derivative's payoff at expiration, typically a function of the underlying asset price STS_T

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:

VaRα=inf⁡{x:P(L>x)≤1−α}\text{VaR}_\alpha = \inf\{x : P(L > x) \leq 1 - \alpha\}

where:

  • VaRα\text{VaR}_\alpha: Value at Risk at confidence level α\alpha
  • LL: portfolio loss (positive values = losses)
  • α\alpha: confidence level (typically 95% or 99%)
  • inf⁡\inf: infimum (smallest value satisfying the condition)

This definition gives the lower α\alpha-quantile of the loss distribution for 0<α<10<\alpha<1. 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.