fundedness 0.2.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. fundedness/__init__.py +71 -0
  2. fundedness/allocation/__init__.py +20 -0
  3. fundedness/allocation/base.py +32 -0
  4. fundedness/allocation/constant.py +25 -0
  5. fundedness/allocation/glidepath.py +111 -0
  6. fundedness/allocation/merton_optimal.py +220 -0
  7. fundedness/cefr.py +241 -0
  8. fundedness/liabilities.py +221 -0
  9. fundedness/liquidity.py +49 -0
  10. fundedness/merton.py +289 -0
  11. fundedness/models/__init__.py +35 -0
  12. fundedness/models/assets.py +148 -0
  13. fundedness/models/household.py +153 -0
  14. fundedness/models/liabilities.py +99 -0
  15. fundedness/models/market.py +199 -0
  16. fundedness/models/simulation.py +80 -0
  17. fundedness/models/tax.py +125 -0
  18. fundedness/models/utility.py +154 -0
  19. fundedness/optimize.py +473 -0
  20. fundedness/policies.py +204 -0
  21. fundedness/risk.py +72 -0
  22. fundedness/simulate.py +595 -0
  23. fundedness/viz/__init__.py +33 -0
  24. fundedness/viz/colors.py +110 -0
  25. fundedness/viz/comparison.py +294 -0
  26. fundedness/viz/fan_chart.py +193 -0
  27. fundedness/viz/histogram.py +225 -0
  28. fundedness/viz/optimal.py +542 -0
  29. fundedness/viz/survival.py +230 -0
  30. fundedness/viz/tornado.py +236 -0
  31. fundedness/viz/waterfall.py +203 -0
  32. fundedness/withdrawals/__init__.py +27 -0
  33. fundedness/withdrawals/base.py +116 -0
  34. fundedness/withdrawals/comparison.py +230 -0
  35. fundedness/withdrawals/fixed_swr.py +174 -0
  36. fundedness/withdrawals/guardrails.py +136 -0
  37. fundedness/withdrawals/merton_optimal.py +286 -0
  38. fundedness/withdrawals/rmd_style.py +203 -0
  39. fundedness/withdrawals/vpw.py +136 -0
  40. fundedness-0.2.4.dist-info/METADATA +300 -0
  41. fundedness-0.2.4.dist-info/RECORD +43 -0
  42. fundedness-0.2.4.dist-info/WHEEL +4 -0
  43. fundedness-0.2.4.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,300 @@
