Files
ai-bubble-research/src/charts/nvidia_revenue.py

153 lines
4.2 KiB
Python

"""NVIDIA Data Center Revenue Chart"""
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
from src.data.ai_infrastructure import nvidia_revenue, nvidia_revenue_meta
from src.utils.styling import get_theme, EXPORT_DPI, REVENUE, GRAY_DARK, AI_SPEND
def plot_nvidia_datacenter() -> str:
plt.rcParams.update(get_theme())
fig, ax1 = plt.subplots(figsize=(14, 8))
# Filter data center revenue
quarters = [d["fiscal_quarter"] for d in nvidia_revenue]
dc_rev = [
d.get(
"data_center_billions",
d.get("compute_billions", 0) + d.get("networking_billions", 0),
)
for d in nvidia_revenue
]
# Calculate YoY growth
growth = []
for i in range(len(dc_rev)):
if i >= 4: # Need previous year's same quarter
prev = dc_rev[i - 4]
if prev > 0:
growth.append(((dc_rev[i] - prev) / prev) * 100)
else:
growth.append(None)
else:
growth.append(None)
# Plot DC revenue (left axis)
ax1.fill_between(range(len(dc_rev)), dc_rev, alpha=0.3, color=REVENUE)
line1 = ax1.plot(
range(len(dc_rev)), dc_rev, color=REVENUE, linewidth=2, label="Data Center Revenue"
)
ax1.set_ylabel("Data Center Revenue ($B)", fontsize=12, color=REVENUE)
ax1.set_ylim(0, max(dc_rev) * 1.2)
# Plot YoY growth (right axis)
ax2 = ax1.twinx()
growth_values = [g for g in growth if g is not None]
growth_indices = [i for i, g in enumerate(growth) if g is not None]
line2 = ax2.plot(
growth_indices,
growth_values,
color=AI_SPEND,
linewidth=2,
marker="o",
markersize=4,
label="YoY Growth Rate",
)
ax2.set_ylabel("YoY Growth Rate (%)", fontsize=12, color=AI_SPEND)
ax2.set_ylim(-50, max(growth_values) * 1.1)
# AI infrastructure buildout shading
ai_start_idx = 17 # FY2024 Q2
ax1.axvspan(ai_start_idx - 0.5, len(dc_rev) - 0.5, alpha=0.1, color=REVENUE)
ax1.text(
ai_start_idx,
max(dc_rev) * 0.8,
"AI Infrastructure\nBuildout",
fontsize=10,
ha="center",
style="italic",
color=REVENUE,
)
# Annotations
ax1.annotate(
"AI demand surge\n(>$10B DC)",
xy=(17, dc_rev[17]),
xytext=(14, dc_rev[17] + 10),
arrowprops=dict(arrowstyle="->", color="gray", lw=1),
fontsize=9,
ha="center",
)
# FY2025 Q4 annotation (index 23, ~$39.3B)
ax1.annotate(
"$39.3B DC rev",
xy=(23, dc_rev[23]),
xytext=(20, dc_rev[23] + 5),
arrowprops=dict(arrowstyle="->", color="gray", lw=1),
fontsize=9,
ha="center",
)
# FY2027 Q1 annotation (index 28, ~$75.2B, decelerating)
ax1.annotate(
"$75.2B DC rev, 83.4% YoY",
xy=(28, dc_rev[28]),
xytext=(25, dc_rev[28] + 5),
arrowprops=dict(arrowstyle="->", color="gray", lw=1),
fontsize=9,
ha="center",
)
# Title and subtitle
ax1.set_title(
"NVIDIA Data Center Revenue \u2014 Growth and Deceleration",
fontsize=16,
fontweight="bold",
)
fig.text(
0.5,
0.93,
"Quarterly revenue FY2020\u2013FY2027 | Growth rate: from 364% to ~83%",
fontsize=11,
ha="center",
style="italic",
color=GRAY_DARK,
)
ax1.set_xlabel("Quarter (FY2020-Q1 \u2192 FY2027-Q1)", fontsize=12)
ax1.grid(True, alpha=0.3)
# Format x-axis
ax1.set_xticks(range(0, len(quarters), 4))
ax1.set_xticklabels(
[q for i, q in enumerate(quarters) if i % 4 == 0],
rotation=45,
ha="right",
fontsize=8,
)
# Combined legend
lines1, labels1 = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(lines1 + lines2, labels1 + labels2, loc="upper left", fontsize=9)
fig.savefig(
"output/charts/07_nvidia_datacenter.png",
dpi=EXPORT_DPI,
facecolor=fig.get_facecolor(),
edgecolor="none",
)
plt.close(fig)
return "output/charts/07_nvidia_datacenter.png"
def main():
path = plot_nvidia_datacenter()
print(f"Chart saved: {path}")
if __name__ == "__main__":
main()