fundedness 0.2.0__tar.gz

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 (95) hide show
  1. fundedness-0.2.0/.github/workflows/docs.yml +36 -0
  2. fundedness-0.2.0/.github/workflows/publish.yml +28 -0
  3. fundedness-0.2.0/.gitignore +106 -0
  4. fundedness-0.2.0/CLAUDE.md +98 -0
  5. fundedness-0.2.0/PKG-INFO +265 -0
  6. fundedness-0.2.0/README.md +211 -0
  7. fundedness-0.2.0/api/__init__.py +1 -0
  8. fundedness-0.2.0/api/main.py +54 -0
  9. fundedness-0.2.0/api/routes/__init__.py +1 -0
  10. fundedness-0.2.0/api/routes/cefr.py +201 -0
  11. fundedness-0.2.0/api/routes/compare.py +154 -0
  12. fundedness-0.2.0/api/routes/simulate.py +145 -0
  13. fundedness-0.2.0/background_information.md +927 -0
  14. fundedness-0.2.0/docs/api/core.md +15 -0
  15. fundedness-0.2.0/docs/api/merton.md +91 -0
  16. fundedness-0.2.0/docs/api/models.md +39 -0
  17. fundedness-0.2.0/docs/api/viz.md +23 -0
  18. fundedness-0.2.0/docs/api/withdrawals.md +29 -0
  19. fundedness-0.2.0/docs/examples/tutorials.md +112 -0
  20. fundedness-0.2.0/docs/getting-started/installation.md +81 -0
  21. fundedness-0.2.0/docs/getting-started/quickstart.md +94 -0
  22. fundedness-0.2.0/docs/guide/cefr.md +102 -0
  23. fundedness-0.2.0/docs/guide/simulations.md +120 -0
  24. fundedness-0.2.0/docs/guide/utility-optimization.md +200 -0
  25. fundedness-0.2.0/docs/guide/visualizations.md +144 -0
  26. fundedness-0.2.0/docs/guide/withdrawals.md +149 -0
  27. fundedness-0.2.0/docs/index.md +75 -0
  28. fundedness-0.2.0/examples/01_cefr_basics.ipynb +298 -0
  29. fundedness-0.2.0/examples/02_time_distribution.ipynb +341 -0
  30. fundedness-0.2.0/examples/03_withdrawal_comparison.ipynb +353 -0
  31. fundedness-0.2.0/fundedness/__init__.py +71 -0
  32. fundedness-0.2.0/fundedness/allocation/__init__.py +20 -0
  33. fundedness-0.2.0/fundedness/allocation/base.py +32 -0
  34. fundedness-0.2.0/fundedness/allocation/constant.py +25 -0
  35. fundedness-0.2.0/fundedness/allocation/glidepath.py +111 -0
  36. fundedness-0.2.0/fundedness/allocation/merton_optimal.py +220 -0
  37. fundedness-0.2.0/fundedness/cefr.py +241 -0
  38. fundedness-0.2.0/fundedness/liabilities.py +221 -0
  39. fundedness-0.2.0/fundedness/liquidity.py +49 -0
  40. fundedness-0.2.0/fundedness/merton.py +289 -0
  41. fundedness-0.2.0/fundedness/models/__init__.py +35 -0
  42. fundedness-0.2.0/fundedness/models/assets.py +148 -0
  43. fundedness-0.2.0/fundedness/models/household.py +153 -0
  44. fundedness-0.2.0/fundedness/models/liabilities.py +99 -0
  45. fundedness-0.2.0/fundedness/models/market.py +188 -0
  46. fundedness-0.2.0/fundedness/models/simulation.py +80 -0
  47. fundedness-0.2.0/fundedness/models/tax.py +125 -0
  48. fundedness-0.2.0/fundedness/models/utility.py +154 -0
  49. fundedness-0.2.0/fundedness/optimize.py +473 -0
  50. fundedness-0.2.0/fundedness/policies.py +204 -0
  51. fundedness-0.2.0/fundedness/risk.py +72 -0
  52. fundedness-0.2.0/fundedness/simulate.py +559 -0
  53. fundedness-0.2.0/fundedness/viz/__init__.py +33 -0
  54. fundedness-0.2.0/fundedness/viz/colors.py +110 -0
  55. fundedness-0.2.0/fundedness/viz/comparison.py +294 -0
  56. fundedness-0.2.0/fundedness/viz/fan_chart.py +193 -0
  57. fundedness-0.2.0/fundedness/viz/histogram.py +225 -0
  58. fundedness-0.2.0/fundedness/viz/optimal.py +542 -0
  59. fundedness-0.2.0/fundedness/viz/survival.py +230 -0
  60. fundedness-0.2.0/fundedness/viz/tornado.py +236 -0
  61. fundedness-0.2.0/fundedness/viz/waterfall.py +203 -0
  62. fundedness-0.2.0/fundedness/withdrawals/__init__.py +27 -0
  63. fundedness-0.2.0/fundedness/withdrawals/base.py +116 -0
  64. fundedness-0.2.0/fundedness/withdrawals/comparison.py +230 -0
  65. fundedness-0.2.0/fundedness/withdrawals/fixed_swr.py +174 -0
  66. fundedness-0.2.0/fundedness/withdrawals/guardrails.py +136 -0
  67. fundedness-0.2.0/fundedness/withdrawals/merton_optimal.py +286 -0
  68. fundedness-0.2.0/fundedness/withdrawals/rmd_style.py +203 -0
  69. fundedness-0.2.0/fundedness/withdrawals/vpw.py +136 -0
  70. fundedness-0.2.0/mkdocs.yml +51 -0
  71. fundedness-0.2.0/pyproject.toml +96 -0
  72. fundedness-0.2.0/requirements.txt +7 -0
  73. fundedness-0.2.0/streamlit_app/__init__.py +1 -0
  74. fundedness-0.2.0/streamlit_app/app.py +104 -0
  75. fundedness-0.2.0/streamlit_app/components/__init__.py +1 -0
  76. fundedness-0.2.0/streamlit_app/components/asset_editor.py +124 -0
  77. fundedness-0.2.0/streamlit_app/components/liability_editor.py +117 -0
  78. fundedness-0.2.0/streamlit_app/components/metrics_display.py +144 -0
  79. fundedness-0.2.0/streamlit_app/pages/0_Inputs.py +242 -0
  80. fundedness-0.2.0/streamlit_app/pages/1_CEFR_Dashboard.py +112 -0
  81. fundedness-0.2.0/streamlit_app/pages/2_Time_Runway.py +219 -0
  82. fundedness-0.2.0/streamlit_app/pages/3_Withdrawal_Lab.py +225 -0
  83. fundedness-0.2.0/streamlit_app/pages/4_Sensitivity.py +305 -0
  84. fundedness-0.2.0/streamlit_app/pages/5_Utility_Optimization.py +440 -0
  85. fundedness-0.2.0/streamlit_app/utils/__init__.py +21 -0
  86. fundedness-0.2.0/streamlit_app/utils/session_state.py +160 -0
  87. fundedness-0.2.0/tests/__init__.py +1 -0
  88. fundedness-0.2.0/tests/conftest.py +119 -0
  89. fundedness-0.2.0/tests/test_api.py +179 -0
  90. fundedness-0.2.0/tests/test_cefr.py +294 -0
  91. fundedness-0.2.0/tests/test_liabilities.py +239 -0
  92. fundedness-0.2.0/tests/test_merton.py +311 -0
  93. fundedness-0.2.0/tests/test_optimize.py +336 -0
  94. fundedness-0.2.0/tests/test_simulate.py +242 -0
  95. fundedness-0.2.0/tests/test_withdrawals.py +275 -0
