teleo-codex/agents/rio/posts/figures/chart_02_finance_share_gdp.py
m3taversal 495a710123 rio: add 8 original charts + embed in print edition, regenerate PDF
- 8 matplotlib charts generated from FRED, BEA, and primary 10-K data
- All chart Python scripts committed alongside PNGs for reproducibility
- Source data CSVs and BEA XLS pulled directly from public APIs
- Print MD updated to embed images inline (was: text-only callouts)
- PDF regenerated via tectonic (1.4MB with all charts)

Corrections from v1 prose (verified against actual data):
- Finance share of corporate profits peak: 34.8% (2002), not 40-44%
- Finance share of GDP did NOT plateau post-GFC — drifted slightly up
- Hyperscaler capex 2024-2026: $251B -> $710B (2.8x, not 3x)

Data gaps flagged in chart captions:
- Philippon 130-year unit-cost series replaced with BEA 1997-2025
- Carta middle-bucket percentages estimated from blog text
- Mega-round pre-2018 shares interpolated from round counts

Pentagon-Agent: Rio <244ba05f-3aa3-4079-8c59-6d68a77c76fe>
2026-05-18 16:01:24 +01:00

98 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Chart 2: Finance & insurance value added as % of US GDP, 1997-2025
Source: BEA Industry Economic Accounts, Table 1.10 (TVA110-A annual)
URL: https://apps.bea.gov/industry/Release/XLS/GDPxInd/ValueAdded.xlsx
Published April 9, 2026. Annual frequency. NAICS-based.
Key story: NO COMPRESSION. Finance and insurance share of GDP went from
6.7% (1997) to 7.9% (2025), oscillating between a 5.9% GFC trough (2008)
and an 8.0% peak (2020). Every prior tech wave was supposed to compress this.
It didn't.
Data gap: pre-1997 data uses SIC industry codes (not NAICS) and lives in
BEA historical archives. The Greenwood/Ialenti/Scharfstein 2025 Annual
Review paper and Philippon's 2015 AER paper provide the longer-run series
back to 1880. We don't reproduce their data here — we cite it in caption.
"""
from pathlib import Path
import csv
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
HERE = Path(__file__).parent
OUT = HERE / "chart_02_finance_share_gdp.png"
years, vals = [], []
with open(HERE / "data" / "bea_finance_share_gdp_1997_2025.csv") as f:
r = csv.DictReader(f)
for row in r:
years.append(int(row["year"]))
vals.append(float(row["finance_insurance_pct_gdp"]))
fig, ax = plt.subplots(figsize=(10, 5.5), dpi=200)
ax.plot(years, vals, color="#1f4e79", linewidth=2.0, marker="o", markersize=4)
ax.fill_between(years, vals, alpha=0.12, color="#1f4e79")
# Reference: Philippon "constant unit cost of intermediation" implies stable ~2% of GDP for the
# *unit cost* metric — different from value-added, but worth annotating as the related claim.
# The relevant horizontal here is the 1997 baseline of 6.7%.
ax.axhline(6.7, color="#888", linestyle="--", linewidth=0.8, alpha=0.6)
ax.text(1997.5, 6.55, "1997 baseline: 6.7%", fontsize=8, color="#666", va="top")
# Annotate key points
ax.annotate(
f"GFC trough\n2008: {vals[years.index(2008)]:.1f}%",
xy=(2008, vals[years.index(2008)]),
xytext=(2003.5, 5.4),
fontsize=8,
arrowprops=dict(arrowstyle="->", color="#666", lw=0.6),
)
peak_idx = vals.index(max(vals))
ax.annotate(
f"Peak\n{years[peak_idx]}: {vals[peak_idx]:.1f}%",
xy=(years[peak_idx], vals[peak_idx]),
xytext=(years[peak_idx] - 4, vals[peak_idx] + 0.5),
fontsize=8,
arrowprops=dict(arrowstyle="->", color="#666", lw=0.6),
)
ax.annotate(
f"2025: {vals[-1]:.1f}%",
xy=(years[-1], vals[-1]),
xytext=(years[-1] - 5, vals[-1] - 0.5),
fontsize=8,
arrowprops=dict(arrowstyle="->", color="#666", lw=0.6),
)
ax.set_title(
"Finance & insurance value added as % of US GDP, 19972025",
fontsize=13,
fontweight="bold",
pad=14,
)
ax.set_xlabel("Year", fontsize=10)
ax.set_ylabel("Finance & insurance value added / GDP", fontsize=10)
ax.yaxis.set_major_formatter(mtick.PercentFormatter(decimals=1))
ax.set_ylim(5.0, 9.0)
ax.set_xlim(1996, 2026)
ax.grid(alpha=0.25)
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
caption = (
"Source: BEA Industry Economic Accounts, Table 1.10 (Value Added as % of GDP), April 2026. NAICS-based.\n"
"Pre-1997 series exists in Philippon (AER 2015) and Greenwood/Ialenti/Scharfstein (Annual Review of\n"
"Financial Economics 2025); these show finance share rose from ~2.8% in 1950 to current levels."
)
fig.text(0.02, 0.005, caption, fontsize=7, color="#555")
plt.tight_layout(rect=[0, 0.045, 1, 1])
plt.savefig(OUT, dpi=200, bbox_inches="tight")
print(f"wrote {OUT}")
print(f"data span: {years[0]}{years[-1]} ({len(years)} years)")
print(f"min: {min(vals)}% in {years[vals.index(min(vals))]}")
print(f"max: {max(vals)}% in {years[vals.index(max(vals))]}")
print(f"latest: {vals[-1]}% ({years[-1]})")