Skip to main content
revenue-model-builder logo

revenue-model-builder

Forecast revenue the way sell-side analysts do — as a driver tree the engine can defend, grade, and stress-test.

CI Docs PyPI Downloads Python 3.9+ Dependencies: zero License: MIT

中文文档:README-zh.md

60-second demo: validate, forecast with industry defaults, Monte Carlo

Zero dependencies. Pure stdlib Monte Carlo. Every number carries a source and a credibility grade.

segment_revenue = market_base × penetration × share × price total_revenue = Σ(segments) + residual


Pre-registered, out-of-sample validated

The v0.16 industry-fit claim was tested on 244 S&P 500 constituents (anti-survivorship anchor 2023-12-31) + six hand-built driver trees, per a spec frozen before any test data was pulled:

  • Driver layer: industry-default forecasts beat naive per-driver trending on 3 of 4 testable trees (SBUX 0.7% vs 3.6%, META 4.6% vs 6.7%, NVDA Gaming 3.0% vs 10.9% sMAPE)
  • Weak-fit redirect works: warnings fired 2/2 with 0/4 false alarms, and Monte Carlo P10–P90 bands framed all three weak-fit test years (JPM NII landed at P46; NVDA Data Center at P75/P66)
  • Honest nulls published: growth-revert falsified at home; totals layer belongs to statistical baselines

Full scorecard: docs/profile-validation.md

Why this exists

Open-source finance tooling covers trading and backtesting (zipline, QuantLib) and DCF valuation — but driver-based revenue forecasting, the base × penetration × share × price decomposition that sell-side analysts and PE associates actually build in Excel, has no runnable engine. Prompt skills describe the method; this library is the method — the math enforced in code, not left to a spreadsheet comment.

A revenue model lives or dies on whether you can defend every number. Here every driver carries a credibility grade (A/B/C) and a source, the residual is a first-class line (not a fudge), and checks catch the classic traps — back-solved penetration, residual dominance — before they poison the forecast.

revenue-model-builder market-sizing prompt skills DCF libs
Runnable engine ✅ ❌ prompt only ✅
Industry-aware defaults (10 profiles) ✅ ❌ ❌
Aligns to reported totals (structural residual) ✅ ❌ n/a
A/B/C grading per number ✅ ❌ ❌
Uncertainty (MC + tornado, pure stdlib) ✅ ❌ sometimes
Core dependency footprint 0 n/a usually numpy + API

One image: where driver trees work — and where they break

NVIDIA Gaming vs Data Center — actual vs driver extrapolation

Same company, same formula, same engine — Gaming (mature market) tracks at 1.0% sMAPE while Data Center (AI regime shift) misses 6× and the engine flags it before the hold-out opens, redirecting to Monte Carlo scenarios whose Bull tail frames the actual $115B. Accuracy is a property of the industry's growth mechanism — v0.16 encodes that as 10 mechanism profiles with strong/adapt/weak fit classes (validated out-of-sample).

60-second start

pip install revenue-model-builder
from revenue_model import (
    Driver, Segment, RevenueModel, BASE, PENETRATION, SHARE, PRICE,
    forecast_segment, segment_warnings, simulate_segment,
)

seg = Segment(
    "cockpit-domestic",
    base=Driver("China passenger car sales", BASE, {2022: 22.0, 2023: 23.0},
                level="A", unit="M units", source="CAAM"),
    penetration=Driver("DMS penetration", PENETRATION, {2022: 0.04, 2023: 0.06},
                       level="B", unit="fraction", source="research institute"),
    share=Driver("market share", SHARE, {2022: 0.10, 2023: 0.12},
                 level="C", unit="fraction", source="estimate"),
    price=Driver("ASP", PRICE, {2022: 600, 2023: 620},
                 level="C", unit="yuan", source="benchmark"),
    industry="consumer_electronics",   # <- the one tag that changes everything
)
model = RevenueModel("DemoCo", [seg], total_revenue={2022: 78.0, 2023: 163.0})

print(model.validate_all())               # Σ segments + residual == reported
fc = forecast_segment(seg, [2024, 2025])  # industry-default extrapolations
for w in segment_warnings(fc):            # fit verdict, before you forecast
    print(w)
mc = simulate_segment(fc, 2024, {"market share": (0.10, 0.18)}, n=20000)
print(mc.median, mc.percentiles["p5"], mc.percentiles["p95"])

Or watch the GIF above. CLI: python -m revenue_model {build, simulate, excel, docx, extract, sec, akshare, tushare}.

What's inside

