teleo-codex/agents/rio/posts/figures/chart_03_hyperscaler_capex.py

86 lines
3.5 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 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 20232026: 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")