Phased portfolio commissioning
Generated: 2026-05-08. Model: 10-site JS-SEZ stylised composite portfolio,
identical site sizes to aggregator_portfolio.md, but each site has a
commissioning_year offset (0 = project t=0). Two anchors come online each
of years 0–4 plus one in year 5, mirroring the public-announcement wave
pattern (Sedenak phases, AirTrunk JHB1 staging, YTL Green DC tranches).
Per-unit economics auto-derived from btm_economics_dc100.json (same as
the instant-deployment aggregator).
Phasing capex over 6 years improves portfolio NPV by +371 M RM (+17%) vs instant deployment — but the absolute headline is still −1,843 M, because the BESS gap is structural, not timing-related.
| Metric | Instant deployment | Phased (default) | Δ phased |
|---|---|---|---|
| Portfolio NPV | −2,213 M | −1,843 M | +371 M |
| PV capex (undiscounted) | 2,572 | 2,572 | 0 |
| PV capex @ PV t=0 | 2,572 | 2,106 | −466 |
| BESS capex (undiscounted) | 3,675 | 3,675 | 0 |
| BESS capex @ PV t=0 | 3,675 | 3,009 | −666 |
| Final aggregate tier | Tier 2: DRC + cap | Tier 2: DRC + cap | same |
| Project end year | year 20 | year 25 | +5 yr |
The +371 M lift is essentially a capital-cost-of-money refund: discounting the late-coming sites’ capex saves ~1.1 B RM total (PV+BESS combined), but those sites also accrue savings later, so the net benefit is the timing spread between capex (early in the site’s life) and savings (across the 20-yr horizon, more of which sits beyond t=0).
What phasing actually does (and doesn’t do)
Section titled “What phasing actually does (and doesn’t do)”Does do
Section titled “Does do”- Discount distant capex. Late-stage BESS capex at year 5 is worth only 68% of its nominal value in t=0 terms. On 184 MW of BESS at 5 M RM/MWh, that’s meaningful (~660 M present-value savings on capex alone).
- Defer commercial risk. A phased build lets each tranche learn from the prior one’s interconnection / O&M lessons before the next tranche commits.
- Match anchor-tenant ramp. Hyperscaler MW commissions in waves; phased PV+BESS matches the load curve more closely than a one-shot install would.
Doesn’t do
Section titled “Doesn’t do”- Close the BESS gap. At 5 M RM/MWh capex with current BTM-only economics (100 kRM/MWh/yr incremental), the per-MWh NPV is still structurally negative. Phasing rearranges the cashflow — it doesn’t make the gap go away.
- Earn higher VPP-tier revenue. The portfolio still tops out at Tier 2 at full deployment (~184 MW BESS); phasing doesn’t push us into Tier 3 (>200 MW) without changing the underlying portfolio.
- Move the breakeven aggregator rate. The 162 kRM/MW/mo breakeven from
aggregator_portfolio.mdis invariant — phasing doesn’t change per-MW economics.
Year-by-year online-capacity ramp
Section titled “Year-by-year online-capacity ramp”| Year | Online PV (MW) | Online BESS (MW) | Aggregate tier |
|---|---|---|---|
| 0 | 0 | 0.0 | Sub-market (capex year only) |
| 1 | 75 | 18.8 | Tier 1: minor DRC |
| 2 | 195 | 48.8 | Tier 1: minor DRC |
| 3 | 315 | 78.8 | Tier 2: DRC + capacity |
| 4 | 495 | 123.8 | Tier 2: DRC + capacity |
| 5 | 615 | 153.8 | Tier 2: DRC + capacity |
| 6 | 735 | 183.8 | Tier 2: DRC + capacity (full) |
| 7-20 | 735 | 183.8 | Tier 2: DRC + capacity |
| 21-25 | tail-off (sites decommissioning at site_horizon=20) |
The portfolio crosses into Tier 2 (60 kRM/MW/mo, DRC + capacity) at year 3, two years earlier than the median site’s mid-life — meaning 3+ years of sub-tier VPP revenue lost vs the (counterfactual) world where Tier 2 clears immediately at full deployment.
How to use this model
Section titled “How to use this model”- Deal-team realism check. Headline NPVs in
aggregator_portfolio.mdassume instant build-out, which overstates the BESS gap by ~17%. Use this report’s −1,843 M for boardroom pricing instead. - Phasing-strategy A/B testing. Pass a custom
tuple[TimedSite, ...]intoevaluate_phased_portfolio()to compare alternative deployment sequences (e.g., “frontload BESS into year 0” vs “BESS-only-after-year-3”). - Tier-progression diagnostics. The schedule field in the JSON output shows which years the portfolio sits in which tier — useful for negotiating tier-conditional VPP service contracts where revenue switches on at a known threshold.
Method
Section titled “Method”For each year t in [0, end_year]:
- Capex(t) = sum of (PV + BESS) capex for sites whose
commissioning_year == t. - Augmentation(t) = sum of (0.5 × BESS capex) for sites whose
commissioning_year + 10 == t. - Online sites at t = sites with
commissioning_year < t ≤ commissioning_year + 20. - Savings(t) =
online_pv_mw × pv_per_mw + online_bess_mwh × bess_per_mwh. - VPP revenue(t) =
online_bess_mw × tier(online_bess_mw) × 12 months. - OpEx(t) =
online_pv_mw × pv_opex + online_bess_mwh × bess_opex. - Net(t) =
−Capex(t) − Augmentation(t) + Savings(t) + VPP rev(t) − OpEx(t).
NPV = Σ_t Net(t) / (1 + r)^t with r = 8%.
The model converges to aggregator.evaluate_portfolio exactly when every
site’s commissioning_year = 0 — pinned by
tests/test_portfolio_timeline.py::test_phased_with_all_zero_commissioning_matches_aggregator_exactly.
Limitations
Section titled “Limitations”- Commissioning timing is hard-coded in
DEFAULT_TIMELINEfrom a stylised wave pattern, not from realdc_trackerdates (which are private and not yet populated; see CLAUDE.md). Whendc_tracker.sitesbecomes populated, swap the default in. - No revenue ramp during the commissioning year. A site commissioned in
year
cproduces zero savings in yearcand full savings from yearc+1. In reality there’s a partial-year ramp; the bias is small (~½ year × per-site savings) and fits within the existing capex-vs-opex precision band. - Per-MW economics are still linear (validated invariant). Phasing does not change the per-MWh BESS gap — it only shifts the cashflow.
Related reports
Section titled “Related reports”aggregator_portfolio.md— instant-deployment baseline (−2,213 M).vpp_service_revenue_required.md— single-site 209 kRM/MW/mo breakeven.bess_trigger_curve.md— capex-fall × VPP-revenue trigger matrix.risk_adjusted_npv.md— Monte Carlo on capex / discount / load growth.
JSON output
Section titled “JSON output”reports/portfolio_timeline.json has the full schedule (per-year cashflow
trace), all aggregate present-value capex / augmentation, and both phased
and instant NPVs for one-shot delta comparison.