waterfall-py 💧
Period-by-period mechanical debt-waterfall engine for structured finance.
waterfall-py runs a mechanical, auditable cash-flow waterfall over a user-supplied CFADS stream and a capital stack of senior + mezzanine + residual equity. It is a tight core: it computes what the deal terms and the CFADS imply, period by period, and proves the arithmetic with built-in validation assertions. It does not project cash flows, make credit judgments, or model anything on the Limitations list.
Mechanical waterfall computation only. Not a credit recommendation. CFADS inputs are user-supplied projections, not modeled cash flows.
The single source of truth for every modeling decision is
docs/methodology.md, a copy of which is bundled in the
wheel and locatable via waterfall.get_methodology_path().
Installation
pip install waterfall-py
Both import waterfall_py and import waterfallpy resolve to the same package
as import waterfall.
Quickstart
from datetime import date
from waterfall import run, Deal, Tranche, ReserveConfig, CovenantConfig, SweepConfig, SweepBand
senior = Tranche(name="Term A", tranche_type="senior", principal=10_000_000,
coupon=0.06, day_count="ACT/360", amort_type="fully_amortizing",
term_periods=8)
mezz = Tranche(name="Mezz", tranche_type="mezzanine", principal=2_000_000,
coupon=0.10, amort_type="bullet", term_periods=8)
equity = Tranche(name="Sponsor Equity", tranche_type="equity", principal=3_000_000)
deal = Deal(
deal_close_date=date(2024, 1, 1),
operations_start_date=date(2024, 1, 1),
period_frequency="Q", # M / Q / SA / A
deal_type="PF", # PF or CRE
tranches=[senior, mezz, equity],
cfads_stream=[1_400_000] * 8, # one operating CFADS per period
data_currency="USD",
reporting_basis="calendar",
reserves=[ReserveConfig(reserve_type="DSRA", months_dsra=6, opening_balance=750_000)],
covenants=[CovenantConfig(metric="DSCR", trap=1.10, default=1.00)],
sweep=SweepConfig(bands=[SweepBand(4.0, 1.0), SweepBand(3.0, 0.5)]),
)
result = run(deal)
from waterfall.report import export
df = export.to_period_dataframe(result) # native DataFrame
print(export.render_text(result)) # text report (opens with the disclaimer)
export.to_excel(result, "deal.xlsx") # openpyxl workbook
Waterfall Priority (LOCKED)
Each operating period, operating cash (CFADS) — supplemented at the steps they fund by non-CFADS sources — is applied in one acyclic priority order:
1. Senior fees & administrative expenses
2. Senior debt service (interest, then scheduled principal, pari-passu pro-rata)
shortfall covered by: DSRA draw, then equity cash-injection cure
3. Required reserve funding / replenishment (DSRA to required, then others)
4. Mezzanine debt service
5. Mandatory ECF sweep — ECF ≡ cash remaining after steps 1–4; leverage-banded;
forced to 100% under a cash-trap
6. Permitted junior uses from retained ECF (6a capex / 6b top-ups / 6c distributions)
7. Residual to equity (absent an active cash-trap)
Reserve releases and event proceeds are applied on a separate proceeds path (to outstanding debt in priority, then equity — the equity leg gated under a cash-trap while debt remains). CFADS stays operating-only; every non-CFADS source is recorded separately.
Built-in validation assertions (primary defensibility)
Every period, the engine asserts — raising a typed exception on any failure:
- Source/use tie-out at close — sources = uses
- Period cash-conservation — Σ all modeled sources = Σ all modeled uses (enumerated from the per-period ledger)
- Principal trace — opening + facility draws − scheduled amort − prepayments − sweeps = closing, per tranche
- Interest reconciliation — rate × average balance × day-count fraction = period interest
- Reserve roll-forward — closing = opening + funding + top-ups − draws − releases, per reserve
- Capital-account roll-forward — opening + contributions − distributions = ending
Covenants
DSCR, LLCR, PLCR (PF only), LTV, debt yield, Debt/EBITDA, fixed-charge and interest coverage are defined inline by formula. A zero denominator (e.g. debt fully repaid) reports n/a — never ∞, 0, or a raised error. Each covenant carries a three-tier cushion: performance / trap / default. Every breach flag is labeled a mechanical test result computed by the engine from user-supplied CFADS and the deal terms — never a legal conclusion.
Out of scope (raise UnsupportedFeatureError)
B-piece / A-B mechanics, preferred equity, construction-period modeling, sculpted-to-DSCR amortization, defeasance, OID, multi-currency, ACT/ACT day-count, tax-credit / SPV-tax modeling, and NOI/CFADS projection. See the Limitations section of the methodology.
Running tests
PYTHONPATH=. pytest tests/ -v
License
MIT — Jaypatel1511
Metadata
Release files for waterfall-py 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| waterfall_py-0.2.0.tar.gz | 68.3 kB | With provenance | Details for waterfall_py-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| waterfall_py-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for waterfall_py-0.2.0-py3-none-any.whl |
Total release size: 122.1 kB
Release files / waterfall_py-0.2.0.tar.gz
| Download URL | waterfall_py-0.2.0.tar.gz |
|---|---|
| Size | 68.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5e5817bac1851d51a67a6e957e7f83a409cf0bc706158a63de3c29629b6cb820
|
|
BLAKE2b-256 checksum How to use checksums |
92ba63b33e528d55be203a0895cb97fb87d067e86c115c5836f2f41226df116d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 14, 2026.
Transparency logRelease files / waterfall_py-0.2.0-py3-none-any.whl
| Download URL | waterfall_py-0.2.0-py3-none-any.whl |
|---|---|
| Size | 53.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8d6e9f0eef15670e6c6f0105049378c3030955297088ddde9a1f7cb514e127a5
|
|
BLAKE2b-256 checksum How to use checksums |
879b470fd227825797523a7f1dde9dd3fbaeb972f549d15f58b99484d6633b69
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 14, 2026.
Transparency logSecurity for waterfall-py 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for waterfall_py-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 14, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.