@@ -0,0 +1,36 @@
1
+ name: Deploy Documentation
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+ pages: write
11
+ id-token: write
12
+
13
+ jobs:
14
+ build:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: '3.11'
21
+ - run: pip install mkdocs mkdocs-material mkdocstrings[python]
22
+ - run: pip install -e .
23
+ - run: mkdocs build
24
+ - uses: actions/upload-pages-artifact@v3
25
+ with:
26
+ path: site
27
+
28
+ deploy:
29
+ needs: build
30
+ runs-on: ubuntu-latest
31
+ environment:
32
+ name: github-pages
33
+ url: ${{ steps.deployment.outputs.page_url }}
34
+ steps:
35
+ - uses: actions/deploy-pages@v4
36
+ id: deployment
@@ -0,0 +1,28 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch: # Allow manual trigger
7
+
8
+ jobs:
9
+ publish:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - uses: actions/setup-python@v5
15
+ with:
16
+ python-version: '3.11'
17
+
18
+ - name: Install build tools
19
+ run: pip install build twine
20
+
21
+ - name: Build package
22
+ run: python -m build
23
+
24
+ - name: Publish to PyPI
25
+ env:
26
+ TWINE_USERNAME: __token__
27
+ TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
28
+ run: twine upload dist/*
@@ -0,0 +1,106 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ *.manifest
31
+ *.spec
32
+
33
+ # Installer logs
34
+ pip-log.txt
35
+ pip-delete-this-directory.txt
36
+
37
+ # Unit test / coverage reports
38
+ htmlcov/
39
+ .tox/
40
+ .nox/
41
+ .coverage
42
+ .coverage.*
43
+ .cache
44
+ nosetests.xml
45
+ coverage.xml
46
+ *.cover
47
+ *.py,cover
48
+ .hypothesis/
49
+ .pytest_cache/
50
+
51
+ # Translations
52
+ *.mo
53
+ *.pot
54
+
55
+ # Jupyter Notebook
56
+ .ipynb_checkpoints
57
+
58
+ # IPython
59
+ profile_default/
60
+ ipython_config.py
61
+
62
+ # pyenv
63
+ .python-version
64
+
65
+ # Environments
66
+ .env
67
+ .venv
68
+ env/
69
+ venv/
70
+ ENV/
71
+ env.bak/
72
+ venv.bak/
73
+
74
+ # Spyder project settings
75
+ .spyderproject
76
+ .spyproject
77
+
78
+ # Rope project settings
79
+ .ropeproject
80
+
81
+ # mkdocs documentation
82
+ /site
83
+
84
+ # mypy
85
+ .mypy_cache/
86
+ .dmypy.json
87
+ dmypy.json
88
+
89
+ # Pyre type checker
90
+ .pyre/
91
+
92
+ # IDE
93
+ .idea/
94
+ .vscode/
95
+ *.swp
96
+ *.swo
97
+ *~
98
+
99
+ # OS
100
+ .DS_Store
101
+ Thumbs.db
102
+
103
+ # Project specific
104
+ *.log
105
+ secrets.yaml
106
+ config.local.yaml
@@ -0,0 +1,98 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ This is a Python financial planning toolkit that implements:
8
+ - **CEFR (Certainty-Equivalent Funded Ratio)**: A fundedness metric that applies after-tax, liquidity, and risk haircuts to assets
9
+ - **Victor-style lifetime utility optimization**: Spending and asset allocation policies that maximize expected lifetime utility
10
+ - **Withdrawal Strategy Lab**: Comparison framework for withdrawal strategies (fixed SWR, guardrails, VPW, RMD-style)
11
+
12
+ The project includes both a Python package (`fundedness/`) and a Streamlit web application (`streamlit_app/`).
13
+
14
+ ## Development Status
15
+
16
+ This project is in the **specification/planning phase**. The `background_information.md` file contains the complete design spec. No implementation code exists yet.
17
+
18
+ ## Planned Commands
19
+
20
+ Once implemented, the project will use:
21
+ - **Package manager**: pip
22
+ - **Testing**: pytest (with property tests for monotonicity)
23
+ - **Docs**: MkDocs
24
+ - **CLI**: `fundedness cefr config.yaml`, `fundedness simulate config.yaml`, `fundedness policy-search config.yaml`
25
+ - **Streamlit**: `streamlit run streamlit_app/app.py`
26
+
27
+ ## Architecture
28
+
29
+ ### Core Package Structure (`fundedness/`)
30
+
31
+ ```
32
+ fundedness/
33
+ ├── cefr.py # CEFR ratio calculation with haircut breakdowns
34
+ ├── liabilities.py # Liability PV calculations with schedules
35
+ ├── taxes.py # Tax modeling by account type
36
+ ├── liquidity.py # Liquidity factor adjustments
37
+ ├── risk.py # Reliability/concentration haircuts
38
+ ├── markets.py # Return/covariance/inflation assumptions
39
+ ├── simulate.py # Monte Carlo engine (time-to-floor, time-to-ruin)
40
+ ├── utility.py # CRRA utility with subsistence floor
41
+ ├── policies.py # Spending/allocation policy interface
42
+ ├── optimize.py # Parametric policy search (v0.4+)
43
+ ├── withdrawals/ # Withdrawal strategy implementations
44
+ ├── allocation/ # Glidepath strategies (constant, rising equity, bucket)
45
+ └── tax/strategy.py # Tax-aware withdrawal sequencing
46
+ ```
47
+
48
+ ### Data Models (Pydantic)
49
+
50
+ Key models: `Household`, `BalanceSheet`, `Asset`, `Liability`, `MarketModel`, `TaxModel`, `UtilityModel`, `SimulationConfig`
51
+
52
+ ### Core Formulas
53
+
54
+ **CEFR Calculation:**
55
+ ```
56
+ CEFR = Σ(Asset × (1-tax_rate) × liquidity_factor × reliability_factor) / PV(Liabilities)
57
+ ```
58
+
59
+ **CRRA Utility with Floor:**
60
+ ```
61
+ u(C) = (C - F)^(1-γ) / (1-γ) where C > F (subsistence floor)
62
+ ```
63
+
64
+ ## Development Tiers
65
+
66
+ 1. **MVP (v0.1-0.3)**: CEFR + Monte Carlo runway with P10/P50/P90 bands
67
+ 2. **v0.4-0.7**: Victor-style parametric policy search
68
+ 3. **v1.0+**: Tax-aware account flows, Roth conversions
69
+
70
+ ## Key Concepts
71
+
72
+ - **Haircuts**: Three adjustments to assets—after-tax (τ), liquidity (λ), reliability (ρ)
73
+ - **Floor/Flex spending**: Essential spending floor vs adjustable discretionary
74
+ - **Time metrics**: Time-to-floor-breach, time-to-ruin, max spending drawdown
75
+ - **Confidence intervals**: Scenario percentiles (P10/P50/P90), not statistical CIs
76
+
77
+ ## Default Haircut Assumptions
78
+
79
+ Liquidity: cash=1.0, taxable_index=0.95, retirement=0.85, home_equity=0.5, private_business=0.3
80
+ Reliability: diversified_bonds=0.95, diversified_equity=0.85, single_stock=0.60, startup=0.30
81
+
82
+ ## Deployment Preferences
83
+
84
+ - **Web App**: Deploy on Streamlit Cloud (free tier)
85
+ - **API**: Expose core functionality via a REST API (FastAPI recommended) for programmatic access
86
+ - **Tutorials**: Create Jupyter notebooks in `examples/` that run in Google Colab. Include working "Open in Colab" badge links in the README using the format:
87
+ ```
88
+ [![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/NOTEBOOK.ipynb)
89
+ ```
90
+
91
+ ## Visualization Standards
92
+
93
+ Use **Plotly** as the primary visualization library for beautiful, interactive charts:
94
+ - Clean, professional appearance with `template="plotly_white"`
95
+ - Interactive features: hover tooltips, zoom, pan
96
+ - Consistent color palette: blues (#3498db, #2980b9) for wealth, greens (#27ae60, #2ecc71) for spending/survival
97
+ - Fan charts with gradient opacity for percentile bands (P10-P90)
98
+ - Export capability to HTML/PNG for reports
@@ -0,0 +1,265 @@
1
+ Metadata-Version: 2.4
2
+ Name: fundedness
3
+ Version: 0.2.0
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
+ [![CI](https://github.com/engineerinvestor/financial-health-calculator/actions/workflows/ci.yml/badge.svg)](https://github.com/engineerinvestor/financial-health-calculator/actions/workflows/ci.yml)
60
+ [![codecov](https://codecov.io/gh/engineerinvestor/financial-health-calculator/branch/main/graph/badge.svg)](https://codecov.io/gh/engineerinvestor/financial-health-calculator)
61
+ [![Documentation](https://img.shields.io/badge/docs-mkdocs-blue.svg)](https://engineerinvestor.github.io/financial-health-calculator/)
62
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
63
+ [![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)
64
+
65
+ A comprehensive Python financial planning toolkit with CEFR calculations, Monte Carlo simulations, and beautiful Plotly visualizations.
66
+
67
+ ## Features
68
+
69
+ - **CEFR (Certainty-Equivalent Funded Ratio)**: A fundedness metric that accounts for taxes, liquidity, and concentration risk
70
+ - **Monte Carlo Simulations**: Project retirement outcomes with configurable market assumptions
71
+ - **Withdrawal Strategy Lab**: Compare strategies including fixed SWR, guardrails, VPW, RMD-style, and Merton optimal
72
+ - **Utility Optimization**: Victor Haghani / Elm Wealth methodology for optimal spending and allocation
73
+ - **Beautiful Visualizations**: Interactive Plotly charts with fan charts, waterfalls, and survival curves
74
+ - **REST API**: FastAPI backend for programmatic access
75
+ - **Streamlit App**: User-friendly web interface
76
+
77
+ ## Quick Start
78
+
79
+ ### Installation
80
+
81
+ ```bash
82
+ pip install fundedness
83
+ ```
84
+
85
+ For development with all extras:
86
+ ```bash
87
+ pip install "fundedness[all]"
88
+ ```
89
+
90
+ ### Basic Usage
91
+
92
+ ```python
93
+ from fundedness import Asset, BalanceSheet, Liability, compute_cefr
94
+ from fundedness.models.assets import AccountType, LiquidityClass, ConcentrationLevel
95
+
96
+ # Define your assets
97
+ assets = [
98
+ Asset(
99
+ name="401(k)",
100
+ value=500_000,
101
+ account_type=AccountType.TAX_DEFERRED,
102
+ liquidity_class=LiquidityClass.RETIREMENT,
103
+ concentration_level=ConcentrationLevel.DIVERSIFIED,
104
+ ),
105
+ Asset(
106
+ name="Roth IRA",
107
+ value=200_000,
108
+ account_type=AccountType.TAX_EXEMPT,
109
+ liquidity_class=LiquidityClass.RETIREMENT,
110
+ concentration_level=ConcentrationLevel.DIVERSIFIED,
111
+ ),
112
+ ]
113
+
114
+ # Define your spending
115
+ liabilities = [
116
+ Liability(name="Living Expenses", annual_amount=50_000, is_essential=True),
117
+ Liability(name="Travel", annual_amount=20_000, is_essential=False),
118
+ ]
119
+
120
+ # Calculate CEFR
121
+ result = compute_cefr(
122
+ balance_sheet=BalanceSheet(assets=assets),
123
+ liabilities=liabilities,
124
+ planning_horizon=30,
125
+ )
126
+
127
+ print(f"CEFR: {result.cefr:.2f}")
128
+ print(f"Funded: {result.is_funded}")
129
+ print(result.get_interpretation())
130
+ ```
131
+
132
+ ## Tutorials
133
+
134
+ - [CEFR Basics](https://colab.research.google.com/github/engineerinvestor/financial-health-calculator/blob/main/examples/01_cefr_basics.ipynb) - Introduction to the CEFR metric
135
+ - [Time Distribution Analysis](https://colab.research.google.com/github/engineerinvestor/financial-health-calculator/blob/main/examples/02_time_distribution.ipynb) - Monte Carlo simulations
136
+ - [Withdrawal Strategy Comparison](https://colab.research.google.com/github/engineerinvestor/financial-health-calculator/blob/main/examples/03_withdrawal_comparison.ipynb) - Compare different approaches
137
+
138
+ ## Running the Apps
139
+
140
+ ### Streamlit Web App
141
+
142
+ ```bash
143
+ streamlit run streamlit_app/app.py
144
+ ```
145
+
146
+ ### FastAPI REST API
147
+
148
+ ```bash
149
+ uvicorn api.main:app --reload
150
+ ```
151
+
152
+ API documentation available at `http://localhost:8000/docs`
153
+
154
+ ## Key Concepts
155
+
156
+ ### CEFR (Certainty-Equivalent Funded Ratio)
157
+
158
+ CEFR measures how well-funded your retirement is after accounting for:
159
+
160
+ - **Tax Haircuts**: What you'll owe when withdrawing from different account types
161
+ - **Liquidity Haircuts**: How easily you can access your assets
162
+ - **Reliability Haircuts**: Risk from concentrated positions
163
+
164
+ **Formula:**
165
+ ```
166
+ CEFR = Σ(Asset × (1-τ) × λ × ρ) / PV(Liabilities)
167
+ ```
168
+
169
+ Where τ = tax rate, λ = liquidity factor, ρ = reliability factor
170
+
171
+ **Interpretation:**
172
+ - CEFR ≥ 2.0: Excellent - Very well-funded
173
+ - CEFR 1.5-2.0: Strong - Well-funded with margin
174
+ - CEFR 1.0-1.5: Adequate - Fully funded
175
+ - CEFR < 1.0: Underfunded - Action needed
176
+
177
+ ### Withdrawal Strategies
178
+
179
+ | Strategy | Description | Best For |
180
+ |----------|-------------|----------|
181
+ | Fixed SWR | 4% of initial portfolio, adjusted for inflation | Predictability |
182
+ | % of Portfolio | Fixed % of current value | Market adaptation |
183
+ | Guardrails | Adjustable with floor/ceiling | Balance |
184
+ | VPW | Age-based variable percentage | Maximizing spending |
185
+ | RMD-Style | IRS distribution table based | Tax efficiency |
186
+ | Merton Optimal | Utility-maximizing spending rate | Optimality |
187
+
188
+ ### Utility Optimization
189
+
190
+ The toolkit includes Merton's optimal consumption and portfolio choice framework, as applied in modern retirement planning research<sup>[1]</sup>:
191
+
192
+ - **Optimal Equity Allocation**: `k* = (μ - r) / (γ × σ²)`
193
+ - **Wealth-Adjusted Allocation**: Reduces equity as wealth approaches subsistence floor
194
+ - **Optimal Spending Rate**: Increases with age as horizon shortens
195
+ - **Expected Lifetime Utility**: Track utility across Monte Carlo paths
196
+
197
+ Key insights from this methodology:
198
+ 1. Optimal spending starts low (~2-3%) and rises with age
199
+ 2. Allocation should decrease as wealth approaches the floor
200
+ 3. Risk aversion (gamma) is the critical input parameter
201
+ 4. The 4% rule is suboptimal from a utility perspective
202
+
203
+ ## Development
204
+
205
+ ### Setup
206
+
207
+ ```bash
208
+ git clone https://github.com/engineerinvestor/financial-health-calculator.git
209
+ cd financial-health-calculator
210
+ pip install -e ".[dev]"
211
+ ```
212
+
213
+ ### Running Tests
214
+
215
+ ```bash
216
+ pytest
217
+ ```
218
+
219
+ ### Code Quality
220
+
221
+ ```bash
222
+ ruff check .
223
+ mypy fundedness
224
+ ```
225
+
226
+ ## Project Structure
227
+
228
+ ```
229
+ financial-health-calculator/
230
+ ├── fundedness/ # Core Python package
231
+ │ ├── models/ # Pydantic data models
232
+ │ ├── viz/ # Plotly visualizations
233
+ │ ├── withdrawals/ # Withdrawal strategies (SWR, guardrails, VPW, Merton)
234
+ │ ├── allocation/ # Asset allocation strategies (constant, glidepath, Merton)
235
+ │ ├── cefr.py # CEFR calculation
236
+ │ ├── simulate.py # Monte Carlo engine with utility tracking
237
+ │ ├── merton.py # Merton optimal formulas
238
+ │ ├── optimize.py # Policy parameter optimization
239
+ │ └── policies.py # Spending/allocation policies
240
+ ├── api/ # FastAPI REST API
241
+ ├── streamlit_app/ # Streamlit web application
242
+ │ └── pages/ # Includes Utility Optimization page
243
+ ├── examples/ # Jupyter notebooks
244
+ └── tests/ # pytest tests
245
+ ```
246
+
247
+ ## Contact
248
+
249
+ - Twitter: [@egr_investor](https://x.com/egr_investor)
250
+ - GitHub: [engineerinvestor](https://github.com/engineerinvestor)
251
+ - Email: egr.investor@gmail.com
252
+
253
+ ## License
254
+
255
+ MIT License
256
+
257
+ ## References
258
+
259
+ 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.
260
+
261
+ 2. Merton, R. C. (1969). Lifetime Portfolio Selection under Uncertainty: The Continuous-Time Case. *The Review of Economics and Statistics*, 51(3), 247-257.
262
+
263
+ ## Disclaimer
264
+
265
+ This tool is for educational purposes only and does not constitute financial advice. Consult a qualified financial advisor for personalized recommendations.