Replication of Chien, Cole, Lustig (2023, "What about Japan?") — Sections 3 to 5 — applied to UK data, 2009-Q1 to 2024-Q4.
A pipeline to construct the UK consolidated public sector balance sheet (Bank of England + central government + LGPS) and compute the realized return wedge between assets and liabilities, plus the implied wedge from CCL's asset-pricing equation. Counterfactuals follow the same structure as CCL Tables 4 panels B/C.
cd ccl_uk
python3 -m scripts.run_tests # confirm pipeline mechanics
python3 -m scripts.consolidate # see consolidated balance sheet (stub data)
python3 -m scripts.wedge # see realized/implied wedge (stub data)All scripts run on stub data by default until real data is downloaded into data/raw/. Each loader has a real implementation (load_*) and a stub (load_*_stub); the real ones currently raise NotImplementedError and need finishing once data is in place.
ccl_uk/
├── data/
│ ├── raw/ # downloaded files go here (see docs/data_manifest.md)
│ └── processed/
├── docs/
│ └── data_manifest.md # spec: every dataset, source URL, format
├── output/ # final tables/figures land here
└── scripts/
├── config.py # parameters, paths, sub-period definitions
├── schemas.py # standard balance-sheet/returns DataFrame shapes
├── load_gdp.py # ONS YBHA loader
├── load_boe.py # BoE Bankstats + APF
├── load_central_government.py # DMO + ONS PSA + UKGI
├── load_lgps.py # LGPS aggregate
├── consolidate.py # combine entities, net cross-holdings
├── wedge.py # realized returns, net-return-as-%-GDP, implied omega
└── run_tests.py # sanity checks
The pipeline is deliberately layered so each loader is independent: when you finish the BoE loader you can verify it on its own without breaking anything else.
The data manifest in docs/data_manifest.md lists every series. To get a first headline number, you need:
- GDP (ONS YBHA) — quarterly, instant download
- Gilts outstanding + APF holdings (DMO + BoE APF reports) — for the gilt netting that drives the QE story
- BoE balance sheet quarterly (BoE Bankstats Tables A1.1, A1.2) — bank reserves, currency, FX reserves
- LGPS aggregate (Scheme Advisory Board annual reports) — assets by class
Items 1-4 produce the consolidated balance sheet. Then for the wedge:
- Returns: gilts (already in Bloomberg pull as G0L0), FTSE All-Share, MSCI World ex-UK, Bank Rate
- UK equity beta and ERP (Damodaran is fine for first cut)
This gives the headline omega. Counterfactuals (no-QE, currency-hedged) come last.
LGPS consolidation is debatable. CCL consolidates GPIF for Japan because Japanese public pension reserves were historically used to fund FILP. The UK case is weaker: LGPS is funded, with pension liabilities owed to specific local authority workers. The pipeline runs both ways. Headline reports include LGPS; robustness reports without.
The asset-to-debt ratio will be much lower than Japan's. Japan's was 0.66 in 2023; the UK's is likely ~0.20-0.30. This means the wedge mechanism is going to operate primarily through the QE-induced liability transformation (long-duration gilts replaced by floating-rate reserves), not through leveraged risky-asset holdings. The story to tell is about duration matching, not carry-trade returns.
Counterfactual sizing for UK QE is smaller than for Japan. UK QE literature (Joyce, Tong, Woods 2011; D'Amico-King 2013) suggests UK QE compressed gilt yields by roughly 50-100 bps, vs CCL's 200-300 bps for Japan. This means the UK no-QE counterfactual should be more conservative.
The 2022 LDI episode is a natural lab. During September 2022 the gilt market briefly crashed and the BoE intervened by purchasing long-dated gilts on financial-stability grounds (i.e., to halt forced selling by pension funds with leveraged liability-driven investment portfolios). This is plausibly the cleanest UK episode of forced bond-holding-as-financial-repression in the sample. Worth a dedicated paragraph in the discussion.
- No duration analysis (CCL Section 6). Out of scope per project decision.
- No household welfare analysis (CCL Section 7). Out of scope.
- No CIP-deviation as repression evidence (CCL Section 5.1). UK is not Japan in this respect; sterling is not a carry-funded currency.
- No structural model. Pure descriptive empirical replication.
- All loaders currently raise
NotImplementedErrorfor the real path; need to finish per actual file structure when data is indata/raw/. - Stub data is rough; the wedge values from stubs are not meaningful.
- The asset-class-to-return-series mapping in
wedge.py(asset_return_map) assumesasset_foreign_securitiesreturns the equity index. If LGPS data lets you split foreign equity from foreign bonds, refine the mapping. - The
liab_pension_fundedrow gets no return assignment in the current code (treated as accrual-basis). This is defensible but worth documenting. - "Annualized GDP × % of GDP" ratios assume quarterly GDP × 4 ≈ annualized rate. Fine for sample averages, but for a single quarter you may want trailing-4Q sum instead. Refine if precision matters.