1
+ Metadata-Version: 2.4
2
+ Name: fundedness
3
+ Version: 0.2.4
4
+ Summary: A Python financial planning toolkit with CEFR calculations, Monte Carlo simulations, and beautiful visualizations
5
+ Project-URL: Homepage, https://github.com/engineerinvestor/financial-health-calculator
6
+ Project-URL: Documentation, https://engineerinvestor.github.io/financial-health-calculator/
7
+ Project-URL: Repository, https://github.com/engineerinvestor/financial-health-calculator
8
+ Author-email: Engineer Investor <egr.investor@gmail.com>
9
+ License-Expression: MIT
10
+ Keywords: CEFR,Monte Carlo,finance,planning,retirement,withdrawal
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: End Users/Desktop
13
+ Classifier: Intended Audience :: Financial and Insurance Industry
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Office/Business :: Financial :: Investment
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: numpy>=1.24.0
22
+ Requires-Dist: pandas>=2.0.0
23
+ Requires-Dist: plotly>=5.18.0
24
+ Requires-Dist: pydantic>=2.0.0
25
+ Requires-Dist: scipy>=1.11.0
26
+ Provides-Extra: all
27
+ Requires-Dist: fastapi>=0.108.0; extra == 'all'
28
+ Requires-Dist: hypothesis>=6.92.0; extra == 'all'
29
+ Requires-Dist: mkdocs-material>=9.5.0; extra == 'all'
30
+ Requires-Dist: mkdocs>=1.5.0; extra == 'all'
31
+ Requires-Dist: mkdocstrings[python]>=0.24.0; extra == 'all'
32
+ Requires-Dist: mypy>=1.8.0; extra == 'all'
33
+ Requires-Dist: pytest-cov>=4.1.0; extra == 'all'
34
+ Requires-Dist: pytest>=7.4.0; extra == 'all'
35
+ Requires-Dist: ruff>=0.1.9; extra == 'all'
36
+ Requires-Dist: streamlit>=1.29.0; extra == 'all'
37
+ Requires-Dist: uvicorn[standard]>=0.25.0; extra == 'all'
38
+ Provides-Extra: api
39
+ Requires-Dist: fastapi>=0.108.0; extra == 'api'
40
+ Requires-Dist: uvicorn[standard]>=0.25.0; extra == 'api'
41
+ Provides-Extra: dev
42
+ Requires-Dist: hypothesis>=6.92.0; extra == 'dev'
43
+ Requires-Dist: mypy>=1.8.0; extra == 'dev'
44
+ Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
45
+ Requires-Dist: pytest>=7.4.0; extra == 'dev'
46
+ Requires-Dist: ruff>=0.1.9; extra == 'dev'
47
+ Provides-Extra: docs
48
+ Requires-Dist: mkdocs-material>=9.5.0; extra == 'docs'
49
+ Requires-Dist: mkdocs>=1.5.0; extra == 'docs'
50
+ Requires-Dist: mkdocstrings[python]>=0.24.0; extra == 'docs'
51
+ Provides-Extra: streamlit
52
+ Requires-Dist: streamlit>=1.29.0; extra == 'streamlit'
53
+ Description-Content-Type: text/markdown
54
+
55
+ # Financial Health Calculator
56
+
57
+ [![PyPI version](https://img.shields.io/pypi/v/fundedness.svg)](https://pypi.org/project/fundedness/)
58
+ [![Python versions](https://img.shields.io/pypi/pyversions/fundedness.svg)](https://pypi.org/project/fundedness/)
59
+ [![Documentation](https://img.shields.io/badge/docs-mkdocs-blue.svg)](https://engineerinvestor.github.io/financial-health-calculator/)
60
+ [![Streamlit App](https://static.streamlit.io/badges/streamlit_badge_black_white.svg)](https://financial-health-calculator.streamlit.app/)
61
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
62
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/engineerinvestor/financial-health-calculator/blob/main/examples/01_cefr_basics.ipynb)
63
+
64
+ A comprehensive Python financial planning toolkit with CEFR calculations, Monte Carlo simulations, and beautiful Plotly visualizations.
65
+
66
+ ## Features
67
+
68
+ - **CEFR (Certainty-Equivalent Funded Ratio)**: A fundedness metric that accounts for taxes, liquidity, and concentration risk
69
+ - **Monte Carlo Simulations**: Project retirement outcomes with configurable market assumptions
70
+ - **Withdrawal Strategy Lab**: Compare strategies including fixed SWR, guardrails, VPW, RMD-style, and Merton optimal
71
+ - **Utility Optimization**: Merton optimal spending and allocation based on lifetime utility maximization
72
+ - **Beautiful Visualizations**: Interactive Plotly charts with fan charts, waterfalls, and survival curves
73
+ - **REST API**: FastAPI backend for programmatic access
74
+ - **Streamlit App**: User-friendly web interface
75
+
76
+ ## Quick Start
77
+
78
+ ### Installation
79
+
80
+ ```bash
81
+ pip install fundedness
82
+ ```
83
+
84
+ For development with all extras:
85
+ ```bash
86
+ pip install "fundedness[all]"
87
+ ```
88
+
89
+ ### Basic Usage
90
+
91
+ ```python
92
+ from fundedness import Asset, BalanceSheet, Liability, compute_cefr
93
+ from fundedness.models.assets import AccountType, LiquidityClass, ConcentrationLevel
94
+
95
+ # Define your assets
96
+ assets = [
97
+ Asset(
98
+ name="401(k)",
99
+ value=500_000,
100
+ account_type=AccountType.TAX_DEFERRED,
101
+ liquidity_class=LiquidityClass.RETIREMENT,
102
+ concentration_level=ConcentrationLevel.DIVERSIFIED,
103
+ ),
104
+ Asset(
105
+ name="Roth IRA",
106
+ value=200_000,
107
+ account_type=AccountType.TAX_EXEMPT,
108
+ liquidity_class=LiquidityClass.RETIREMENT,
109
+ concentration_level=ConcentrationLevel.DIVERSIFIED,
110
+ ),
111
+ ]
112
+
113
+ # Define your spending
114
+ liabilities = [
115
+ Liability(name="Living Expenses", annual_amount=50_000, is_essential=True),
116
+ Liability(name="Travel", annual_amount=20_000, is_essential=False),
117
+ ]
118
+
119
+ # Calculate CEFR
120
+ result = compute_cefr(
121
+ balance_sheet=BalanceSheet(assets=assets),
122
+ liabilities=liabilities,
123
+ planning_horizon=30,
124
+ )
125
+
126
+ print(f"CEFR: {result.cefr:.2f}")
127
+ print(f"Funded: {result.is_funded}")
128
+ print(result.get_interpretation())
129
+ ```
130
+
131
+ ## Tutorials
132
+
133
+ - [CEFR Basics](https://colab.research.google.com/github/engineerinvestor/financial-health-calculator/blob/main/examples/01_cefr_basics.ipynb) - Introduction to the CEFR metric
134
+ - [Time Distribution Analysis](https://colab.research.google.com/github/engineerinvestor/financial-health-calculator/blob/main/examples/02_time_distribution.ipynb) - Monte Carlo simulations
135
+ - [Withdrawal Strategy Comparison](https://colab.research.google.com/github/engineerinvestor/financial-health-calculator/blob/main/examples/03_withdrawal_comparison.ipynb) - Compare different approaches
136
+
137
+ ## Running the Apps
138
+
139
+ ### Streamlit Web App
140
+
141
+ ```bash
142
+ streamlit run streamlit_app/app.py
143
+ ```
144
+
145
+ ### FastAPI REST API
146
+
147
+ ```bash
148
+ uvicorn api.main:app --reload
149
+ ```
150
+
151
+ API documentation available at `http://localhost:8000/docs`
152
+
153
+ ## Key Concepts
154
+
155
+ ### CEFR (Certainty-Equivalent Funded Ratio)
156
+
157
+ CEFR measures how well-funded your retirement is after accounting for:
158
+
159
+ - **Tax Haircuts**: What you'll owe when withdrawing from different account types
160
+ - **Liquidity Haircuts**: How easily you can access your assets
161
+ - **Reliability Haircuts**: Risk from concentrated positions
162
+
163
+ **Formula:**
164
+ ```
165
+ CEFR = Σ(Asset × (1-τ) × λ × ρ) / PV(Liabilities)
166
+ ```
167
+
168
+ Where τ = tax rate, λ = liquidity factor, ρ = reliability factor
169
+
170
+ **Interpretation:**
171
+ - CEFR ≥ 2.0: Excellent - Very well-funded
172
+ - CEFR 1.5-2.0: Strong - Well-funded with margin
173
+ - CEFR 1.0-1.5: Adequate - Fully funded
174
+ - CEFR < 1.0: Underfunded - Action needed
175
+
176
+ ### Withdrawal Strategies
177
+
178
+ | Strategy | Description | Best For |
179
+ |----------|-------------|----------|
180
+ | Fixed SWR | 4% of initial portfolio, adjusted for inflation | Predictability |
181
+ | % of Portfolio | Fixed % of current value | Market adaptation |
182
+ | Guardrails | Adjustable with floor/ceiling | Balance |
183
+ | VPW | Age-based variable percentage | Maximizing spending |
184
+ | RMD-Style | IRS distribution table based | Tax efficiency |
185
+ | Merton Optimal | Utility-maximizing spending rate | Optimality |
186
+
187
+ ### Utility Optimization
188
+
189
+ The toolkit includes Merton's optimal consumption and portfolio choice framework, as applied in modern retirement planning research<sup>[1]</sup>:
190
+
191
+ - **Optimal Equity Allocation**: `k* = (μ - r) / (γ × σ²)`
192
+ - **Wealth-Adjusted Allocation**: Reduces equity as wealth approaches subsistence floor
193
+ - **Optimal Spending Rate**: Increases with age as horizon shortens
194
+ - **Expected Lifetime Utility**: Track utility across Monte Carlo paths
195
+
196
+ Key insights from this methodology:
197
+ 1. Optimal spending starts low (~2-3%) and rises with age
198
+ 2. Allocation should decrease as wealth approaches the floor
199
+ 3. Risk aversion (gamma) is the critical input parameter
200
+ 4. The 4% rule is suboptimal from a utility perspective
201
+
202
+ ## Development
203
+
204
+ ### Setup
205
+
206
+ ```bash
207
+ git clone https://github.com/engineerinvestor/financial-health-calculator.git
208
+ cd financial-health-calculator
209
+ pip install -e ".[dev]"
210
+ ```
211
+
212
+ ### Running Tests
213
+
214
+ ```bash
215
+ pytest
216
+ ```
217
+
218
+ ### Code Quality
219
+
220
+ ```bash
221
+ ruff check .
222
+ mypy fundedness
223
+ ```
224
+
225
+ ## Project Structure
226
+
227
+ ```
228
+ financial-health-calculator/
229
+ ├── fundedness/ # Core Python package
230
+ │ ├── models/ # Pydantic data models
231
+ │ ├── viz/ # Plotly visualizations
232
+ │ ├── withdrawals/ # Withdrawal strategies (SWR, guardrails, VPW, Merton)
233
+ │ ├── allocation/ # Asset allocation strategies (constant, glidepath, Merton)
234
+ │ ├── cefr.py # CEFR calculation
235
+ │ ├── simulate.py # Monte Carlo engine with utility tracking
236
+ │ ├── merton.py # Merton optimal formulas
237
+ │ ├── optimize.py # Policy parameter optimization
238
+ │ └── policies.py # Spending/allocation policies
239
+ ├── api/ # FastAPI REST API
240
+ ├── streamlit_app/ # Streamlit web application
241
+ │ └── pages/ # Includes Utility Optimization page
242
+ ├── examples/ # Jupyter notebooks
243
+ └── tests/ # pytest tests
244
+ ```
245
+
246
+ ## Contact
247
+
248
+ - Twitter: [@egr_investor](https://x.com/egr_investor)
249
+ - GitHub: [engineerinvestor](https://github.com/engineerinvestor)
250
+ - Email: egr.investor@gmail.com
251
+
252
+ ## License
253
+
254
+ MIT License
255
+
256
+ ## References
257
+
258
+ 1. Haghani, V., & White, J. (2023). *The Missing Billionaires: A Guide to Better Financial Decisions*. Wiley. See also [Elm Wealth](https://elmwealth.com/) for related research on optimal spending and allocation.
259
+
260
+ 2. Merton, R. C. (1969). Lifetime Portfolio Selection under Uncertainty: The Continuous-Time Case. *The Review of Economics and Statistics*, 51(3), 247-257.
261
+
262
+ ## Citation
263
+
264
+ If you use this package in academic work, please cite:
265
+
266
+ ```bibtex
267
+ @software{fundedness,
268
+ title = {Fundedness: A Python Financial Planning Toolkit},
269
+ author = {Engineer Investor},
270
+ year = {2024},
271
+ url = {https://github.com/engineerinvestor/financial-health-calculator},
272
+ version = {0.2.1}
273
+ }
274
+ ```
275
+
276
+ For the underlying methodology, please also cite:
277
+
278
+ ```bibtex
279
+ @article{merton1969lifetime,
280
+ title = {Lifetime Portfolio Selection under Uncertainty: The Continuous-Time Case},
281
+ author = {Merton, Robert C.},
282
+ journal = {The Review of Economics and Statistics},
283
+ volume = {51},
284
+ number = {3},
285
+ pages = {247--257},
286
+ year = {1969},
287
+ publisher = {MIT Press}
288
+ }
289
+
290
+ @book{haghani2023missing,
291
+ title = {The Missing Billionaires: A Guide to Better Financial Decisions},
292
+ author = {Haghani, Victor and White, James},
293
+ year = {2023},
294
+ publisher = {Wiley}
295
+ }
296
+ ```
297
+
298
+ ## Disclaimer
299
+
300
+ This tool is for educational purposes only and does not constitute financial advice. Consult a qualified financial advisor for personalized recommendations.
@@ -0,0 +1,43 @@
1
+ fundedness/__init__.py,sha256=5rATL7-dfOIzb43-c3oDYImGu70ezYv2ALfbadhyR20,1678
2
+ fundedness/cefr.py,sha256=hCImRrjz-DCPJsuF3HShDZK5tw1vslakh-DrNBHsh2k,7728
3
+ fundedness/liabilities.py,sha256=uKvEV6JQnQdrd7b6VsCc2qf9S2DJdK0XhEX9qwca2Ws,6662
4
+ fundedness/liquidity.py,sha256=ncZF70AfgoVoYZnozpA_CHemfaHmI4KKCe3vITp5ljM,1713
5
+ fundedness/merton.py,sha256=VUKVxkNimoI0gsQJROb1wrO-SW4ubiNvcYDL2aH69AU,9218
6
+ fundedness/optimize.py,sha256=21ksSkNgtDY_UGTub0KRlIvfaFA363csfSfHnLJrmJs,15567
7
+ fundedness/policies.py,sha256=pyIYz86Z3sMYAW2rNhPLnXQ3PQCDCa-oxf9NhWyawy8,5854
8
+ fundedness/risk.py,sha256=Lpls6Q2wVq5SX4p9ZQwCtTM73AcqrGCm3hE2QcgKuq0,2750
9
+ fundedness/simulate.py,sha256=1undHqkhVGWHK_pXS5KvqlRCpUmBEXQZ7-ujvrEsJkI,21448
10
+ fundedness/allocation/__init__.py,sha256=5p85uRFltSfEwXjengr56FNY1s4KvcMMxuH05I_Omfs,677
11
+ fundedness/allocation/base.py,sha256=kDypu2t86fsn2DyL5an1fPjbPbQWNmqydz3axWUgjLI,763
12
+ fundedness/allocation/constant.py,sha256=6QcUJ0aBQcJcRJtOMhs7uUu13wJtgcPU7ToQzQZhcgw,531
13
+ fundedness/allocation/glidepath.py,sha256=-q6Jb5WpRuZjJ68akT5WgeRIx3QSIDtlNih0_Iz-_cc,3440
14
+ fundedness/allocation/merton_optimal.py,sha256=krRd7sKbvXXxfewLJuF9RWbMLYUHbehvdbdYSjwnczk,7702
15
+ fundedness/models/__init__.py,sha256=EyW6tGUI9T6QMbIfzsG3igqg5--DtZHSTAuMX6foOiA,874
16
+ fundedness/models/assets.py,sha256=ZKgxl4YaqdRVfDErL9weRhh4St_azo8ruN4g15T3IsQ,5013
17
+ fundedness/models/household.py,sha256=t64FjvO0uQJemddLtCPpK3NNYdZCXU6KjA1VZshaqEk,4671
18
+ fundedness/models/liabilities.py,sha256=iqGl5RU841k1clGOwnFParUvxzCJclq2JzNJoNPywuo,3416
19
+ fundedness/models/market.py,sha256=JAUt-MM__yM_v-FsgKwJj7rXC0yh6oFUv5JLoob58OE,6388
20
+ fundedness/models/simulation.py,sha256=0jtIJWISDL-TlKVjr6KxcRfAj5Mrbp-VNyA4Bu7IUfU,2224
21
+ fundedness/models/tax.py,sha256=0XhoBNZqfRqF1_acakrkYgMS5L6Pknq-TloQQBrFw1U,3859
22
+ fundedness/models/utility.py,sha256=0AoJdccTb2hKBrTz5LExm8SrSsaWhhBf7y2NNaUzWQ0,4678
23
+ fundedness/viz/__init__.py,sha256=Om8qlI13w13MfDmyB_xeR6hgr7LpWX1tjAf_x3eDbEQ,1168
24
+ fundedness/viz/colors.py,sha256=kbYyCLvLARoIAMztHjnJZDxMGF9-an5z4obORa6JFEU,3204
25
+ fundedness/viz/comparison.py,sha256=DoQW6xr0r2ko55qyli4ue8ndj__opun97brbbHSnKVA,8530
26
+ fundedness/viz/fan_chart.py,sha256=GqdrOKdW12K7Y8sFQJ853QbYG3ASxvEzfY9cC-EKK70,6102
27
+ fundedness/viz/histogram.py,sha256=i56g330-S84WxUU8GGya40yNUQbnAI2D0vzUbFy51DI,6784
28
+ fundedness/viz/optimal.py,sha256=w5vI2O-4O6F1Dobsfg55pznlfD100SRnSgZqLIpcT9c,16056
29
+ fundedness/viz/survival.py,sha256=xtaAHkJ3jlTUCYnLrTvwWlOlfLao6NC5cRxT5XKWrxM,6515
30
+ fundedness/viz/tornado.py,sha256=1dZzAfKTDCcyyfbDUBE39f44e6k48yviF8kTRee-pwQ,6684
31
+ fundedness/viz/waterfall.py,sha256=6LD0SbZDUzJrA0Zh1Y1qDx0I4BM5ZN_f2eVCXNK5HRc,5586
32
+ fundedness/withdrawals/__init__.py,sha256=FiXfK7QBzUp4Iwf25VK0jbZyguF8bLlZAWWMjg8tFPo,886
33
+ fundedness/withdrawals/base.py,sha256=WXBuo-tJtp4V2Ottp2PC2YtyK3mGVJ9Cgq21zGUWObg,3472
34
+ fundedness/withdrawals/comparison.py,sha256=eiobGMHmeQpGnr0_HcY_EKrv5_Nu7EaVf5Y9DdDNAyg,7833
35
+ fundedness/withdrawals/fixed_swr.py,sha256=2ZgkQ_xZakpcdZQIop46TAFML7ESz7nyTVdVfI-1Z18,5469
36
+ fundedness/withdrawals/guardrails.py,sha256=rZKVojKbl9LLJLi9LlK1I2JXb537MN_AbZfn4hIU8is,5468
37
+ fundedness/withdrawals/merton_optimal.py,sha256=mSxRAKGx8sr_YdlhQMtIvnojqfuG0MiYtBp18xboLHs,9269
38
+ fundedness/withdrawals/rmd_style.py,sha256=E5FfrUYxFJwULKxzxbtZFLoLspLzUUomTQRUWLGLDpg,6373
39
+ fundedness/withdrawals/vpw.py,sha256=aajHLAkHfsxh33uGRgzv0ozVuZREG-EmARJgWOU6mis,4389
40
+ fundedness-0.2.4.dist-info/METADATA,sha256=fEFxniSnE2ymvEo4rIS_q5im2NWZoNQmtd8Bic2vxqA,11017
41
+ fundedness-0.2.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
42
+ fundedness-0.2.4.dist-info/entry_points.txt,sha256=Oh-Hg08i044YHuSHViCdfoD8CenIGcKrVuUVysvN9sY,51
43
+ fundedness-0.2.4.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ fundedness = fundedness.cli:main