Feature Benefit
Driver-tree core (pure stdlib, zero deps) Auditable base × penetration × share × price with A/B/C grades and sources — no black box
Structural residual Segments align to reported totals; the un-modeled remainder is visible, not hidden
10 industry profiles (v0.16) Tag industry= and get analyst-first defaults, industry checks, and weak-fit scenario redirects — soft defaults, hand overrides always win
Monte Carlo + tornado Per-driver uncertainty bands (not uniform %); find which assumption actually moves revenue — pure stdlib
Honest backtesting Out-of-sample sMAPE across Naive/Linear/CAGR/Holt/ARIMA + profile-implied shape methods; the validation report publishes its nulls
Data adapters (optional extras) SEC EDGAR / A-share tushare / HK akshare / Q4 IR PDFs — pull real filings into driver histories
Excel / Word output Model workbook with formulas; methodology memo with charts
LLM segment extraction Annual-report text → segment skeletons (injectable LLM, tests need no key)
  • Industry fit — the matrix, NVDA/Luxun natural experiments → docs · examples/industry_demo

  • Profile validation — the pre-registered 244-company test → docs · examples/profile_validation

  • News-impact validation — do 8-K events predict revenue? (spoiler: no, and that's the finding) → docs

  • Backtest — adaptive methods vs driver structure on real data → examples/backtest_demo

  • Real-data demos — NVDA (SEC, quarterly granularity), Luxun/Desay SV (A-share 20-year), zhipu ARR ladder →

    examples/

Install

Core is dependency-free; extras opt in:

pip install revenue-model-builder                 # core, zero deps
pip install revenue-model-builder[excel]          # openpyxl
pip install revenue-model-builder[docx]           # python-docx + matplotlib
pip install revenue-model-builder[backtest,data]  # statsmodels + akshare

Python 3.9–3.13 · MIT license · Documentation · Changelog

Design principles

Five hard-won rules, enforced structurally: structural residual · A/B/C data grading · incremental (not growth-rate) penetration · certainty pyramid · history-first workflow → docs/design-principles.md

Research/education tool, not investment advice — see DISCLAIMER.

Roadmap

  • v0.18 (data anchor): Damodaran industry benchmarks wired into profile checks — thresholds become citations
  • v0.19 (experience): profile auto-recommendation from backtest fingerprints; profile catalog page

Shipped — v0.17 (math kernel): churn-survival dynamics for subscription bases (base × (1+gross) − base × churn as the saas/telecom default, with a net-churn check that no ARPU escalator offsets a shrinking base); DampedTrend + DeceleratingCAGR graduated from the pre-registered validation into the standard backtest battery (7 methods); hand-coverage fix in forecast_segment; G1 code gate in CI (ruff, pinned ruleset + mypy on the kernel); FIG teaching-consensus citations for the weak-fit financials class.

Full history: CHANGELOG.md · Releases

Who is this for

Sell-side/PE associates who want their revenue model to be code; quants researching forecastability by industry mechanism; students learning driver-based valuation; FP&A teams escaping spreadsheet sprawl. Contributions welcome — the docs double as the design record.

API at a glance (click to expand)
from revenue_model import (
    Driver, Segment, RevenueModel,            # core tree
    BASE, PENETRATION, SHARE, PRICE,          # driver kinds
    implied_driver,                           # calibrate one driver to a known
                                              # revenue (prefer PRICE/BASE over
                                              # PENETRATION: avoids back-solve)
    forecast_segment, segment_warnings,       # industry defaults + checks
    check_segment, list_profiles, resolve_industry,
    simulate_model, simulate_segment, scenarios,   # Monte Carlo
    tornado,                                  # per-driver sensitivity ranking
)
# Driver extrapolations: trend (fit_trend), mean_reversion, erosion, growth,
# hold, logistic, incremental — and net_growth (v0.17): subscriber bases as
# base x (1+gross) - base x churn, the two knobs kept separate.

# Driver(name, kind, {year: value}, level="A"|"B"|"C", unit=..., source=...)
# Segment(name, base=..., penetration=..., share=..., price=...,
#         reported_revenue={...}, industry="saas_subscription" | "40" | "银行")
# Segment.revenue(year) -> float
# RevenueModel.validate_all() -> [YearResult(segment_sum, residual, warnings)]
# CLI: python -m revenue_model {build, simulate, excel, docx, extract,
#                               sec, akshare, tushare}

Layout: revenue_model/ (engine) · docs/ (methodology + validation reports) · examples/ (NVDA, Luxun, industry demo, profile validation, backtest, ARR ladders) · tests (303, pure-stdlib CI).

Metadata

Release files for revenue-model-builder 0.17.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for revenue-model-builder 0.17.0
File Size Uploaded
revenue_model_builder-0.17.0.tar.gz 144.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for revenue-model-builder 0.17.0
File Interpreter ABI Platform
revenue_model_builder-0.17.0-py3-none-any.whl Python 3 none any Details

Total release size: 259.6 kB

Release files / revenue_model_builder-0.17.0.tar.gz

Download URL revenue_model_builder-0.17.0.tar.gz
Size 144.0 kB
Tags Source
SHA-256 checksum
How to use checksums
fc46b9115946043d62f691432e4f03fbc61f4378b9dbea0946ce253428d99546
BLAKE2b-256 checksum
How to use checksums
5cccf58c5201f9e65aa1f054365117e763264b12e7a441cc37772135988845c0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.5

Release files / revenue_model_builder-0.17.0-py3-none-any.whl

Download URL revenue_model_builder-0.17.0-py3-none-any.whl
Size 115.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5a7ce771893910a063364f75d97846f79ad0cabbeded1fce98a0f659103bbc85
BLAKE2b-256 checksum
How to use checksums
b91c77d4bf03b5531d589fd15851747c1b50452f0ec535878ede321b38740db4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.5

Release history Release notifications | RSS feed

0.22.2

2 release files

0.22.1

2 release files

0.22.0

2 release files

0.21.0

2 release files

0.19.0

2 release files

0.18.0

2 release files

This release

0.17.0 This release

2 release files

0.16.1

2 release files

0.15.0

2 release files

0.14.1

2 release files

0.14.0

2 release files

0.13.0

2 release files

0.12.1

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page