""" Chart 3: Hyperscaler capex trajectory 2023-2026 Sources (all from 10-K filings, earnings transcripts, and consolidated reporting): - 2023 actuals: Platformonomics 2024 retrospective (implied from 62% YoY growth) - 2024 actuals: Platformonomics Cloud Table Stakes 2024 Retrospective (Feb 2025) - 2025 actuals: Companies' Q4 2025 earnings reports (Jan-Feb 2026) - 2026 guidance: Companies' Q1 2026 earnings reports (Apr-May 2026) Notes / data gaps: - Microsoft reports fiscal-year (July-June); we use calendar-year approximation - Apple and Oracle excluded (different infrastructure model, smaller scale) - 2026 numbers are guidance, not actuals; revisable each quarter - Numbers represent total company capex, ~75% of which is AI infrastructure per Q1 2026 commentary (CNBC, Feb 2026) """ from pathlib import Path import matplotlib.pyplot as plt import numpy as np HERE = Path(__file__).parent OUT = HERE / "chart_03_hyperscaler_capex.png" years = [2023, 2024, 2025, 2026] amazon = [48, 83.9, 125, 200] microsoft = [41, 75.6, 95, 190] alphabet = [32, 52.5, 92, 185] meta = [28, 39.2, 72, 135] companies = [ ("Amazon", amazon, "#FF9900"), ("Microsoft", microsoft, "#0078D4"), ("Alphabet", alphabet, "#34A853"), ("Meta", meta, "#1877F2"), ] fig, ax = plt.subplots(figsize=(11, 6), dpi=200) x = np.arange(len(years)) width = 0.20 for i, (name, vals, color) in enumerate(companies): bars = ax.bar(x + (i - 1.5) * width, vals, width, label=name, color=color, edgecolor="white") for bar, v in zip(bars, vals): ax.text(bar.get_x() + bar.get_width()/2, v + 4, f"${v:.0f}B", ha="center", va="bottom", fontsize=8, color="#333") totals = [a+b+c+d for a,b,c,d in zip(amazon, microsoft, alphabet, meta)] for xi, t in zip(x, totals): ax.text(xi, max(amazon[x.tolist().index(xi)], microsoft[x.tolist().index(xi)], alphabet[x.tolist().index(xi)], meta[x.tolist().index(xi)]) + 22, f"Total: ${t:.0f}B", ha="center", va="bottom", fontsize=10, fontweight="bold", color="#333", bbox=dict(boxstyle="round,pad=0.3", fc="#f5f5f5", ec="#aaa", lw=0.5)) # Mark 2026 as guidance ax.annotate("Guidance\n(forward)", xy=(x[3], 215), xytext=(x[3], 252), fontsize=9, color="#a33", ha="center", style="italic") # Title and labels ax.set_title("Hyperscaler capex 2023–2026: tripled in two years", fontsize=14, fontweight="bold", pad=14) ax.set_xticks(x) ax.set_xticklabels([f"{y}{' E' if y == 2026 else ''}" for y in years]) ax.set_ylabel("Capital expenditure ($B, calendar year)", fontsize=10) ax.set_ylim(0, 230) ax.legend(loc="upper left", frameon=False, ncol=4, fontsize=10) ax.grid(axis="y", alpha=0.25) ax.spines["top"].set_visible(False) ax.spines["right"].set_visible(False) caption = ( "Sources: Platformonomics 2024 Retrospective (Feb 2025), company Q4 2025 + Q1 2026 earnings releases.\n" "2026 figures are forward guidance (Microsoft $190B incl. ~$25B component price inflation; Alphabet revised Apr 2026).\n" "Microsoft reported on a fiscal year ending June; figures approximate calendar year. ~75% of capex is AI infrastructure." ) fig.text(0.02, 0.005, caption, fontsize=7, color="#555") plt.tight_layout(rect=[0, 0.05, 1, 1]) plt.savefig(OUT, dpi=200, bbox_inches="tight") print(f"wrote {OUT}") print("year | total") for y, t in zip(years, totals): print(f"{y} | ${t:.0f}B") print(f"growth 2023->2026: {totals[-1]/totals[0]:.1f}x") print(f"growth 2024->2026: {totals[-1]/totals[1]:.1f}x")