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.
Files changed (246) hide show
  1. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/.github/workflows/github-actions-runtests.yml +1 -1
  2. owlplanner-2026.1.26/.gitignore +91 -0
  3. owlplanner-2026.1.26/.streamlit/config.toml +3 -0
  4. owlplanner-2026.1.26/AUTHORS +15 -0
  5. owlplanner-2026.1.26/Adamodar_Rates_2026.xlsx +0 -0
  6. owlplanner-2026.1.26/INSTALL.md +132 -0
  7. owlplanner-2026.1.26/PARAMETERS.md +289 -0
  8. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/PKG-INFO +50 -158
  9. owlplanner-2026.1.26/README.md +96 -0
  10. owlplanner-2026.1.26/RELEASE_NOTES.md +229 -0
  11. owlplanner-2026.1.26/USER_GUIDE.md +279 -0
  12. owlplanner-2026.1.26/awi.txt +75 -0
  13. owlplanner-2026.1.26/case_test.toml +69 -0
  14. owlplanner-2026.1.26/convert_rates.py +58 -0
  15. owlplanner-2026.1.26/docker/buildContainers.sh +8 -0
  16. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/docker/buildPackage.cmd +3 -0
  17. owlplanner-2026.1.26/docker/buildPackage.sh +10 -0
  18. owlplanner-2026.1.26/docs/examples/example-1.html +1313 -0
  19. owlplanner-2026.1.26/docs/index.html +631 -0
  20. owlplanner-2026.1.26/docs/install-uv.html +680 -0
  21. owlplanner-2026.1.26/docs/installation.html +649 -0
  22. owlplanner-2026.1.26/docs/papers +1 -0
  23. owlplanner-2026.1.26/docs/search.json +191 -0
  24. owlplanner-2026.1.26/docs/site_libs/bootstrap/bootstrap-45a48b56c8ad2523a9a31c69be39928e.min.css +12 -0
  25. owlplanner-2026.1.26/docs/site_libs/bootstrap/bootstrap-icons.css +2106 -0
  26. owlplanner-2026.1.26/docs/site_libs/bootstrap/bootstrap-icons.woff +0 -0
  27. owlplanner-2026.1.26/docs/site_libs/bootstrap/bootstrap.min.js +7 -0
  28. owlplanner-2026.1.26/docs/site_libs/clipboard/clipboard.min.js +7 -0
  29. owlplanner-2026.1.26/docs/site_libs/quarto-html/anchor.min.js +9 -0
  30. owlplanner-2026.1.26/docs/site_libs/quarto-html/axe/axe-check.js +145 -0
  31. owlplanner-2026.1.26/docs/site_libs/quarto-html/popper.min.js +6 -0
  32. owlplanner-2026.1.26/docs/site_libs/quarto-html/quarto-syntax-highlighting-587c61ba64f3a5504c4d52d930310e48.css +236 -0
  33. owlplanner-2026.1.26/docs/site_libs/quarto-html/quarto.js +847 -0
  34. owlplanner-2026.1.26/docs/site_libs/quarto-html/tabsets/tabsets.js +95 -0
  35. owlplanner-2026.1.26/docs/site_libs/quarto-html/tippy.css +1 -0
  36. owlplanner-2026.1.26/docs/site_libs/quarto-html/tippy.umd.min.js +2 -0
  37. owlplanner-2026.1.26/docs/site_libs/quarto-nav/headroom.min.js +7 -0
  38. owlplanner-2026.1.26/docs/site_libs/quarto-nav/quarto-nav.js +325 -0
  39. owlplanner-2026.1.26/docs/site_libs/quarto-search/autocomplete.umd.js +3 -0
  40. owlplanner-2026.1.26/docs/site_libs/quarto-search/fuse.min.js +9 -0
  41. owlplanner-2026.1.26/docs/site_libs/quarto-search/quarto-search.js +1290 -0
  42. owlplanner-2026.1.26/docs/users_guide.html +719 -0
  43. owlplanner-2026.1.26/examples/Case_drawdowncalc-comparison-1.toml +57 -0
  44. owlplanner-2026.1.26/examples/Case_jack+jill.toml +62 -0
  45. owlplanner-2026.1.26/examples/Case_joe.toml +55 -0
  46. owlplanner-2026.1.26/examples/Case_john+sally.toml +59 -0
  47. owlplanner-2026.1.26/examples/Case_jon+jane.toml +60 -0
  48. owlplanner-2026.1.26/examples/Case_kim+sam-bequest.toml +63 -0
  49. owlplanner-2026.1.26/examples/Case_kim+sam-spending.toml +63 -0
  50. owlplanner-2026.1.26/examples/HFP_jack+jill.xlsx +0 -0
  51. owlplanner-2026.1.26/examples/HFP_jack+jill_house.xlsx +0 -0
  52. owlplanner-2026.1.26/examples/HFP_joe.xlsx +0 -0
  53. owlplanner-2026.1.26/examples/HFP_john+sally.xlsx +0 -0
  54. owlplanner-2026.1.26/examples/HFP_jon+jane.xlsx +0 -0
  55. owlplanner-2026.1.26/examples/HFP_kim+sam.xlsx +0 -0
  56. owlplanner-2026.1.26/examples/HFP_template.xlsx +0 -0
  57. owlplanner-2026.1.26/iteration_data.csv +32 -0
  58. owlplanner-2026.1.26/iteration_data_2.csv +57 -0
  59. owlplanner-2026.1.26/myrates.csv +3 -0
  60. owlplanner-2026.1.26/myrates.xlsx +0 -0
  61. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/notebooks/john+sally.ipynb +2 -2
  62. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/notebooks/kim+sam.ipynb +2 -2
  63. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/notebooks/template.ipynb +2 -1
  64. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/notebooks/tutorial_1.ipynb +2 -1
  65. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/notebooks/tutorial_2.ipynb +2 -1
  66. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/notebooks/tutorial_3.ipynb +2 -1
  67. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/owlplanner.cmd +1 -1
  68. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/owl.pdf +0 -0
  69. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/owl.tex +320 -166
  70. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/pyproject.toml +13 -0
  71. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/pytest.ini +3 -0
  72. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/requirements.txt +6 -5
  73. owlplanner-2026.1.26/site-src/.gitignore +2 -0
  74. owlplanner-2026.1.26/site-src/README.md +19 -0
  75. owlplanner-2026.1.26/site-src/_quarto.yml +26 -0
  76. owlplanner-2026.1.26/site-src/assets/owl.png +0 -0
  77. owlplanner-2026.1.26/site-src/examples/example-1.qmd +252 -0
  78. owlplanner-2026.1.26/site-src/examples/workbook_jack & jill - tutorial.xlsx +0 -0
  79. owlplanner-2025.12.5/README.md → owlplanner-2026.1.26/site-src/index.qmd +47 -82
  80. owlplanner-2026.1.26/site-src/install-uv.qmd +108 -0
  81. owlplanner-2026.1.26/site-src/installation.qmd +136 -0
  82. owlplanner-2025.12.5/USER_GUIDE.md → owlplanner-2026.1.26/site-src/users_guide.qmd +28 -15
  83. owlplanner-2026.1.26/src/owlplanner/In Discussion #58, the case of Kim and Sam.md +307 -0
  84. owlplanner-2026.1.26/src/owlplanner/__init__.py +27 -0
  85. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/src/owlplanner/abcapi.py +24 -23
  86. owlplanner-2026.1.26/src/owlplanner/cli/README.md +50 -0
  87. owlplanner-2026.1.26/src/owlplanner/cli/_main.py +52 -0
  88. owlplanner-2026.1.26/src/owlplanner/cli/cli_logging.py +56 -0
  89. owlplanner-2026.1.26/src/owlplanner/cli/cmd_list.py +83 -0
  90. owlplanner-2026.1.26/src/owlplanner/cli/cmd_run.py +86 -0
  91. owlplanner-2026.1.26/src/owlplanner/config.py +498 -0
  92. owlplanner-2026.1.26/src/owlplanner/data/__init__.py +21 -0
  93. owlplanner-2026.1.26/src/owlplanner/data/awi.csv +75 -0
  94. owlplanner-2026.1.26/src/owlplanner/data/bendpoints.csv +49 -0
  95. owlplanner-2026.1.26/src/owlplanner/data/newawi.csv +75 -0
  96. owlplanner-2026.1.26/src/owlplanner/data/rates.csv +99 -0
  97. owlplanner-2026.1.26/src/owlplanner/debts.py +315 -0
  98. owlplanner-2026.1.26/src/owlplanner/fixedassets.py +288 -0
  99. owlplanner-2026.1.26/src/owlplanner/mylogging.py +216 -0
  100. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/src/owlplanner/plan.py +1044 -332
  101. owlplanner-2026.1.26/src/owlplanner/plotting/__init__.py +25 -0
  102. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/src/owlplanner/plotting/base.py +17 -3
  103. owlplanner-2026.1.26/src/owlplanner/plotting/factory.py +50 -0
  104. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/src/owlplanner/plotting/matplotlib_backend.py +30 -7
  105. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/src/owlplanner/plotting/plotly_backend.py +33 -10
  106. owlplanner-2026.1.26/src/owlplanner/progress.py +81 -0
  107. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/src/owlplanner/rates.py +366 -361
  108. owlplanner-2026.1.26/src/owlplanner/socialsecurity.py +209 -0
  109. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/src/owlplanner/tax2026.py +170 -57
  110. owlplanner-2026.1.26/src/owlplanner/timelists.py +406 -0
  111. owlplanner-2026.1.26/src/owlplanner/utils.py +302 -0
  112. owlplanner-2026.1.26/src/owlplanner/version.py +20 -0
  113. owlplanner-2026.1.26/tests/test_abcapi_coverage.py +305 -0
  114. owlplanner-2026.1.26/tests/test_config_coverage.py +340 -0
  115. owlplanner-2026.1.26/tests/test_debts.py +447 -0
  116. owlplanner-2026.1.26/tests/test_fixedassets.py +746 -0
  117. owlplanner-2026.1.26/tests/test_historical.py +66 -0
  118. owlplanner-2026.1.26/tests/test_logger.py +49 -0
  119. owlplanner-2026.1.26/tests/test_ltcg.py +45 -0
  120. owlplanner-2026.1.26/tests/test_mc.py +66 -0
  121. owlplanner-2026.1.26/tests/test_mylogging_coverage.py +287 -0
  122. owlplanner-2026.1.26/tests/test_plan_edge_cases.py +426 -0
  123. owlplanner-2026.1.26/tests/test_rates.py +514 -0
  124. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/tests/test_regressions.py +61 -32
  125. owlplanner-2026.1.26/tests/test_repro.py +250 -0
  126. owlplanner-2026.1.26/tests/test_socsec.py +100 -0
  127. owlplanner-2026.1.26/tests/test_summary.py +271 -0
  128. owlplanner-2026.1.26/tests/test_timelists.py +410 -0
  129. owlplanner-2026.1.26/tests/test_timelists_coverage.py +364 -0
  130. owlplanner-2026.1.26/tests/test_toml_cases.py +168 -0
  131. owlplanner-2026.1.26/tests/test_ui_asset_allocation.py +36 -0
  132. owlplanner-2026.1.26/tests/test_ui_compare_summaries.py +40 -0
  133. owlplanner-2026.1.26/tests/test_ui_sskeys.py +45 -0
  134. owlplanner-2026.1.26/tests/test_units.py +31 -0
  135. owlplanner-2026.1.26/tests/test_utils_coverage.py +283 -0
  136. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/About_Owl.py +42 -12
  137. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/Asset_Allocation.py +37 -10
  138. owlplanner-2026.1.26/ui/Create_Case.py +226 -0
  139. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/Documentation.py +330 -138
  140. owlplanner-2026.1.26/ui/Fixed_Income.py +200 -0
  141. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/Graphs.py +23 -1
  142. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/Historical_Range.py +24 -4
  143. owlplanner-2026.1.26/ui/Household_Financial_Profile.py +303 -0
  144. owlplanner-2026.1.26/ui/Logs.py +113 -0
  145. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/Monte_Carlo.py +23 -1
  146. owlplanner-2026.1.26/ui/Optimization_Parameters.py +219 -0
  147. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/Output_Files.py +34 -14
  148. owlplanner-2026.1.26/ui/Parameters_Reference.py +37 -0
  149. owlplanner-2026.1.26/ui/Quick_Start.py +107 -0
  150. owlplanner-2026.1.26/ui/Rates_Selection.py +313 -0
  151. owlplanner-2026.1.26/ui/Savings_Assets.py +106 -0
  152. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/Settings.py +28 -6
  153. owlplanner-2026.1.26/ui/Worksheets.py +41 -0
  154. owlplanner-2026.1.26/ui/__init__.py +21 -0
  155. owlplanner-2026.1.26/ui/case_progress.py +272 -0
  156. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/main.py +27 -3
  157. owlplanner-2026.1.26/ui/owl.png +0 -0
  158. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/owlbridge.py +350 -75
  159. owlplanner-2026.1.26/ui/progress.py +46 -0
  160. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/sskeys.py +162 -47
  161. owlplanner-2026.1.26/ui/tomlexamples.py +105 -0
  162. owlplanner-2025.12.5/.gitignore +0 -10
  163. owlplanner-2025.12.5/.streamlit/config.toml +0 -3
  164. owlplanner-2025.12.5/INSTALL.md +0 -76
  165. owlplanner-2025.12.5/RELEASE_NOTES.md +0 -43
  166. owlplanner-2025.12.5/examples/case_drawdowncalc-comparison-1.toml +0 -58
  167. owlplanner-2025.12.5/examples/case_jack+jill.toml +0 -58
  168. owlplanner-2025.12.5/examples/case_joe.toml +0 -55
  169. owlplanner-2025.12.5/examples/case_john+sally.toml +0 -54
  170. owlplanner-2025.12.5/examples/case_jon+jane.toml +0 -57
  171. owlplanner-2025.12.5/examples/case_kim+sam-bequest.toml +0 -57
  172. owlplanner-2025.12.5/examples/case_kim+sam-spending.toml +0 -57
  173. owlplanner-2025.12.5/examples/jack+jill.xlsx +0 -0
  174. owlplanner-2025.12.5/examples/joe.xlsx +0 -0
  175. owlplanner-2025.12.5/examples/john+sally.xlsx +0 -0
  176. owlplanner-2025.12.5/examples/jon+jane.xlsx +0 -0
  177. owlplanner-2025.12.5/examples/kim+sam.xlsx +0 -0
  178. owlplanner-2025.12.5/examples/template.xlsx +0 -0
  179. owlplanner-2025.12.5/examples/ttt.toml +0 -58
  180. owlplanner-2025.12.5/src/owlplanner/__init__.py +0 -8
  181. owlplanner-2025.12.5/src/owlplanner/config.py +0 -319
  182. owlplanner-2025.12.5/src/owlplanner/data/__init__.py +0 -0
  183. owlplanner-2025.12.5/src/owlplanner/data/rates.csv +0 -98
  184. owlplanner-2025.12.5/src/owlplanner/mylogging.py +0 -84
  185. owlplanner-2025.12.5/src/owlplanner/plotting/__init__.py +0 -12
  186. owlplanner-2025.12.5/src/owlplanner/plotting/factory.py +0 -37
  187. owlplanner-2025.12.5/src/owlplanner/progress.py +0 -24
  188. owlplanner-2025.12.5/src/owlplanner/socialsecurity.py +0 -89
  189. owlplanner-2025.12.5/src/owlplanner/tax2025.py +0 -339
  190. owlplanner-2025.12.5/src/owlplanner/timelists.py +0 -122
  191. owlplanner-2025.12.5/src/owlplanner/utils.py +0 -103
  192. owlplanner-2025.12.5/src/owlplanner/version.py +0 -1
  193. owlplanner-2025.12.5/tests/test_logger.py +0 -21
  194. owlplanner-2025.12.5/tests/test_repro.py +0 -126
  195. owlplanner-2025.12.5/tests/test_socsec.py +0 -72
  196. owlplanner-2025.12.5/tests/test_toml_cases.py +0 -52
  197. owlplanner-2025.12.5/tests/test_ui_asset_allocation.py +0 -14
  198. owlplanner-2025.12.5/tests/test_ui_compare_summaries.py +0 -18
  199. owlplanner-2025.12.5/tests/test_ui_sskeys.py +0 -24
  200. owlplanner-2025.12.5/tests/test_units.py +0 -11
  201. owlplanner-2025.12.5/ui/AI +0 -48
  202. owlplanner-2025.12.5/ui/Create_Case.py +0 -137
  203. owlplanner-2025.12.5/ui/Current_Assets.py +0 -79
  204. owlplanner-2025.12.5/ui/Fixed_Income.py +0 -94
  205. owlplanner-2025.12.5/ui/Logs.py +0 -14
  206. owlplanner-2025.12.5/ui/Optimization_Parameters.py +0 -153
  207. owlplanner-2025.12.5/ui/Quick_Start.py +0 -86
  208. owlplanner-2025.12.5/ui/Rates_Selection.py +0 -243
  209. owlplanner-2025.12.5/ui/Wages_and_Contributions.py +0 -91
  210. owlplanner-2025.12.5/ui/Worksheets.py +0 -19
  211. owlplanner-2025.12.5/ui/__init__.py +0 -0
  212. owlplanner-2025.12.5/ui/progress.py +0 -29
  213. owlplanner-2025.12.5/ui/tomlexamples.py +0 -31
  214. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/.devcontainer/devcontainer.json +0 -0
  215. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/.flake8 +0 -0
  216. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/.gitattributes +0 -0
  217. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/.streamlit/fullconfig.toml +0 -0
  218. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/LICENSE +0 -0
  219. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/docker/Dockerfile.bare +0 -0
  220. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/docker/Dockerfile.static +0 -0
  221. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/docker/README.md +0 -0
  222. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/docker/buildContainers.cmd +0 -0
  223. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/docker/buildentrypoint.sh +0 -0
  224. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/docker/docker-compose.yml +0 -0
  225. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/docker/runentrypoint.sh +0 -0
  226. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/owlplanner.sh +0 -0
  227. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/AD-taxDef.png +0 -0
  228. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/AD-taxFree.png +0 -0
  229. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/AD-taxable.png +0 -0
  230. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/Hist_Bequest.png +0 -0
  231. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/Hist_Spending.png +0 -0
  232. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/MC-tutorial2a.png +0 -0
  233. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/MC-tutorial2b.png +0 -0
  234. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/OwlUI.png +0 -0
  235. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/allocations.png +0 -0
  236. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/owl.png +0 -0
  237. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/piecewiseConstant.png +0 -0
  238. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/profile.png +0 -0
  239. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/ratesCorrelations.png +0 -0
  240. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/ratesPlot.png +0 -0
  241. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/savingsPlot.png +0 -0
  242. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/sourcesPlot.png +0 -0
  243. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/spendingPlot.png +0 -0
  244. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/taxIncomePlot.png +0 -0
  245. {owlplanner-2025.12.5/docs → owlplanner-2026.1.26/papers}/images/taxesPlot.png +0 -0
  246. {owlplanner-2025.12.5 → owlplanner-2026.1.26}/ui/README.md +0 -0
@@ -12,7 +12,7 @@ jobs:
12
12
  strategy:
13
13
  fail-fast: false
14
14
  matrix:
15
- python-version: ["3.9", "3.10", "3.13"]
15
+ python-version: ["3.10", "3.13", "3.14"]
16
16
 
17
17
  steps:
18
18
  - uses: actions/checkout@v4
@@ -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,3 @@
1
+ [theme]
2
+ base = "dark"
3
+ # dataframeHeaderBackgroundColor = "#692f24"
@@ -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
+
@@ -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
+