owlplanner 2025.12.5__tar.gz → 2026.1.26__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.
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/.github/workflows/github-actions-runtests.yml +1 -1
- owlplanner-2026.1.26/.gitignore +91 -0
- owlplanner-2026.1.26/.streamlit/config.toml +3 -0
- owlplanner-2026.1.26/AUTHORS +15 -0
- owlplanner-2026.1.26/Adamodar_Rates_2026.xlsx +0 -0
- owlplanner-2026.1.26/INSTALL.md +132 -0
- owlplanner-2026.1.26/PARAMETERS.md +289 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/PKG-INFO +50 -158
- owlplanner-2026.1.26/README.md +96 -0
- owlplanner-2026.1.26/RELEASE_NOTES.md +229 -0
- owlplanner-2026.1.26/USER_GUIDE.md +279 -0
- owlplanner-2026.1.26/awi.txt +75 -0
- owlplanner-2026.1.26/case_test.toml +69 -0
- owlplanner-2026.1.26/convert_rates.py +58 -0
- owlplanner-2026.1.26/docker/buildContainers.sh +8 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/docker/buildPackage.cmd +3 -0
- owlplanner-2026.1.26/docker/buildPackage.sh +10 -0
- owlplanner-2026.1.26/docs/examples/example-1.html +1313 -0
- owlplanner-2026.1.26/docs/index.html +631 -0
- owlplanner-2026.1.26/docs/install-uv.html +680 -0
- owlplanner-2026.1.26/docs/installation.html +649 -0
- owlplanner-2026.1.26/docs/papers +1 -0
- owlplanner-2026.1.26/docs/search.json +191 -0
- owlplanner-2026.1.26/docs/site_libs/bootstrap/bootstrap-45a48b56c8ad2523a9a31c69be39928e.min.css +12 -0
- owlplanner-2026.1.26/docs/site_libs/bootstrap/bootstrap-icons.css +2106 -0
- owlplanner-2026.1.26/docs/site_libs/bootstrap/bootstrap-icons.woff +0 -0
- owlplanner-2026.1.26/docs/site_libs/bootstrap/bootstrap.min.js +7 -0
- owlplanner-2026.1.26/docs/site_libs/clipboard/clipboard.min.js +7 -0
- owlplanner-2026.1.26/docs/site_libs/quarto-html/anchor.min.js +9 -0
- owlplanner-2026.1.26/docs/site_libs/quarto-html/axe/axe-check.js +145 -0
- owlplanner-2026.1.26/docs/site_libs/quarto-html/popper.min.js +6 -0
- owlplanner-2026.1.26/docs/site_libs/quarto-html/quarto-syntax-highlighting-587c61ba64f3a5504c4d52d930310e48.css +236 -0
- owlplanner-2026.1.26/docs/site_libs/quarto-html/quarto.js +847 -0
- owlplanner-2026.1.26/docs/site_libs/quarto-html/tabsets/tabsets.js +95 -0
- owlplanner-2026.1.26/docs/site_libs/quarto-html/tippy.css +1 -0
- owlplanner-2026.1.26/docs/site_libs/quarto-html/tippy.umd.min.js +2 -0
- owlplanner-2026.1.26/docs/site_libs/quarto-nav/headroom.min.js +7 -0
- owlplanner-2026.1.26/docs/site_libs/quarto-nav/quarto-nav.js +325 -0
- owlplanner-2026.1.26/docs/site_libs/quarto-search/autocomplete.umd.js +3 -0
- owlplanner-2026.1.26/docs/site_libs/quarto-search/fuse.min.js +9 -0
- owlplanner-2026.1.26/docs/site_libs/quarto-search/quarto-search.js +1290 -0
- owlplanner-2026.1.26/docs/users_guide.html +719 -0
- owlplanner-2026.1.26/examples/Case_drawdowncalc-comparison-1.toml +57 -0
- owlplanner-2026.1.26/examples/Case_jack+jill.toml +62 -0
- owlplanner-2026.1.26/examples/Case_joe.toml +55 -0
- owlplanner-2026.1.26/examples/Case_john+sally.toml +59 -0
- owlplanner-2026.1.26/examples/Case_jon+jane.toml +60 -0
- owlplanner-2026.1.26/examples/Case_kim+sam-bequest.toml +63 -0
- owlplanner-2026.1.26/examples/Case_kim+sam-spending.toml +63 -0
- owlplanner-2026.1.26/examples/HFP_jack+jill.xlsx +0 -0
- owlplanner-2026.1.26/examples/HFP_jack+jill_house.xlsx +0 -0
- owlplanner-2026.1.26/examples/HFP_joe.xlsx +0 -0
- owlplanner-2026.1.26/examples/HFP_john+sally.xlsx +0 -0
- owlplanner-2026.1.26/examples/HFP_jon+jane.xlsx +0 -0
- owlplanner-2026.1.26/examples/HFP_kim+sam.xlsx +0 -0
- owlplanner-2026.1.26/examples/HFP_template.xlsx +0 -0
- owlplanner-2026.1.26/iteration_data.csv +32 -0
- owlplanner-2026.1.26/iteration_data_2.csv +57 -0
- owlplanner-2026.1.26/myrates.csv +3 -0
- owlplanner-2026.1.26/myrates.xlsx +0 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/notebooks/john+sally.ipynb +2 -2
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/notebooks/kim+sam.ipynb +2 -2
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/notebooks/template.ipynb +2 -1
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/notebooks/tutorial_1.ipynb +2 -1
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/notebooks/tutorial_2.ipynb +2 -1
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/notebooks/tutorial_3.ipynb +2 -1
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/owlplanner.cmd +1 -1
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/owl.pdf +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/owl.tex +320 -166
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/pyproject.toml +13 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/pytest.ini +3 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/requirements.txt +6 -5
- owlplanner-2026.1.26/site-src/.gitignore +2 -0
- owlplanner-2026.1.26/site-src/README.md +19 -0
- owlplanner-2026.1.26/site-src/_quarto.yml +26 -0
- owlplanner-2026.1.26/site-src/assets/owl.png +0 -0
- owlplanner-2026.1.26/site-src/examples/example-1.qmd +252 -0
- owlplanner-2026.1.26/site-src/examples/workbook_jack & jill - tutorial.xlsx +0 -0
- owlplanner-2025.12.5/README.md → owlplanner-2026.1.26/site-src/index.qmd +47 -82
- owlplanner-2026.1.26/site-src/install-uv.qmd +108 -0
- owlplanner-2026.1.26/site-src/installation.qmd +136 -0
- owlplanner-2025.12.5/USER_GUIDE.md → owlplanner-2026.1.26/site-src/users_guide.qmd +28 -15
- owlplanner-2026.1.26/src/owlplanner/In Discussion #58, the case of Kim and Sam.md +307 -0
- owlplanner-2026.1.26/src/owlplanner/__init__.py +27 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/src/owlplanner/abcapi.py +24 -23
- owlplanner-2026.1.26/src/owlplanner/cli/README.md +50 -0
- owlplanner-2026.1.26/src/owlplanner/cli/_main.py +52 -0
- owlplanner-2026.1.26/src/owlplanner/cli/cli_logging.py +56 -0
- owlplanner-2026.1.26/src/owlplanner/cli/cmd_list.py +83 -0
- owlplanner-2026.1.26/src/owlplanner/cli/cmd_run.py +86 -0
- owlplanner-2026.1.26/src/owlplanner/config.py +498 -0
- owlplanner-2026.1.26/src/owlplanner/data/__init__.py +21 -0
- owlplanner-2026.1.26/src/owlplanner/data/awi.csv +75 -0
- owlplanner-2026.1.26/src/owlplanner/data/bendpoints.csv +49 -0
- owlplanner-2026.1.26/src/owlplanner/data/newawi.csv +75 -0
- owlplanner-2026.1.26/src/owlplanner/data/rates.csv +99 -0
- owlplanner-2026.1.26/src/owlplanner/debts.py +315 -0
- owlplanner-2026.1.26/src/owlplanner/fixedassets.py +288 -0
- owlplanner-2026.1.26/src/owlplanner/mylogging.py +216 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/src/owlplanner/plan.py +1044 -332
- owlplanner-2026.1.26/src/owlplanner/plotting/__init__.py +25 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/src/owlplanner/plotting/base.py +17 -3
- owlplanner-2026.1.26/src/owlplanner/plotting/factory.py +50 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/src/owlplanner/plotting/matplotlib_backend.py +30 -7
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/src/owlplanner/plotting/plotly_backend.py +33 -10
- owlplanner-2026.1.26/src/owlplanner/progress.py +81 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/src/owlplanner/rates.py +366 -361
- owlplanner-2026.1.26/src/owlplanner/socialsecurity.py +209 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/src/owlplanner/tax2026.py +170 -57
- owlplanner-2026.1.26/src/owlplanner/timelists.py +406 -0
- owlplanner-2026.1.26/src/owlplanner/utils.py +302 -0
- owlplanner-2026.1.26/src/owlplanner/version.py +20 -0
- owlplanner-2026.1.26/tests/test_abcapi_coverage.py +305 -0
- owlplanner-2026.1.26/tests/test_config_coverage.py +340 -0
- owlplanner-2026.1.26/tests/test_debts.py +447 -0
- owlplanner-2026.1.26/tests/test_fixedassets.py +746 -0
- owlplanner-2026.1.26/tests/test_historical.py +66 -0
- owlplanner-2026.1.26/tests/test_logger.py +49 -0
- owlplanner-2026.1.26/tests/test_ltcg.py +45 -0
- owlplanner-2026.1.26/tests/test_mc.py +66 -0
- owlplanner-2026.1.26/tests/test_mylogging_coverage.py +287 -0
- owlplanner-2026.1.26/tests/test_plan_edge_cases.py +426 -0
- owlplanner-2026.1.26/tests/test_rates.py +514 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/tests/test_regressions.py +61 -32
- owlplanner-2026.1.26/tests/test_repro.py +250 -0
- owlplanner-2026.1.26/tests/test_socsec.py +100 -0
- owlplanner-2026.1.26/tests/test_summary.py +271 -0
- owlplanner-2026.1.26/tests/test_timelists.py +410 -0
- owlplanner-2026.1.26/tests/test_timelists_coverage.py +364 -0
- owlplanner-2026.1.26/tests/test_toml_cases.py +168 -0
- owlplanner-2026.1.26/tests/test_ui_asset_allocation.py +36 -0
- owlplanner-2026.1.26/tests/test_ui_compare_summaries.py +40 -0
- owlplanner-2026.1.26/tests/test_ui_sskeys.py +45 -0
- owlplanner-2026.1.26/tests/test_units.py +31 -0
- owlplanner-2026.1.26/tests/test_utils_coverage.py +283 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/About_Owl.py +42 -12
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/Asset_Allocation.py +37 -10
- owlplanner-2026.1.26/ui/Create_Case.py +226 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/Documentation.py +330 -138
- owlplanner-2026.1.26/ui/Fixed_Income.py +200 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/Graphs.py +23 -1
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/Historical_Range.py +24 -4
- owlplanner-2026.1.26/ui/Household_Financial_Profile.py +303 -0
- owlplanner-2026.1.26/ui/Logs.py +113 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/Monte_Carlo.py +23 -1
- owlplanner-2026.1.26/ui/Optimization_Parameters.py +219 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/Output_Files.py +34 -14
- owlplanner-2026.1.26/ui/Parameters_Reference.py +37 -0
- owlplanner-2026.1.26/ui/Quick_Start.py +107 -0
- owlplanner-2026.1.26/ui/Rates_Selection.py +313 -0
- owlplanner-2026.1.26/ui/Savings_Assets.py +106 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/Settings.py +28 -6
- owlplanner-2026.1.26/ui/Worksheets.py +41 -0
- owlplanner-2026.1.26/ui/__init__.py +21 -0
- owlplanner-2026.1.26/ui/case_progress.py +272 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/main.py +27 -3
- owlplanner-2026.1.26/ui/owl.png +0 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/owlbridge.py +350 -75
- owlplanner-2026.1.26/ui/progress.py +46 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/sskeys.py +162 -47
- owlplanner-2026.1.26/ui/tomlexamples.py +105 -0
- owlplanner-2025.12.5/.gitignore +0 -10
- owlplanner-2025.12.5/.streamlit/config.toml +0 -3
- owlplanner-2025.12.5/INSTALL.md +0 -76
- owlplanner-2025.12.5/RELEASE_NOTES.md +0 -43
- owlplanner-2025.12.5/examples/case_drawdowncalc-comparison-1.toml +0 -58
- owlplanner-2025.12.5/examples/case_jack+jill.toml +0 -58
- owlplanner-2025.12.5/examples/case_joe.toml +0 -55
- owlplanner-2025.12.5/examples/case_john+sally.toml +0 -54
- owlplanner-2025.12.5/examples/case_jon+jane.toml +0 -57
- owlplanner-2025.12.5/examples/case_kim+sam-bequest.toml +0 -57
- owlplanner-2025.12.5/examples/case_kim+sam-spending.toml +0 -57
- owlplanner-2025.12.5/examples/jack+jill.xlsx +0 -0
- owlplanner-2025.12.5/examples/joe.xlsx +0 -0
- owlplanner-2025.12.5/examples/john+sally.xlsx +0 -0
- owlplanner-2025.12.5/examples/jon+jane.xlsx +0 -0
- owlplanner-2025.12.5/examples/kim+sam.xlsx +0 -0
- owlplanner-2025.12.5/examples/template.xlsx +0 -0
- owlplanner-2025.12.5/examples/ttt.toml +0 -58
- owlplanner-2025.12.5/src/owlplanner/__init__.py +0 -8
- owlplanner-2025.12.5/src/owlplanner/config.py +0 -319
- owlplanner-2025.12.5/src/owlplanner/data/__init__.py +0 -0
- owlplanner-2025.12.5/src/owlplanner/data/rates.csv +0 -98
- owlplanner-2025.12.5/src/owlplanner/mylogging.py +0 -84
- owlplanner-2025.12.5/src/owlplanner/plotting/__init__.py +0 -12
- owlplanner-2025.12.5/src/owlplanner/plotting/factory.py +0 -37
- owlplanner-2025.12.5/src/owlplanner/progress.py +0 -24
- owlplanner-2025.12.5/src/owlplanner/socialsecurity.py +0 -89
- owlplanner-2025.12.5/src/owlplanner/tax2025.py +0 -339
- owlplanner-2025.12.5/src/owlplanner/timelists.py +0 -122
- owlplanner-2025.12.5/src/owlplanner/utils.py +0 -103
- owlplanner-2025.12.5/src/owlplanner/version.py +0 -1
- owlplanner-2025.12.5/tests/test_logger.py +0 -21
- owlplanner-2025.12.5/tests/test_repro.py +0 -126
- owlplanner-2025.12.5/tests/test_socsec.py +0 -72
- owlplanner-2025.12.5/tests/test_toml_cases.py +0 -52
- owlplanner-2025.12.5/tests/test_ui_asset_allocation.py +0 -14
- owlplanner-2025.12.5/tests/test_ui_compare_summaries.py +0 -18
- owlplanner-2025.12.5/tests/test_ui_sskeys.py +0 -24
- owlplanner-2025.12.5/tests/test_units.py +0 -11
- owlplanner-2025.12.5/ui/AI +0 -48
- owlplanner-2025.12.5/ui/Create_Case.py +0 -137
- owlplanner-2025.12.5/ui/Current_Assets.py +0 -79
- owlplanner-2025.12.5/ui/Fixed_Income.py +0 -94
- owlplanner-2025.12.5/ui/Logs.py +0 -14
- owlplanner-2025.12.5/ui/Optimization_Parameters.py +0 -153
- owlplanner-2025.12.5/ui/Quick_Start.py +0 -86
- owlplanner-2025.12.5/ui/Rates_Selection.py +0 -243
- owlplanner-2025.12.5/ui/Wages_and_Contributions.py +0 -91
- owlplanner-2025.12.5/ui/Worksheets.py +0 -19
- owlplanner-2025.12.5/ui/__init__.py +0 -0
- owlplanner-2025.12.5/ui/progress.py +0 -29
- owlplanner-2025.12.5/ui/tomlexamples.py +0 -31
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/.devcontainer/devcontainer.json +0 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/.flake8 +0 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/.gitattributes +0 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/.streamlit/fullconfig.toml +0 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/LICENSE +0 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/docker/Dockerfile.bare +0 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/docker/Dockerfile.static +0 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/docker/README.md +0 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/docker/buildContainers.cmd +0 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/docker/buildentrypoint.sh +0 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/docker/docker-compose.yml +0 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/docker/runentrypoint.sh +0 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/owlplanner.sh +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/AD-taxDef.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/AD-taxFree.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/AD-taxable.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/Hist_Bequest.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/Hist_Spending.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/MC-tutorial2a.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/MC-tutorial2b.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/OwlUI.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/allocations.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/owl.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/piecewiseConstant.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/profile.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/ratesCorrelations.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/ratesPlot.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/savingsPlot.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/sourcesPlot.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/spendingPlot.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/taxIncomePlot.png +0 -0
- {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/taxesPlot.png +0 -0
- {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/README.md +0 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# --------------------------------------------------
|
|
2
|
+
# Python
|
|
3
|
+
# --------------------------------------------------
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.py[cod]
|
|
6
|
+
*.so
|
|
7
|
+
.coverage
|
|
8
|
+
.coverage.*
|
|
9
|
+
.pytest_cache/
|
|
10
|
+
.mypy_cache/
|
|
11
|
+
.ruff_cache/
|
|
12
|
+
|
|
13
|
+
# --------------------------------------------------
|
|
14
|
+
# Virtual environments
|
|
15
|
+
# --------------------------------------------------
|
|
16
|
+
.venv/
|
|
17
|
+
venv/
|
|
18
|
+
.env/
|
|
19
|
+
|
|
20
|
+
# --------------------------------------------------
|
|
21
|
+
# Conda (optional developer use)
|
|
22
|
+
# --------------------------------------------------
|
|
23
|
+
.conda/
|
|
24
|
+
conda-meta/
|
|
25
|
+
*.conda
|
|
26
|
+
*.conda-lock
|
|
27
|
+
environment.lock.yml
|
|
28
|
+
|
|
29
|
+
# --------------------------------------------------
|
|
30
|
+
# uv / packaging
|
|
31
|
+
# --------------------------------------------------
|
|
32
|
+
dist/
|
|
33
|
+
build/
|
|
34
|
+
*.egg-info/
|
|
35
|
+
|
|
36
|
+
# IMPORTANT:
|
|
37
|
+
# uv.lock IS TRACKED (do not ignore) but...
|
|
38
|
+
# Left there for now to prevent Streamlit lock down
|
|
39
|
+
# Added before building packages in docker/scripts
|
|
40
|
+
uv.lock
|
|
41
|
+
|
|
42
|
+
# --------------------------------------------------
|
|
43
|
+
# Quarto
|
|
44
|
+
# --------------------------------------------------
|
|
45
|
+
.quarto/
|
|
46
|
+
*_cache/
|
|
47
|
+
*_files/
|
|
48
|
+
|
|
49
|
+
# --------------------------------------------------
|
|
50
|
+
# Jupyter
|
|
51
|
+
# --------------------------------------------------
|
|
52
|
+
.ipynb_checkpoints/
|
|
53
|
+
|
|
54
|
+
# --------------------------------------------------
|
|
55
|
+
# Streamlit
|
|
56
|
+
# --------------------------------------------------
|
|
57
|
+
.streamlit/secrets.toml
|
|
58
|
+
|
|
59
|
+
# --------------------------------------------------
|
|
60
|
+
# dotenv / secrets
|
|
61
|
+
# --------------------------------------------------
|
|
62
|
+
.env
|
|
63
|
+
.env.*
|
|
64
|
+
!.env.example
|
|
65
|
+
|
|
66
|
+
# --------------------------------------------------
|
|
67
|
+
# Logs & temporary files
|
|
68
|
+
# --------------------------------------------------
|
|
69
|
+
*.log
|
|
70
|
+
*.aux
|
|
71
|
+
*~
|
|
72
|
+
|
|
73
|
+
# --------------------------------------------------
|
|
74
|
+
# OS / editor noise
|
|
75
|
+
# --------------------------------------------------
|
|
76
|
+
.DS_Store
|
|
77
|
+
Thumbs.db
|
|
78
|
+
*.swp
|
|
79
|
+
*.swo
|
|
80
|
+
|
|
81
|
+
# --------------------------------------------------
|
|
82
|
+
# Project-specific ignored folders
|
|
83
|
+
# --------------------------------------------------
|
|
84
|
+
otherFiles/
|
|
85
|
+
myfiles/
|
|
86
|
+
secrets/
|
|
87
|
+
|
|
88
|
+
# --------------------------------------------------
|
|
89
|
+
# GitHub Pages
|
|
90
|
+
# --------------------------------------------------
|
|
91
|
+
# docs/ IS TRACKED (Quarto output)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# This is the list of Owlplanner's significant contributors.
|
|
2
|
+
#
|
|
3
|
+
# This does not necessarily list everyone who has contributed code.
|
|
4
|
+
# To see the full list of contributors, see the revision history in
|
|
5
|
+
# source control.
|
|
6
|
+
Martin-D. Lacasse (mdlacasse, original author)
|
|
7
|
+
Robert E. Anderson (NH-RedAnt)
|
|
8
|
+
Clark Jefcoat (hubcity)
|
|
9
|
+
kg333
|
|
10
|
+
John Leonard (jleonard99)
|
|
11
|
+
Benjamin Quinn (blquinn)
|
|
12
|
+
Dale Seng (sengsational)
|
|
13
|
+
Josh Williams (noimjosh)
|
|
14
|
+
Gene Wood (gene1wood)
|
|
15
|
+
|
|
Binary file
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Owl - Optimal Wealth Lab
|
|
2
|
+
|
|
3
|
+
## A retirement exploration tool based on linear programming
|
|
4
|
+
|
|
5
|
+
<img align=right src="https://github.com/mdlacasse/Owl/blob/main/docs/images/owl.png?raw=true" width="250">
|
|
6
|
+
|
|
7
|
+
------------------------------------------------------------------------------------
|
|
8
|
+
### About
|
|
9
|
+
This document is aimed at software developers desiring to install the Owl source code
|
|
10
|
+
and run it locally on their computer.
|
|
11
|
+
|
|
12
|
+
For end-users, we suggest accessing Owl from the
|
|
13
|
+
[Streamlit Community Server](http://owlplanner.streamlit.app)
|
|
14
|
+
or, if one prefers to have everything on their own computer,
|
|
15
|
+
to install and run a Docker image as described in these [instructions](docker/README.md).
|
|
16
|
+
|
|
17
|
+
### Requirements
|
|
18
|
+
You will need a Python environment, and the `pip` module installed on your
|
|
19
|
+
computer for completing the installation. The `build` module will be required
|
|
20
|
+
for developers. You will also need `git` to manage the source code from GitHub
|
|
21
|
+
which is found [here](https://git-scm.com/install/windows) for Windows,
|
|
22
|
+
and by installing developer tools on MacOS and Linux.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
A good option for a comprehensive Python environment is to use the *Anaconda* distribution
|
|
26
|
+
that can be found [here](https://repo.anaconda.com/archive/) for various operating systems.
|
|
27
|
+
Installation of *Anaconda* can be done by downloading and running the installation
|
|
28
|
+
file corresponding to your operating system and hardware.
|
|
29
|
+
|
|
30
|
+
Instructions given here are command-line instructions to be entered from a terminal window.
|
|
31
|
+
|
|
32
|
+
If using *Anaconda*, `pip` can be installed as follows
|
|
33
|
+
```
|
|
34
|
+
conda install pip
|
|
35
|
+
```
|
|
36
|
+
otherwise, your distribution will most likely include `pip` already.
|
|
37
|
+
|
|
38
|
+
The `build` module is included in *Anaconda*.
|
|
39
|
+
Command `pip install build` will install it in other distributions.
|
|
40
|
+
|
|
41
|
+
### Creating a virtual environment
|
|
42
|
+
It is common practice to create a virtual environment for a specific project.
|
|
43
|
+
This is to avoid making changes in the base ditribution that could break dependencies.
|
|
44
|
+
Creating and activating a new environment called *owlenv* in *Anaconda*
|
|
45
|
+
is achieved by the following commands:
|
|
46
|
+
```
|
|
47
|
+
conda create --name owlenv
|
|
48
|
+
conda activate owlenv
|
|
49
|
+
```
|
|
50
|
+
A cheat sheet for *Anaconda* can be found
|
|
51
|
+
[here](https://docs.conda.io/projects/conda/en/latest/user-guide/cheatsheet.html).
|
|
52
|
+
|
|
53
|
+
When not using `conda`, creating and activating an environment can be done by
|
|
54
|
+
using the module `venv` as follows:
|
|
55
|
+
```
|
|
56
|
+
python -m venv owlenv
|
|
57
|
+
```
|
|
58
|
+
This will create subdirectory *owlenv* in the current directory.
|
|
59
|
+
For activating this environment:
|
|
60
|
+
```
|
|
61
|
+
# in MS command
|
|
62
|
+
.\owlenv\Scripts\activate.bat
|
|
63
|
+
|
|
64
|
+
# in MS PowerShell
|
|
65
|
+
./owlenv/Scripts/activate.ps1
|
|
66
|
+
|
|
67
|
+
# MacOS or Linux
|
|
68
|
+
source ./owlenv/Scripts/activate
|
|
69
|
+
```
|
|
70
|
+
More details on how to create a virtual environment using *venv* can be found
|
|
71
|
+
[here](https://python.land/virtual-environments/virtualenv).
|
|
72
|
+
|
|
73
|
+
### Obtaining Owl's source code
|
|
74
|
+
We assume that you have created and activated a virtual environment
|
|
75
|
+
at this point. From there, we install the latest version of Owl from GitHub.
|
|
76
|
+
```shell
|
|
77
|
+
git clone https://github.com/mdlacasse/Owl.git
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
Then go (`cd`) to the directory where you installed Owl.
|
|
81
|
+
```
|
|
82
|
+
cd Owl
|
|
83
|
+
```
|
|
84
|
+
From the top directory of the source code run:
|
|
85
|
+
The following command will install the current version of Owl and all its dependencies:
|
|
86
|
+
```shell
|
|
87
|
+
pip install --upgrade -r requirements.txt
|
|
88
|
+
```
|
|
89
|
+
You can also install the Owl package directly from the [Python Package Index](http://pypi.org).
|
|
90
|
+
|
|
91
|
+
### Running the Streamlit frontend locally
|
|
92
|
+
Once Owl's source code and all its dependencies as been installed,
|
|
93
|
+
one can run the Owl user interface locally:
|
|
94
|
+
```shell
|
|
95
|
+
# From Windows
|
|
96
|
+
./owlplanner.cmd
|
|
97
|
+
|
|
98
|
+
# From MacOS or Linux
|
|
99
|
+
./owlplanner.sh
|
|
100
|
+
```
|
|
101
|
+
This will open a tab on your default browser.
|
|
102
|
+
|
|
103
|
+
### Installation steps for developers
|
|
104
|
+
First use the same steps as above to create and activate a virtual environment
|
|
105
|
+
and install the source code from GitHub.
|
|
106
|
+
Then make sure that the `build` module is installed (`pip install build`).
|
|
107
|
+
|
|
108
|
+
The next commands will build and install the Owl module in "edit mode"
|
|
109
|
+
```shell
|
|
110
|
+
python -m build
|
|
111
|
+
pip install -e .
|
|
112
|
+
```
|
|
113
|
+
The -e instructs `pip` to install in *editable* mode and use the live version
|
|
114
|
+
in the current directory tree.
|
|
115
|
+
|
|
116
|
+
### Publishing a version (for reference only)
|
|
117
|
+
Run checks before all commits:
|
|
118
|
+
```
|
|
119
|
+
flake8 ui src tests
|
|
120
|
+
pytest
|
|
121
|
+
```
|
|
122
|
+
To update version, edit number in `src/owlplanner/version.py`.
|
|
123
|
+
|
|
124
|
+
To update package on pypi or testpypi,
|
|
125
|
+
|
|
126
|
+
```shell
|
|
127
|
+
rm dist/*
|
|
128
|
+
python -m build
|
|
129
|
+
twine upload --repository [repo] dist/*
|
|
130
|
+
```
|
|
131
|
+
where [repo] is *testpypi* or *pypi* depending on the type of release.
|
|
132
|
+
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# Owl Parameters
|
|
2
|
+
|
|
3
|
+
This document describes all parameters used in Owl TOML configuration files. The TOML file structure is organized into sections for clarity, and can be consumed by both the UI and CLI applications.
|
|
4
|
+
|
|
5
|
+
**Note:** Throughout this document, `N_i` refers to the number of individuals in the plan (1 for single, 2 for married).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Root Level Parameters
|
|
10
|
+
|
|
11
|
+
These parameters are defined at the root level of the TOML file (not within any section).
|
|
12
|
+
|
|
13
|
+
| Parameter | Type | Description |
|
|
14
|
+
|-----------|------|-------------|
|
|
15
|
+
| `case_name` | string | Name of the case/plan |
|
|
16
|
+
| `description` | string | A short text describing the purpose of the case |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## [basic_info]
|
|
21
|
+
|
|
22
|
+
Basic information about the individuals in the plan.
|
|
23
|
+
|
|
24
|
+
| Parameter | Type | Description |
|
|
25
|
+
|-----------|------|-------------|
|
|
26
|
+
| `status` | string | Filing status. Valid values: `"single"`, `"married"` |
|
|
27
|
+
| `names` | list of strings | Names of the individuals in the plan. Must contain 1 or 2 names. Length determines `N_i` |
|
|
28
|
+
| `date_of_birth` | list of `N_i` ISO dates | Date of birth for each individual in ISO format (e.g., `"1967-01-15"`). Defaults to `"1965-01-15"` if not specified |
|
|
29
|
+
| `life_expectancy` | list of `N_i` integers | Life expectancy in years for each individual |
|
|
30
|
+
| `start_date` | string | Start date of the plan (e.g., `"01-01"`, `"01/01"`, `"2026-01-01"`). Only the month and day are used; the plan always starts in the current year. Defaults to `"today"` if not specified |
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## [savings_assets]
|
|
35
|
+
|
|
36
|
+
Initial account balances and beneficiary information.
|
|
37
|
+
|
|
38
|
+
| Parameter | Type | Description |
|
|
39
|
+
|-----------|------|-------------|
|
|
40
|
+
| `taxable_savings_balances` | list of `N_i` floats | Initial balance in taxable accounts for each individual (in thousands of dollars) |
|
|
41
|
+
| `tax_deferred_savings_balances` | list of `N_i` floats | Initial balance in tax-deferred accounts (e.g., 401k, traditional IRA) for each individual (in thousands of dollars) |
|
|
42
|
+
| `tax_free_savings_balances` | list of `N_i` floats | Initial balance in tax-free accounts (e.g., Roth IRA, Roth 401k) for each individual (in thousands of dollars) |
|
|
43
|
+
| `beneficiary_fractions` | list of 3 floats | *(Married only)* Fraction of each account type (taxable, tax-deferred, tax-free) bequeathed to the surviving spouse. Each value should be between 0.0 and 1.0 |
|
|
44
|
+
| `spousal_surplus_deposit_fraction` | float | *(Married only)* Fraction of surplus to deposit in the second spouse's taxable account. Value between 0.0 and 1.0 |
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## [household_financial_profile]
|
|
49
|
+
|
|
50
|
+
Reference to the Excel file containing wages, contributions, and other time-varying financial data.
|
|
51
|
+
|
|
52
|
+
| Parameter | Type | Description |
|
|
53
|
+
|-----------|------|-------------|
|
|
54
|
+
| `HFP_file_name` | string | Name of the Excel file (`.xlsx`) containing wages, contributions, Roth conversions, and big-ticket items. Use `"None"` if no file is associated with the case |
|
|
55
|
+
|
|
56
|
+
**Note:** The Excel file should contain one sheet per individual with columns for: year, anticipated wages, taxable contributions, 401k contributions, Roth 401k contributions, IRA contributions, Roth IRA contributions, Roth conversions, and big-ticket items.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## [fixed_income]
|
|
61
|
+
|
|
62
|
+
Pension and Social Security information.
|
|
63
|
+
|
|
64
|
+
| Parameter | Type | Description |
|
|
65
|
+
|-----------|------|-------------|
|
|
66
|
+
| `pension_monthly_amounts` | list of `N_i` floats | Monthly pension amount for each individual (in dollars). Use `0` if no pension |
|
|
67
|
+
| `pension_ages` | list of `N_i` floats | Age at which pension starts for each individual |
|
|
68
|
+
| `pension_indexed` | list of `N_i` booleans | Whether each pension is indexed for inflation |
|
|
69
|
+
| `social_security_pia_amounts` | list of `N_i` integers | Primary Insurance Amount (PIA) for Social Security for each individual (in dollars) |
|
|
70
|
+
| `social_security_ages` | list of `N_i` floats | Age at which Social Security benefits start for each individual |
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## [rates_selection]
|
|
75
|
+
|
|
76
|
+
Investment return rates and inflation assumptions.
|
|
77
|
+
|
|
78
|
+
| Parameter | Type | Description |
|
|
79
|
+
|-----------|------|-------------|
|
|
80
|
+
| `heirs_rate_on_tax_deferred_estate` | float | Tax rate (as percentage, e.g., `30.0` for 30%) that heirs will pay on inherited tax-deferred accounts |
|
|
81
|
+
| `dividend_rate` | float | Dividend rate as a percentage (e.g., `1.72` for 1.72%) |
|
|
82
|
+
| `obbba_expiration_year` | integer | Year when the OBBBA (One Big Beautiful Bill Act) provisions expire. Default is `2032` |
|
|
83
|
+
| `method` | string | Method for determining rates. Valid values: `"default"`, `"optimistic"`, `"conservative"`, `"user"`, `"historical"`, `"historical average"`, `"stochastic"`, `"histochastic"` |
|
|
84
|
+
|
|
85
|
+
### Conditional Parameters Based on `method`
|
|
86
|
+
|
|
87
|
+
#### For `method = "user"` or `"stochastic"`:
|
|
88
|
+
| Parameter | Type | Description |
|
|
89
|
+
|-----------|------|-------------|
|
|
90
|
+
| `values` | list of 4 floats | Fixed rate values as percentages: [S&P 500 return, Corporate Baa bonds return, 10-year Treasury notes return, Inflation rate] |
|
|
91
|
+
|
|
92
|
+
#### For `method = "stochastic"`:
|
|
93
|
+
| Parameter | Type | Description |
|
|
94
|
+
|-----------|------|-------------|
|
|
95
|
+
| `standard_deviations` | list of 4 floats | Standard deviations (as percentages) for each rate type |
|
|
96
|
+
| `correlations` | array | Correlation matrix (4×4) or flattened upper triangle (6 values) for the four rate types |
|
|
97
|
+
|
|
98
|
+
#### For `method = "stochastic"` or `"histochastic"`:
|
|
99
|
+
| Parameter | Type | Description |
|
|
100
|
+
|-----------|------|-------------|
|
|
101
|
+
| `rate_seed` | integer | Random seed for reproducible stochastic rates |
|
|
102
|
+
| `reproducible_rates` | boolean | Whether stochastic rates should be reproducible |
|
|
103
|
+
|
|
104
|
+
#### For `method = "historical"`, `"historical average"`, or `"histochastic"`:
|
|
105
|
+
| Parameter | Type | Description |
|
|
106
|
+
|-----------|------|-------------|
|
|
107
|
+
| `from` | integer | Starting year for historical data range (must be between 1928 and 2025) |
|
|
108
|
+
| `to` | integer | Ending year for historical data range (must be between 1928 and 2025, and greater than `from`) |
|
|
109
|
+
|
|
110
|
+
**Note:** `from`/`to` are stored for all methods in saved case files. Methods that do not use them ignore these fields.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## [asset_allocation]
|
|
115
|
+
|
|
116
|
+
Asset allocation strategy and how it changes over time.
|
|
117
|
+
|
|
118
|
+
| Parameter | Type | Description |
|
|
119
|
+
|-----------|------|-------------|
|
|
120
|
+
| `interpolation_method` | string | Method for interpolating asset allocation over time. Valid values: `"linear"`, `"s-curve"` |
|
|
121
|
+
| `interpolation_center` | float | Center point of the interpolation curve (in years from start). Ignored for `"linear"` |
|
|
122
|
+
| `interpolation_width` | float | Width of the interpolation curve (in years). Ignored for `"linear"` |
|
|
123
|
+
| `type` | string | Type of allocation strategy. Valid values: `"account"`, `"individual"`, `"spouses"` |
|
|
124
|
+
|
|
125
|
+
### Conditional Parameters Based on `type`
|
|
126
|
+
|
|
127
|
+
#### For `type = "account"`:
|
|
128
|
+
| Parameter | Type | Description |
|
|
129
|
+
|-----------|------|-------------|
|
|
130
|
+
| `taxable` | 3D array | Asset allocation bounds for taxable accounts. Structure: `[[[initial_stocks, initial_bonds, initial_fixed, initial_real_estate], [final_stocks, final_bonds, final_fixed, final_real_estate]]]` for each individual |
|
|
131
|
+
| `tax-deferred` | 3D array | Asset allocation bounds for tax-deferred accounts (same structure as `taxable`) |
|
|
132
|
+
| `tax-free` | 3D array | Asset allocation bounds for tax-free accounts (same structure as `taxable`) |
|
|
133
|
+
|
|
134
|
+
#### For `type = "individual"` or `"spouses"`:
|
|
135
|
+
| Parameter | Type | Description |
|
|
136
|
+
|-----------|------|-------------|
|
|
137
|
+
| `generic` | 3D array | Generic asset allocation bounds. Structure: `[[[initial_stocks, initial_bonds, initial_fixed, initial_real_estate], [final_stocks, final_bonds, final_fixed, final_real_estate]], ...]` for each individual. For single individuals, only one pair is needed |
|
|
138
|
+
|
|
139
|
+
**Note:** All allocation values are percentages that should sum to 100 for each time point. The four asset classes are: stocks, bonds, fixed assets, and real estate.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## [optimization_parameters]
|
|
144
|
+
|
|
145
|
+
Parameters controlling the optimization objective and spending profile.
|
|
146
|
+
|
|
147
|
+
| Parameter | Type | Description |
|
|
148
|
+
|-----------|------|-------------|
|
|
149
|
+
| `spending_profile` | string | Type of spending profile. Valid values: `"flat"`, `"smile"` |
|
|
150
|
+
| `surviving_spouse_spending_percent` | integer | Percentage of spending amount for the surviving spouse (0-100). Default is `60` |
|
|
151
|
+
| `objective` | string | Optimization objective. Valid values: `"maxSpending"`, `"maxBequest"` |
|
|
152
|
+
|
|
153
|
+
### Conditional Parameters for `spending_profile = "smile"`:
|
|
154
|
+
| Parameter | Type | Description |
|
|
155
|
+
|-----------|------|-------------|
|
|
156
|
+
| `smile_dip` | integer | Percentage to decrease spending during the "slow-go" years (0-100). Default is `15` |
|
|
157
|
+
| `smile_increase` | integer | Percentage to increase (or decrease if negative) spending over the time span (-100 to 100). Default is `12` |
|
|
158
|
+
| `smile_delay` | integer | Number of years from the start before spending begins to decrease (0 to plan duration - 2). Default is `0` |
|
|
159
|
+
|
|
160
|
+
**Note:** The "smile" profile creates a spending pattern that starts high, decreases during middle years, and increases again later in retirement.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## [solver_options]
|
|
165
|
+
|
|
166
|
+
Options controlling the optimization solver and constraints.
|
|
167
|
+
|
|
168
|
+
| Parameter | Type | Description | Default |
|
|
169
|
+
|-----------|------|-------------|---------|
|
|
170
|
+
| `absTol` | float | *(Advanced)* Absolute convergence tolerance for the self-consistent loop objective. | `20` |
|
|
171
|
+
| `amoConstraints` | boolean | *(Advanced)* Whether to use at-most-one (AMO) constraints in the optimization. | `true` |
|
|
172
|
+
| `amoRoth` | boolean | *(Advanced)* Whether to enforce at-most-one (AMO) constraints preventing simultaneous Roth conversions and tax-free withdrawals. | `true` |
|
|
173
|
+
| `amoSurplus` | boolean | *(Advanced)* Whether to enforce XOR constraints preventing simultaneous surplus deposits and withdrawals from taxable or tax-free accounts. | `true` |
|
|
174
|
+
| `bequest` | float | Target bequest value in today's dollars (in `units`). Used when `objective = "maxSpending"`. | `1` (if omitted with `maxSpending`) |
|
|
175
|
+
| `bigMirmaa` | float | *(Advanced)* Big-M value for Medicare IRMAA bracket constraints (used when `withMedicare = "optimize"`). Should exceed any plausible aggregate MAGI. | `5e7` |
|
|
176
|
+
| `bigMamo` | float | *(Advanced)* Big-M value for at-mot-one (AMO) constraints (mutually exclusive operations). Should exceed any individual withdrawal, conversion, or surplus deposit. | `5e7` |
|
|
177
|
+
| `gap` | float | *(Advanced)* Relative MILP gap used by solvers and to scale convergence tolerances. | `1e-4` (default); if `withMedicare = "optimize"` and unset, set to `1e-3` (or `1e-2` when `maxRothConversion <= 15`) |
|
|
178
|
+
| `maxIter` | integer | *(Advanced)* Maximum number of iterations for the self-consistent loop. Must be at least 1. | `29` |
|
|
179
|
+
| `maxRothConversion` | float or string | Maximum annual Roth conversion amount (in `units`). Use `"file"` to take per-year limits from time lists; omit for no cap (except last year). | No cap unless provided |
|
|
180
|
+
| `maxTime` | float | *(Advanced)* Solver time limit in seconds. | `900` |
|
|
181
|
+
| `netSpending` | float | Target net spending amount in today's dollars (in `units`). Used when `objective = "maxBequest"`. | Required for `maxBequest` |
|
|
182
|
+
| `noLateSurplus` | boolean | Disallow surplus deposits in the final two years of the plan. | `false` |
|
|
183
|
+
| `noRothConversions` | string | Name of individual for whom Roth conversions are disabled, or `"None"` to allow conversions for all. | `"None"` |
|
|
184
|
+
| `oppCostX` | float | *(Advanced)* Opportunity cost applied to Roth conversions (percent). | `0` |
|
|
185
|
+
| `previousMAGIs` | array | *(Advanced)* Two-element list of prior-year MAGI values (in `units`) for Medicare calculations. | `[0, 0]` |
|
|
186
|
+
| `relTol` | float | *(Advanced)* Relative convergence tolerance for the self-consistent loop objective. | `max(1e-6, gap / 300)` |
|
|
187
|
+
| `solver` | string | Solver to use for optimization. Valid values: `"HiGHS"`, `"PuLP/CBC"`, `"PuLP/HiGHS"`, `"MOSEK"`. | `"HiGHS"` |
|
|
188
|
+
| `spendingSlack` | integer | Percentage allowed to deviate from the spending profile (0-50). | `0` |
|
|
189
|
+
| `startRothConversions` | integer | Year when Roth conversions can begin (clamped to the current year). | Current year |
|
|
190
|
+
| `swapRothConverters` | integer | *(Advanced)* For plans involvng spouses, only allow one spouse to perform Roth conversions per year. The year provided determines a transition year when roles are swapped. The sign selects who converts first: positive means person 1 can convert first and person 2 any time after; negative year means person 2 before and person 1 after. This option overrides the `noRothConversions` option. | `0` |
|
|
191
|
+
| `units` | string | Units for amounts. Valid values: `"1"` (dollars), `"k"` (thousands), `"M"` (millions). | `"k"` |
|
|
192
|
+
| `verbose` | boolean | Enable solver verbosity/output where supported. | `false` |
|
|
193
|
+
| `withMedicare` | string | Medicare IRMAA handling. Valid values: `"None"`, `"loop"`, `"optimize"` (expert). | `"loop"` |
|
|
194
|
+
| `withSCLoop` | boolean | Whether to use the self-consistent loop for solving. | `true` |
|
|
195
|
+
|
|
196
|
+
**Note:** The solver options dictionary is passed directly to the optimization routine. Only the options listed above are validated; other options may be accepted but are not documented here.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## [results]
|
|
201
|
+
|
|
202
|
+
Parameters controlling result display and output.
|
|
203
|
+
|
|
204
|
+
| Parameter | Type | Description |
|
|
205
|
+
|-----------|------|-------------|
|
|
206
|
+
| `default_plots` | string | Default plot display mode. Valid values: `"nominal"` (nominal dollars), `"today"` (today's dollars) |
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Notes on Data Types
|
|
211
|
+
|
|
212
|
+
- **Floats**: All monetary amounts are typically in thousands of dollars unless otherwise specified
|
|
213
|
+
- **Integers**: Used for years, ages, and counts
|
|
214
|
+
- **Booleans**: `true` or `false` in TOML
|
|
215
|
+
- **ISO Dates**: Format `"YYYY-MM-DD"` (e.g., `"1967-01-15"`)
|
|
216
|
+
- **Lists**: Arrays in TOML, e.g., `[1, 2, 3]` or `["Name1", "Name2"]`
|
|
217
|
+
- **3D Arrays**: Nested arrays, e.g., `[[[60, 40, 0, 0], [70, 30, 0, 0]]]`
|
|
218
|
+
|
|
219
|
+
## Example TOML Structure
|
|
220
|
+
|
|
221
|
+
```toml
|
|
222
|
+
case_name = "example"
|
|
223
|
+
description = "Example case description"
|
|
224
|
+
|
|
225
|
+
[basic_info]
|
|
226
|
+
status = "married"
|
|
227
|
+
names = ["Person1", "Person2"]
|
|
228
|
+
date_of_birth = ["1965-01-15", "1967-03-20"]
|
|
229
|
+
life_expectancy = [89, 92]
|
|
230
|
+
start_date = "2026-01-01"
|
|
231
|
+
|
|
232
|
+
[savings_assets]
|
|
233
|
+
taxable_savings_balances = [100.0, 50.0]
|
|
234
|
+
tax_deferred_savings_balances = [500.0, 300.0]
|
|
235
|
+
tax_free_savings_balances = [200.0, 150.0]
|
|
236
|
+
beneficiary_fractions = [1.0, 1.0, 1.0]
|
|
237
|
+
spousal_surplus_deposit_fraction = 0.5
|
|
238
|
+
|
|
239
|
+
[household_financial_profile]
|
|
240
|
+
HFP_file_name = "HFP_example.xlsx"
|
|
241
|
+
|
|
242
|
+
[fixed_income]
|
|
243
|
+
pension_monthly_amounts = [0, 0]
|
|
244
|
+
pension_ages = [65.0, 65.0]
|
|
245
|
+
pension_indexed = [false, false]
|
|
246
|
+
social_security_pia_amounts = [2360, 1642]
|
|
247
|
+
social_security_ages = [70.0, 67.0]
|
|
248
|
+
|
|
249
|
+
[rates_selection]
|
|
250
|
+
heirs_rate_on_tax_deferred_estate = 30.0
|
|
251
|
+
dividend_rate = 1.8
|
|
252
|
+
obbba_expiration_year = 2032
|
|
253
|
+
method = "historical average"
|
|
254
|
+
from = 1969
|
|
255
|
+
to = 2002
|
|
256
|
+
|
|
257
|
+
[asset_allocation]
|
|
258
|
+
interpolation_method = "s-curve"
|
|
259
|
+
interpolation_center = 15.0
|
|
260
|
+
interpolation_width = 5.0
|
|
261
|
+
type = "individual"
|
|
262
|
+
generic = [[[60, 40, 0, 0], [70, 30, 0, 0]], [[60, 40, 0, 0], [80, 20, 0, 0]]]
|
|
263
|
+
|
|
264
|
+
[optimization_parameters]
|
|
265
|
+
spending_profile = "smile"
|
|
266
|
+
surviving_spouse_spending_percent = 60
|
|
267
|
+
smile_dip = 15
|
|
268
|
+
smile_increase = 12
|
|
269
|
+
smile_delay = 0
|
|
270
|
+
objective = "maxSpending"
|
|
271
|
+
|
|
272
|
+
[solver_options]
|
|
273
|
+
maxRothConversion = 100
|
|
274
|
+
noRothConversions = "None"
|
|
275
|
+
startRothConversions = 2025
|
|
276
|
+
withMedicare = "loop"
|
|
277
|
+
bequest = 500
|
|
278
|
+
solver = "HiGHS"
|
|
279
|
+
spendingSlack = 0
|
|
280
|
+
amoRoth = true
|
|
281
|
+
amoSurplus = true
|
|
282
|
+
withSCLoop = true
|
|
283
|
+
maxIter = 29
|
|
284
|
+
maxTime = 900
|
|
285
|
+
|
|
286
|
+
[results]
|
|
287
|
+
default_plots = "nominal"
|
|
288
|
+
```
|
|
289
|
+
|