feat(chart): NVIDIA data center revenue with growth deceleration
This commit is contained in:
152
src/charts/nvidia_revenue.py
Normal file
152
src/charts/nvidia_revenue.py
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
"""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, 70.7% 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 323% to ~70%",
|
||||||
|
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()
|
||||||
Reference in New Issue
Block a user