Data and code for The Great Reversal report.
Development Finance Observatory | ONE DATA
This project analyzes net financial flows to low and lower-middle income countries by combining:
- Official Development Assistance (ODA) and Other Official Flows data from OECD DAC
- Total Official Support for Sustainable Development (TOSSD)
- Debt statistics from World Bank International Debt Statistics
| Source | Provider | What It Contains |
|---|---|---|
| OECD DAC/CRS | OECD | ODA grants, loans, equity investments, other official flows |
| TOSSD | International Forum on TOSSD | TOSSD |
| International Debt Statistics | World Bank | PPG long-term external debt disbursements and debt service |
Net flows = Gross inflows − Debt service payments
- PPG debt: Public and Publicly Guaranteed long-term external debt
- Country coverage: Low Income Countries (LIC) and Lower-Middle Income Countries (LMIC) only
- Excluded: Upper-middle income countries, high income countries
- Outliers excluded: China, Libya, Ukraine, Venezuela (as recipients)
- Special cases: Ethiopia classified as LIC throughout
- Prices: Constant 2024 USD using
pydeflate
# Prerequisites: Python 3.13+, uv package manager
git clone https://github.com/ONEcampaign/DFO-Net-Flows.git
cd DFO-Net-Flows
uv sync
# Generate the analysis
uv run python scripts/analysis/net.py
uv run python scripts/analysis/replication.py
# Output: output/replication_analysis.xlsx┌─────────────────────────────────────────────────────────────┐
│ DATA SOURCES │
├─────────────────────────────────────────────────────────────┤
│ OECD DAC/CRS TOSSD World Bank IDS │
│ (oda.py) (tossd.py) (debt.py) │
└──────────┬─────────────┬────────────────┬───────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ ANALYSIS LAYER │
├─────────────────────────────────────────────────────────────┤
│ inflows.py → Combines grants + debt + other disbursements │
│ outflows.py → Debt service payments (principal + interest) │
│ net.py → Merges inflows/outflows + adds metadata │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ OUTPUT FILES │
├─────────────────────────────────────────────────────────────┤
│ net_flows_agg.parquet - Main dataset │
│ replication_analysis.xlsx - Report figures with data │
└─────────────────────────────────────────────────────────────┘
The replication.py module provides statement-driven analysis that matches claims from The Great Reversal report. Each
statement generates an Excel sheet with:
- Title and narrative explaining the finding
- Backing data that supports the claim
Run uv run python scripts/analysis/replication.py to generate all statement sheets.
| File | Description |
|---|---|
inflows_by_source_and_type.parquet |
Inflows by source (DAC, TOSSD, IDS) |
outflows_by_source_and_type.parquet |
Debt service payments |
net_flows_agg.parquet |
Combined flows with country metadata |
replication_analysis.xlsx |
Report figures with backing data |
Use the research module for flexible queries:
from scripts.research.data import get_flows
from scripts.research.aggregate import by_year, by_period, totals
# Get all LIC/LMIC flows (excludes outliers by default)
data = get_flows()
# Filter by region and time
africa = get_flows(regions=["Africa"], years=(2020, 2024))
# Filter by counterpart type
bilateral = get_flows(counterpart_types=["Bilateral"])
# Filter by debt distress risk
high_risk = get_flows(debt_distress=["High", "In Distress"])
# Aggregate by year
yearly = by_year(data)
# Compare periods
periods = by_period(data, periods=[(2010, 2014), (2020, 2024)])Available filters:
| Parameter | Description | Example |
|---|---|---|
years |
Time range tuple | (2020, 2024) |
income_levels |
Income classification | ["LIC", "LMC"] |
regions |
Geographic region | ["Africa", "Asia"] |
counterpart_types |
Source type | ["Bilateral", "Multilateral", "Private"] |
countries |
Specific countries | ["Kenya", "Nigeria"] |
debt_distress |
DSA risk level | ["High", "In Distress"] |
include_outliers |
Include China, Libya, etc. | True |
DFO-Net-Flows/
├── scripts/
│ ├── sources/ # Data fetching
│ │ ├── oda.py # OECD DAC/CRS data
│ │ ├── debt.py # World Bank IDS
│ │ ├── tossd.py # TOSSD data
│ │ └── metadata.py # Income levels, DSA risk
│ ├── analysis/ # Processing pipeline
│ │ ├── inflows.py # Combine inflow sources
│ │ ├── outflows.py # Debt service payments
│ │ ├── net.py # Main pipeline
│ │ └── replication.py # Report figures
│ ├── research/ # Researcher-facing API
│ │ ├── data.py # get_flows() function
│ │ ├── aggregate.py # by_year, by_period, totals
│ │ └── metrics.py # Shares, ratios, growth
│ └── config.py # Configuration
├── raw_data/ # Input data files
├── output/ # Generated outputs
└── pyproject.toml # Dependencies
Key libraries:
| Library | Purpose |
|---|---|
oda-data |
OECD DAC/CRS data access |
bblocks-data-importers |
World Bank IDS data |
pydeflate |
GDP deflation for constant prices |
pandas |
Data manipulation |
Install with: uv sync
- TOSSD: 2024 data interpolated from 2020-2023 average (publication lag)
- Chinese development finance: Based on debt service data; AidData commitment tracking captures different flows
- Not included: Philanthropic flows, remittances, illicit financial flows
- Not covered: Private capital flows (FDI, portfolio investment)
# Lint and format
uv run ruff check scripts/
uv run ruff format scripts/
# Type checking
uv run mypy scripts/
# Run all pre-commit hooks
pre-commit run --all-filesDevelopment Finance Observatory | ONE Data (2025). The Great Reversal.
Questions or feedback? Open an issue on GitHub or contact ONE Data.