A one-period, annual, flow-of-funds model of the AI capital build. Money enters as compute demand from AI labs, passes through six balance sheets that decide how much to spend, is allocated across five physical supply tiers, and lands as revenue and profit on twenty-six named public companies. Every levered decision in the chain is priced off the US Treasury curve plus a per-issuer credit spread.
It is a what-if engine, not a forecast. Live data sets the sliders' default positions; the user can move any of them. The output is not "what will happen" but "if this driver moves, who is exposed, by how much, and through which channel."
The solver runs top to bottom. Each stage consumes the one above it.
Inputs: y10, y20, y30 (UST yields, live from FRED) and spread_multiple (live from ICE BofA OAS buckets, base 1.0).
Each entity carries a rating bucket (AAA → B) and a hand-set issuer spread in basis points.
all_in_cost_of_debt = treasury_yield + issuer_spread × spread_multiple
Design choice: the live OAS feed scales the level of spreads per rating bucket. The issuer-specific spread stays hand-set. This keeps knowledge like "Oracle trades wide of its BBB rating" intact across a live refresh. This layer is computed first because every downstream node consumes Δ(all_in_cost_of_debt) versus base.
OpenAI, Anthropic, and "everyone else" carry a compute-spend figure relative to a base year. A capex driver scales this demand (1.0 = base; 0.40 = the "winter" case).
These figures are commitments and press reports. Neither lab files with the SEC. They are permanently flagged ESTIMATE and nothing in the ingest pipeline may present them otherwise.
Six hyperscalers — Amazon, Google, Microsoft, Meta, Oracle, SpaceX/xAI — convert demand into capex, damped two ways:
rate_drag ≥ 0.60 is the floor.finance_drag scales with leverage × Δ(all_in_cost_of_debt), floored at 0.10. Same Treasury shock, different leverage and spread → different capex response.System capex at base is the sum of the six carriers' capex, 704.1 ($B).
CAPEX_SPLIT distributes each capex dollar across destinations: silicon; power & grid equipment; utilities / IPPs; oil & gas midstream; telecom / fiber; land & construction.
Within the power dollar there is a zero-sum sub-allocation between gas-fired and utility-procured power:
gas_tilt = gas_share / BASE_GAS # BASE_GAS = 0.25
util_tilt = (1 - gas_share) / (1 - BASE_GAS)
Raising gas_share moves dollars from NextEra / Dominion / AEP to Williams / Energy Transfer / Kinder Morgan / Cheniere / EQT. Same procurement dollar, different pipe. At gas_share = BASE_GAS both tilts are exactly 1.0.
BASE_GAS is a calibration constant. When EIA data moves the live gas_share, it moves the slider's default position, not the baseline the tilts are computed against.
For each of the 26 suppliers:
Δrevenue ≈ base_revenue × ai_exposure × Δ(tier_flow) × cushion_damping
pct = Δrevenue / base_revenue
Two estimated parameters dominate this stage:
At base every pct is exactly 0.00% (INV-1).
Revenue change becomes profit through:
power_price_index (EIA wholesale power vs. trailing 3-year mean) and Henry Hub gas for the gas-exposed names.margin ≥ -0.30 is the floor. A single scenario can hit one company three times: demand, input cost, refinancing.
Hyperscaler profit is a delta off a stated base, not a rebuilt income statement. The critical equation:
dep = (prior_cohort × depreciable_share / life)
+ (current_capex × depreciable_share / life) × new_in_service_share
Last year's chips and buildings are already in service and keep depreciating whether or not this year's capex is cut. In the winter case, capex falls ~78% while system depreciation moves only 109 → 106 ($B). About 84% of depreciation is locked.
An early prototype used dep = current_capex / life. That made hyperscaler profits *rise* in an AI winter — economically backwards. The corrected form is guarded by INV-2 and is the single most important analytical result the tool produces.
capex_beta and rate_beta are computed numerically: perturb the driver by ±ε, re-solve, take the finite difference of each supplier's revenue. This is a sensitivity, not a regression.
The market-data phase adds a realised 60-day beta of each supplier to an equal-weight capex-proxy basket (AMZN, GOOGL, MSFT, META, ORCL) and shows it next to the modelled beta. Where they diverge sharply, one of two things is true: the model's exposure estimate is wrong, or the market is mispricing the exposure. The page does not decide which. It shows both and labels the gap.
capex = 0.40, life = 4, spreads wideningCAPEX_SPLIT. Silicon takes the largest absolute cut because it is the largest share.Step 2 is driven by finance drag alone. The story is the dispersion across carriers: Oracle and xAI at roughly −20% capex, Microsoft and Google at roughly −12%. Credit quality, not the level of rates, determines who cuts (INV-3). Everything downstream inherits that ordering.
gas_share 0.25 → 0.70No new money. Midstream and gas-fired names rise; regulated utilities fall by the same procurement dollar. This is INV-4 in motion, and it is the scenario most likely to be misread as "gas is winning" when it is actually "the same budget moved."
Each regression test in tests/test_invariants.py encodes one economic claim:
| Invariant | Economic claim |
|---|---|
| INV-1 base reconciles to zero | The model has no hidden bias. Every departure from zero was caused by a driver the user moved. |
| INV-2 depreciation wall | Capital is a stock. A flow cut does not unwind the stock. Profits fall in a winter, they do not rise. |
| INV-3 credit > risk-free | For levered issuers, the spread and leverage dominate the Treasury move. Rate shocks are dispersive, not uniform. |
| INV-4 gas share zero-sum | Power procurement is a budget, not an appetite. Fuel mix is a reallocation. |
| INV-5 provenance never silent | You always know which number is filed, which is live, which is a guess, and which is stale. |
| INV-6 clamps stay | The model cannot produce absurdities at slider extremes that get screenshotted out of context. |
A reader of any scenario output should be able to trace every number back to one of these six claims plus the estimated parameters in §4.
FILED / LIVE)DGS10, DGS20, DGS30, daily.companyfacts, annual 10-K frames. The XBRL tag that resolved is recorded per field. Fiscal years are carried through and labelled — Oracle (May), NVIDIA (January) and Microsoft (June) are not coerced into calendar years.gas_share default.ESTIMATE / GUIDANCE)CAPEX_SPLIT** across the five tiers. Calibrated from disclosures and industry estimates.FILED and a test asserts it.| Flag | Meaning |
|---|---|
LIVE | Fetched from a live source within the freshness window; as_of shown |
FILED | From an SEC filing; fiscal period and XBRL tag shown |
GUIDANCE | Company-stated forward figure, not yet filed |
ESTIMATE | Analyst judgement; will not be upgraded by ingest |
STALE | A live fetch failed; the value shown is the last good one and is flagged as such |
USER | Overridden by the user in the assumptions panel |
A STALE flag on any field raises a visible banner. The model keeps solving.