Skip to main content

Period-by-period mechanical debt-waterfall engine for structured finance

Project description

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

waterfall_py-0.2.0.tar.gz (68.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

waterfall_py-0.2.0-py3-none-any.whl (53.7 kB view details)

Uploaded Python 3

File details

Details for the file waterfall_py-0.2.0.tar.gz.

File metadata

  • Download URL: waterfall_py-0.2.0.tar.gz
  • Upload date:
  • Size: 68.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for waterfall_py-0.2.0.tar.gz
Algorithm Hash digest
SHA256 5e5817bac1851d51a67a6e957e7f83a409cf0bc706158a63de3c29629b6cb820
MD5 c31030abc07aaf425065474ae18ee728
BLAKE2b-256 92ba63b33e528d55be203a0895cb97fb87d067e86c115c5836f2f41226df116d

See more details on using hashes here.

Provenance

The following attestation bundles were made for waterfall_py-0.2.0.tar.gz:

Publisher: release.yml on Jaypatel1511/waterfall-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file waterfall_py-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: waterfall_py-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 53.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for waterfall_py-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8d6e9f0eef15670e6c6f0105049378c3030955297088ddde9a1f7cb514e127a5
MD5 5a24b4e159fd1181ed7ceb579a729813
BLAKE2b-256 879b470fd227825797523a7f1dde9dd3fbaeb972f549d15f58b99484d6633b69

See more details on using hashes here.

Provenance

The following attestation bundles were made for waterfall_py-0.2.0-py3-none-any.whl:

Publisher: release.yml on Jaypatel1511/waterfall-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page