Predicted bilateral trade from economic size and distance, and the residual by which an observed corridor over- or under-trades relative to that prediction.
Surface: /gravity
BACI 202501 (CEPII), HS92, 1995-2024 (retrieved 2026-04-28)
The gravity_residual column served by /gravity and /api/gravity/* comes from a per-year OLS on log-linearised trade, positive flows only, with three regressors and no fixed effects: ln(trade) = b0 + b_d ln(dist) + b_o ln(gdp_o) + b_m ln(gdp_d). BACI trade values are stored in thousands of USD, so the fitted intercept reflects that unit. Reproduced exactly from the stored column on 2026-08-27 (maximum absolute deviation 0.0 for every year tested). Adding contiguity, common language and FTA breaks the reproduction, so those variables are displayed on the page but are not regressors.
Fitted values, re-derived: 2020 gives b_d = -1.5005, b_o = +1.3343, b_m = +0.9728, intercept -20.8546, R-squared 0.6389 on 23,795 pairs. 1996 gives b_d = -1.1483, R-squared 0.6848 on 11,203 pairs. The distance elasticity steepens from about -1.15 in 1996 to about -1.53 in 2019.
A separate, genuine PPML estimation lives at /research/gravity-ppml: Poisson pseudo-maximum-likelihood by hand-written IRLS in TypeScript (fitPPML() at lines 167-215), regressors [1, ln dist, ln gdp_o, ln gdp_d, contig], zero-inclusive sample built from bilateral_year with COALESCE(trade, 0), top 120 economies by mean nominal GDP, years 1996, 2005, 2015 and 2024, Eicker-Huber-White sandwich standard errors, unclustered, no fixed effects.
The card links /gravity for the residuals and /research/gravity-ppml for the PPML estimates. They are separate estimators.
ln X(o,d,t) = b0 + b_d ln dist(o,d) + b_o ln GDP(o,t) + b_m ln GDP(d,t) + e (OLS, positive flows, per year)residual(o,d,t) = ln X(o,d,t) - fittedover-trading in percent = (exp(residual) - 1) * 100E[X(o,d,t)] = exp( b0 + b_d ln dist + b_o ln GDP_o + b_m ln GDP_d + b_c contig ) (PPML, zeros included)| Path | Method | Returns | Example |
|---|---|---|---|
| /api/gravity/pair | GET | The full covariate row for one corridor plus its residual; falls back to the mirror pair and flags it. | /api/gravity/pair?o=DEU&d=FRA&year=2020 |
| /api/gravity/potential | GET | A country's largest over- and under-trading partners by residual. | /api/gravity/potential?iso3=DEU&year=2020&limit=20 |
| /api/gravity/scatter | GET | The 2,000 largest flows as distance against trade, tagged by FTA, colonial link and common language. | /api/gravity/scatter?year=2020 |
| /api/v1/gravity | GET | The versioned single-corridor envelope. | /api/v1/gravity?exporter=DEU&importer=FRA&year=2020 |