Browse the docs
Example 9 of 13
Tax equity partnership flip
Based on Tax Equity Model 19-11-23_2.xlsx
A US renewable project financed by a tax equity investor. The investor takes most of the cash, income and tax credits until it earns its target yield, then the shares flip to the sponsor. The workbook also works through capital accounts, back leverage, a leveraged lease and an inverted lease. Design example: written in the full v0.5 language. The compiler builds the working core today, so this one doesn't compile yet. Source: examples/design/taxequity/.
- Library
- F. Tax Equity Structures / Tax Equity Course (63 files in the folder)
- Timeline
- 13 months construction, 30 years operations; partnership monthly, tax equity quarterly, tax yearly
- Project
- Capex 1,700 and EBITDA 90 a year (workbook units), 0.5% degradation, monthly seasonality
- Tax
- 21% federal, no state tax (Texas), 5-year MACRS, 26% ITC with half of it off the depreciable base
- Flip
- Investor funds 60%, takes 95% of cash and income until it earns 5%, then 15%; flip in year 9
- Rebuild shown
- 6 files, 106 lines
Where each sheet goes
| Workbook sheets | Rufineer |
|---|---|
| Inputs | inputs.rfn and the Seasonality sheet of the data workbook |
| Partnership-M, Partnership-A | partnership.rfn (monthly operations on its own ruler) |
| Tax Equity-Q, Yield Based Flip Example | flip.rfn: one split … among, one event |
| Minimum Gain Illustration, 704(b) accounts | capital_account in flip.rfn |
| Back Leverage, Project L Debt | sponsor.rfn |
| Leveraged Lease, Inverted Lease | alternatives.rfn, switched by when |
| MACRS | the macrs_5 method in the standard library |
Source 6 files shown, 106 lines
model "Tax Equity Partnership Flip" {
currency USD
unit kUSD = 1_000 USD
display thousands
data "tax_equity_inputs.xlsx"
}
timeline {
start 2024-01-01
construction 13m
operations 30y
ruler monthly month // partnership operations
ruler quarterly quarter // distributions and capital accounts
ruler annual year ends Dec // tax returns
}inputs "Project" {
capex = 1_700 kUSD // before IDC and fees
ebitda = 90 kUSD/y
degradation = 0.5 %/y
spend_curve = option normal | weibull // S-curve: normal(6.5, 3) or weibull(4, 3)
}
table seasonality: % // Month | Share of the year
inputs "Tax" {
federal_rate = 21 %
state_rate = 0 % // Texas
itc_rate = 26 %
itc_boriole_cut = 50 % // half the ITC comes off the depreciable base
}
inputs "Partnership" {
investor_capital = 60 %
flip_yield = 5 %/y
pre_flip = 95 %
post_flip = 15 %
dro = 0 kUSD // deficit restoration obligation
structure = option partnership_flip | sale_leaseback | inverted_lease
}
/// Amounts live on the Back leverage sheet of the data workbook
inputs "Back leverage" sheet "Back leverage" {
back_leverage_amount: kUSD "Amount"
back_leverage_rate: %/y "Rate"
back_leverage_tenor: y "Tenor"
back_leverage_dscr: x "DSCR"
}module ops "Partnership operations" on monthly {
spend: kUSD = spread(inputs.capex, over: construction,
profile: match inputs.spend_curve { normal => normal(6.5, 3),
weibull => weibull(4, 3) })
// 90 a year, shaped by month and degrading 0.5% a year
ebitda: kUSD = inputs.ebitda * seasonal(inputs.seasonality)
* decline(inputs.degradation) | during operations
}
module tax "Tax" on quarterly {
itc: kUSD = inputs.itc_rate * sum(ops.spend) | at operations.start
basis: kUSD = sum(ops.spend) - inputs.itc_boriole_cut * sum(itc)
depreciation: kUSD = depreciation(additions: basis | at operations.start,
method: macrs_5).charge // 20%, 32%, 19.2% …
taxable_income: kUSD = ops.ebitda - depreciation
rate = inputs.federal_rate + inputs.state_rate
}module flip "Partnership flip" on quarterly {
/// Cash, income and credits are split the same way; the sponsor takes the rest
split partnership among tax_investor, sponsor {
capital = ops.spend tax_investor inputs.investor_capital
cash = ops.ebitda tax_investor inputs.pre_flip until flip, then inputs.post_flip
income = tax.taxable_income tax_investor inputs.pre_flip until flip, then inputs.post_flip
credits = tax.itc tax_investor inputs.pre_flip until flip, then inputs.post_flip
}
investor_after_tax: kUSD = partnership.tax_investor.cash - partnership.tax_investor.capital
- partnership.tax_investor.income * tax.rate
+ partnership.tax_investor.credits
/// Flips the quarter after the investor has earned 5% after tax
event flip = first(earned(investor_after_tax, inputs.flip_yield))
sponsor_after_tax: kUSD = partnership.sponsor.cash - partnership.sponsor.capital
- partnership.sponsor.income * tax.rate + partnership.sponsor.credits
investor_irr = xirr(investor_after_tax) // 7.5% in the workbook
sponsor_irr = xirr(sponsor_after_tax) // 6.1%
investor_account = capital_account(partnership.tax_investor,
dro: inputs.dro, itc_basis: inputs.itc_boriole_cut)
}module sponsor "Sponsor and back leverage" on quarterly {
/// The sponsor borrows against its share of partnership cash
back_leverage = sculpted_loan(
draws: inputs.back_leverage_amount | at operations.start,
rate: inputs.back_leverage_rate,
window: operations.start for inputs.back_leverage_tenor,
cfads: flip.partnership.sponsor.cash,
dscr: inputs.back_leverage_dscr
)
levered_cash: kUSD = flip.sponsor_after_tax - back_leverage.debt_service
+ back_leverage.draws
levered_irr = xirr(levered_cash)
}/// The same project financed three ways, chosen on the Inputs sheet
when inputs.structure == sale_leaseback {
lessor = lease(cost: sum(ops.spend), term: 20y, residual: 20 %, yield: 7 %/y,
tax_benefits: tax.itc + tax.depreciation * tax.rate)
sponsor_cash: kUSD = ops.ebitda - lessor.rent
}
when inputs.structure == inverted_lease {
/// The investor leases the plant, pays rent, keeps the revenue and the ITC
investor_lease = lease(cost: sum(ops.spend), term: 20y, residual: 0 %, yield: 6 %/y,
lessee_takes: [ops.ebitda, tax.itc])
}
results "Structures compared" {
across inputs.structure = [partnership_flip, sale_leaseback, inverted_lease]
show flip.sponsor_irr, flip.investor_irr, sponsor.levered_irr
}What this model needed from the language
- Splitting more than cash. Tax equity splits taxable income and credits as well as cash, with different shares before and after the flip.
split … amongtakes one row per line. - A flip on a return.
event flip = first(earned(…))keeps the investor's balance at the flip yield, as the workbook does, and switches the split the quarter after. - Three rulers. Monthly operations, quarterly partnership accounts and yearly tax returns.
- Capital accounts. 704(b) accounts with the DRO and minimum gain are a standard-library component, not 60 hand-built rows.
- Comparing structures. Flip, sale-leaseback and inverted lease sit in one model behind a switch, compared with
results.