A Python library for modeling startup liquidation preferences. Know your payout before the lawyers do.
When a startup gets acquired or liquidated, who gets paid what is not as simple as "divide by shares." Investors negotiate liquidation preferences — contractual rights that determine payout order and amounts before common shareholders see a dime.
This library models the full complexity: stacked preferences across funding rounds, participating vs. non-participating preferred shares, participation caps, options & warrants with exercise prices, and Nash equilibrium conversion decisions where each share class strategically decides whether to convert to common.
Feed it a CSV cap table, give it exit values, get back the exact distribution. Use it as a library, or run it from the CLI. No spreadsheet gymnastics required.
Liquidation preferences are paid in priority order — highest stack order first. Series E before Series D before Series C. If there isn't enough, pro-rate within the priority group.
After preferences are satisfied, remaining proceeds go to participating preferred (who double-dip) and common shareholders on a pro-rata basis.
Participating preferred with caps (e.g., 2x) get cut off when their total payout hits the cap. Excess is redistributed to uncapped participants.
Non-participating preferred must choose: take the preference, or convert to common for a larger pro-rata share. The Nash equilibrium algorithm finds the optimal strategy considering all classes simultaneously.
# Analyze a cap table at multiple exit values python cli.py captable.csv --exit-values 15M 25M 50M 100M # Detailed step-by-step breakdown python cli.py captable.csv --exit-values 50M --detailed # Compare conversion algorithms python cli.py captable.csv --conversion-algorithm nash python cli.py captable.csv --conversion-algorithm heuristic
# Load a cap table from CSV and analyze from liquidation_waterfall import ( parse_cap_table_csv, format_waterfall_analysis ) calculator = parse_cap_table_csv("captable.csv") exit_values = [15_000_000, 25_000_000, 50_000_000, 100_000_000] print(format_waterfall_analysis(calculator, exit_values))
# Or construct programmatically from liquidation_waterfall import ( WaterfallCalculator, ShareClass, PreferenceType ) calc = WaterfallCalculator() common = ShareClass("Common", 1_000_000, 0, PreferenceType.COMMON) series_a = ShareClass( "Series A", 200_000, 900_000, PreferenceType.PARTICIPATING, 1.0, 2.0, 1 ) calc.add_share_class(common) calc.add_share_class(series_a) distribution = calc.calculate_distribution(5_000_000) print(distribution)