Equity waterfall calculator (LP/GP pref, catch-up and promote)
Equity waterfall calculator: LP/GP distributions with preferred return, catch-up, IRR hurdle tiers and promote, plus each party's IRR and multiple.
What it computes
An equity waterfall divides a real estate deal's cash flows between the limited partner (LP) investors and the general partner (GP) sponsor under the terms of an operating agreement. The calculator runs project-level equity cash flows through a preferred return, return of capital, an optional GP catch-up, a series of LP IRR hurdle tiers with promote splits, and a residual split. It returns every period's distributions by tier, the GP's promote, each party's contributions, distributions, profit, equity multiple and IRR, and the project IRR before the waterfall.
Method and conventions
Each negative cash flow is a contribution, split lp_share to the
LP and the rest to the GP as co-investor. Each positive cash flow is a
distribution and runs through the steps below in order. Capital, pref and the
non-promote part of every split are paid to LP and GP pro rata to capital.
-
Pref. It accrues from the period after each contribution,
on balances after the previous period's flows. With
compoundingcompound, unreturned capital plus unpaid pref earns(1 + rate_annual)^(1 ÷ periods_per_year) − 1each period, so a fully paid pref equals an IRR of the pref rate. Withsimple, each period accruesunreturned capital × rate_annual ÷ periods_per_year, and unpaid pref earns nothing. -
Return of capital. By default accrued pref is paid first
and then capital.
distribution_ordercapital_then_prefreverses that. -
Catch-up.
gp_shareof each dollar goes to the GP as promote, and the rest goes to investors pro rata. This continues until the GP's cumulative promote equalstarget_promoteof all profit distributed so far. Profit means everything other than return of capital, including pref paid to both LP and GP. -
IRR tiers. Each tier tracks an LP balance. The balance
grows each period at
(1 + until_irr)^(1 ÷ periods_per_year) − 1, rises with LP contributions and falls with every LP distribution. The tier pays with itspromoteuntil that balance reaches zero, which is the point where the LP's IRR reaches the hurdle. -
Residual. Everything after the last tier is split with
residual_promoteto the GP.
Each period's LP distribution is rounded to the cent and the GP receives the rest of the cash flow, so each row foots. IRRs are annualized from the period flows.
Operating agreements differ on most of these points. Pref may compound or
accrue simply (pref.compounding). Hurdles may compound at an
effective periodic rate, as FactLot does, or at a nominal rate ÷ periods.
Hurdles may be tested on the LP's cash flows, as here, or on all investors'
cash flows, or by equity multiple instead of IRR. A catch-up may be full
(gp_share of 1) or partial (for example 0.5), and its target may
or may not count the pref as profit. FactLot fixes the hurdle basis and the
catch-up definition as described. The pref, order, catch-up, tiers and
residual are all inputs. The result warns when a tier hurdle is at or below
the pref, when a catch-up has no pref, and when the catch-up target differs
from the next split's promote.
Inputs that matter
-
cash_flows: equity flows at t = 0, 1, 2 and so on, negative for contributions and positive for distributions. -
periods_per_year: 1, 4 or 12. It sets the periodic pref and hurdle rates and annualizes the IRRs. -
lp_share: the LP's share of every contribution; 1 means the GP puts in no capital. -
pref:rate_annualandcompounding(compoundorsimple). -
distribution_order:pref_then_capital(default) orcapital_then_pref. -
catch_up:gp_shareof each catch-up dollar and thetarget_promoteshare of profit. -
tiers: up to tenuntil_irrhurdles in increasing order, each with itspromote. -
residual_promote: the GP's promote on everything after the last tier.
Limits
- One deal, one LP class and one GP. Multiple investor classes, side letters and separate capital accounts are not modeled.
- The GP's co-investment shares pref, capital and splits with the LP on equal terms. There is no separate GP pref.
- There are no clawbacks, lookbacks, asset management or acquisition fees, or tax distributions.
- Periods are equal and all flows are at period end. There are no day-count or mid-period dates.
- Each period takes one net cash flow, so a capital call and a distribution in the same period are netted before they are entered.
- An IRR is reported as null when it does not exist, and a GP with no capital has no IRR or multiple. The input is limited to 600 periods.
- Capital not returned or pref unpaid by the last period is reported and warned about, not forced.
Worked example
Inputs from FactLot's shared test case "annual: compounding 8% pref, full catch-up to 20%, 80/20 to a 12% LP IRR, 70/30 to 15%, 60/40 after", which the TypeScript and Python libraries must both reproduce:
{
"cash_flows": [
-1000000,
50000,
60000,
70000,
1800000
],
"lp_share": 0.9,
"pref": {
"rate_annual": 0.08
},
"catch_up": {
"gp_share": 1,
"target_promote": 0.2
},
"tiers": [
{
"until_irr": 0.12,
"promote": 0.2
},
{
"until_irr": 0.15,
"promote": 0.3
}
],
"residual_promote": 0.4
}
Result
| Result | Value |
|---|---|
project_irr | 0.197399 |
unreturned_capital | 0 |
unpaid_pref | 0 |
Audit trail
Every intermediate value, in order, with the formula that produced it. Formula calc.equity_waterfall@1.
| Step | Value | Formula |
|---|---|---|
| Investors | LP 90% / GP 10% of every contribution; capital, pref, and the non-promote part of every split go pro rata to capital | |
| Pref | 8% compounding: unpaid pref and capital accrue 0.08 a period ((1 + rate)^(1/1) − 1) | accrues from the period after each contribution, on balances after the previous period's flows |
| Order of distributions | accrued pref → return of capital → catch-up (100% to GP until the promote is 20% of profit) → 80%/20% until the LP IRR is 12% → 70%/30% until the LP IRR is 15% → 60%/40% thereafter | |
| IRR hurdles | each tier tracks an LP balance that grows at the hurdle's effective periodic rate ((1 + hurdle)^(1/periods_per_year) − 1), rises with LP contributions and falls with every LP distribution; the tier ends when the balance reaches zero, which is when the LP IRR (calc_irr annualization) reaches the hurdle | |
| Rounding | every period's LP distribution is rounded to the cent and the GP receives the rest of the cash flow; tier columns are rounded and the last tier paid in the period takes the rest, so each row foots; totals are row sums | |
| LP | $900,000.00 in, $1,569,383.90 out | IRR 15.882%, multiple 1.7438x |
| GP | $100,000.00 in, $410,616.10 out, of which $236,240.11 promote | IRR 44.008%, multiple 4.1062x |
| Project IRR | 0.197399 | IRR of cash_flows before the waterfall |
Warnings
- Waterfall conventions to confirm against the operating agreement: hurdles are measured on the LP's cash flows with end-of-period timing and effective periodic compounding; the GP's co-investment shares pref, capital and splits pari passu with the LP; the catch-up target is a share of all profit (pref included); distributions are not clawed back.
Use it from an agent or your code
- MCP: tool
calc_equity_waterfallonhttps://api.factlot.com/mcp(connect a client). - Python:
factlot.run_tool("calc_equity_waterfall", input)runs the same calculation offline (Python SDK). - Input schema: every field is described in tools.json.
curl -s https://api.factlot.com/v1/calc/equity_waterfall \
-H 'content-type: application/json' \
-d '{"cash_flows":[-1000000,50000,60000,70000,1800000],"lp_share":0.9,"pref":{"rate_annual":0.08},"catch_up":{"gp_share":1,"target_promote":0.2},"tiers":[{"until_irr":0.12,"promote":0.2},{"until_irr":0.15,"promote":0.3}],"residual_promote":0.4}'