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.

  1. Pref. It accrues from the period after each contribution, on balances after the previous period's flows. With compounding compound, unreturned capital plus unpaid pref earns (1 + rate_annual)^(1 ÷ periods_per_year) − 1 each period, so a fully paid pref equals an IRR of the pref rate. With simple, each period accrues unreturned capital × rate_annual ÷ periods_per_year, and unpaid pref earns nothing.
  2. Return of capital. By default accrued pref is paid first and then capital. distribution_order capital_then_pref reverses that.
  3. Catch-up. gp_share of each dollar goes to the GP as promote, and the rest goes to investors pro rata. This continues until the GP's cumulative promote equals target_promote of all profit distributed so far. Profit means everything other than return of capital, including pref paid to both LP and GP.
  4. 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 its promote until that balance reaches zero, which is the point where the LP's IRR reaches the hurdle.
  5. Residual. Everything after the last tier is split with residual_promote to 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_annual and compounding (compound or simple).
  • distribution_order: pref_then_capital (default) or capital_then_pref.
  • catch_up: gp_share of each catch-up dollar and the target_promote share of profit.
  • tiers: up to ten until_irr hurdles in increasing order, each with its promote.
  • 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 values
ResultValue
project_irr0.197399
unreturned_capital0
unpaid_pref0

Audit trail

Every intermediate value, in order, with the formula that produced it. Formula calc.equity_waterfall@1.

Audit trail
StepValueFormula
InvestorsLP 90% / GP 10% of every contribution; capital, pref, and the non-promote part of every split go pro rata to capital
Pref8% 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 distributionsaccrued 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 hurdleseach 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
Roundingevery 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 outIRR 15.882%, multiple 1.7438x
GP$100,000.00 in, $410,616.10 out, of which $236,240.11 promoteIRR 44.008%, multiple 4.1062x
Project IRR0.197399IRR 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_waterfall on https://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}'