owlplanner 2025.12.3__tar.gz → 2025.12.20__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 (207) hide show
  1. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/.gitignore +1 -0
  2. owlplanner-2025.12.20/INSTALL.md +132 -0
  3. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/PKG-INFO +41 -157
  4. owlplanner-2025.12.20/README.md +91 -0
  5. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/RELEASE_NOTES.md +33 -0
  6. owlplanner-2025.12.20/awi.txt +75 -0
  7. owlplanner-2025.12.20/docker/buildPackage.cmd +10 -0
  8. owlplanner-2025.12.20/docker/buildPackage.sh +10 -0
  9. owlplanner-2025.12.20/docs/examples/example-1.html +1313 -0
  10. owlplanner-2025.12.20/docs/index.html +631 -0
  11. owlplanner-2025.12.20/docs/install-uv.html +680 -0
  12. owlplanner-2025.12.20/docs/installation.html +649 -0
  13. owlplanner-2025.12.20/docs/search.json +191 -0
  14. owlplanner-2025.12.20/docs/site_libs/bootstrap/bootstrap-45a48b56c8ad2523a9a31c69be39928e.min.css +12 -0
  15. owlplanner-2025.12.20/docs/site_libs/bootstrap/bootstrap-icons.css +2106 -0
  16. owlplanner-2025.12.20/docs/site_libs/bootstrap/bootstrap-icons.woff +0 -0
  17. owlplanner-2025.12.20/docs/site_libs/bootstrap/bootstrap.min.js +7 -0
  18. owlplanner-2025.12.20/docs/site_libs/clipboard/clipboard.min.js +7 -0
  19. owlplanner-2025.12.20/docs/site_libs/quarto-html/anchor.min.js +9 -0
  20. owlplanner-2025.12.20/docs/site_libs/quarto-html/axe/axe-check.js +145 -0
  21. owlplanner-2025.12.20/docs/site_libs/quarto-html/popper.min.js +6 -0
  22. owlplanner-2025.12.20/docs/site_libs/quarto-html/quarto-syntax-highlighting-587c61ba64f3a5504c4d52d930310e48.css +236 -0
  23. owlplanner-2025.12.20/docs/site_libs/quarto-html/quarto.js +847 -0
  24. owlplanner-2025.12.20/docs/site_libs/quarto-html/tabsets/tabsets.js +95 -0
  25. owlplanner-2025.12.20/docs/site_libs/quarto-html/tippy.css +1 -0
  26. owlplanner-2025.12.20/docs/site_libs/quarto-html/tippy.umd.min.js +2 -0
  27. owlplanner-2025.12.20/docs/site_libs/quarto-nav/headroom.min.js +7 -0
  28. owlplanner-2025.12.20/docs/site_libs/quarto-nav/quarto-nav.js +325 -0
  29. owlplanner-2025.12.20/docs/site_libs/quarto-search/autocomplete.umd.js +3 -0
  30. owlplanner-2025.12.20/docs/site_libs/quarto-search/fuse.min.js +9 -0
  31. owlplanner-2025.12.20/docs/site_libs/quarto-search/quarto-search.js +1290 -0
  32. owlplanner-2025.12.20/docs/users_guide.html +719 -0
  33. owlplanner-2025.12.3/examples/case_jack+jill.toml → owlplanner-2025.12.20/examples/Case_jack+jill.toml +4 -5
  34. owlplanner-2025.12.3/examples/case_joe.toml → owlplanner-2025.12.20/examples/Case_joe.toml +3 -4
  35. owlplanner-2025.12.3/examples/case_john+sally.toml → owlplanner-2025.12.20/examples/Case_john+sally.toml +3 -4
  36. owlplanner-2025.12.3/examples/case_jon+jane.toml → owlplanner-2025.12.20/examples/Case_jon+jane.toml +4 -5
  37. owlplanner-2025.12.3/examples/case_kim+sam-bequest.toml → owlplanner-2025.12.20/examples/Case_kim+sam-bequest.toml +3 -4
  38. owlplanner-2025.12.3/examples/case_kim+sam-spending.toml → owlplanner-2025.12.20/examples/Case_kim+sam-spending.toml +3 -4
  39. owlplanner-2025.12.20/examples/HFP_jack+jill.xlsx +0 -0
  40. owlplanner-2025.12.20/examples/HFP_jack+jill_house.xlsx +0 -0
  41. owlplanner-2025.12.20/examples/HFP_joe.xlsx +0 -0
  42. owlplanner-2025.12.20/examples/HFP_john+sally.xlsx +0 -0
  43. owlplanner-2025.12.20/examples/HFP_jon+jane.xlsx +0 -0
  44. owlplanner-2025.12.20/examples/HFP_kim+sam.xlsx +0 -0
  45. owlplanner-2025.12.20/examples/HFP_template.xlsx +0 -0
  46. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/examples/case_drawdowncalc-comparison-1.toml +3 -4
  47. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/notebooks/john+sally.ipynb +1 -1
  48. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/notebooks/kim+sam.ipynb +1 -1
  49. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/notebooks/template.ipynb +1 -1
  50. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/notebooks/tutorial_1.ipynb +1 -1
  51. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/notebooks/tutorial_2.ipynb +1 -1
  52. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/notebooks/tutorial_3.ipynb +1 -1
  53. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/owlplanner.cmd +1 -1
  54. owlplanner-2025.12.20/papers/owl.pdf +0 -0
  55. owlplanner-2025.12.20/paste.py +68 -0
  56. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/pyproject.toml +7 -0
  57. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/requirements.txt +4 -4
  58. owlplanner-2025.12.20/site-src/.gitignore +2 -0
  59. owlplanner-2025.12.20/site-src/README.md +19 -0
  60. owlplanner-2025.12.20/site-src/_quarto.yml +26 -0
  61. owlplanner-2025.12.20/site-src/assets/owl.png +0 -0
  62. owlplanner-2025.12.20/site-src/examples/example-1.qmd +252 -0
  63. owlplanner-2025.12.20/site-src/examples/workbook_jack & jill - tutorial.xlsx +0 -0
  64. owlplanner-2025.12.3/README.md → owlplanner-2025.12.20/site-src/index.qmd +46 -81
  65. owlplanner-2025.12.20/site-src/install-uv.qmd +108 -0
  66. owlplanner-2025.12.20/site-src/installation.qmd +136 -0
  67. owlplanner-2025.12.20/site-src/papers/images/AD-taxDef.png +0 -0
  68. owlplanner-2025.12.20/site-src/papers/images/AD-taxFree.png +0 -0
  69. owlplanner-2025.12.20/site-src/papers/images/AD-taxable.png +0 -0
  70. owlplanner-2025.12.20/site-src/papers/images/Hist_Bequest.png +0 -0
  71. owlplanner-2025.12.20/site-src/papers/images/Hist_Spending.png +0 -0
  72. owlplanner-2025.12.20/site-src/papers/images/MC-tutorial2a.png +0 -0
  73. owlplanner-2025.12.20/site-src/papers/images/MC-tutorial2b.png +0 -0
  74. owlplanner-2025.12.20/site-src/papers/images/OwlUI.png +0 -0
  75. owlplanner-2025.12.20/site-src/papers/images/allocations.png +0 -0
  76. owlplanner-2025.12.20/site-src/papers/images/owl.png +0 -0
  77. owlplanner-2025.12.20/site-src/papers/images/piecewiseConstant.png +0 -0
  78. owlplanner-2025.12.20/site-src/papers/images/profile.png +0 -0
  79. owlplanner-2025.12.20/site-src/papers/images/ratesCorrelations.png +0 -0
  80. owlplanner-2025.12.20/site-src/papers/images/ratesPlot.png +0 -0
  81. owlplanner-2025.12.20/site-src/papers/images/savingsPlot.png +0 -0
  82. owlplanner-2025.12.20/site-src/papers/images/sourcesPlot.png +0 -0
  83. owlplanner-2025.12.20/site-src/papers/images/spendingPlot.png +0 -0
  84. owlplanner-2025.12.20/site-src/papers/images/taxIncomePlot.png +0 -0
  85. owlplanner-2025.12.20/site-src/papers/images/taxesPlot.png +0 -0
  86. owlplanner-2025.12.20/site-src/papers/owl.pdf +0 -0
  87. owlplanner-2025.12.20/site-src/papers/owl.tex +1552 -0
  88. owlplanner-2025.12.20/site-src/users_guide.qmd +238 -0
  89. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/src/owlplanner/abcapi.py +6 -6
  90. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/src/owlplanner/config.py +22 -26
  91. owlplanner-2025.12.20/src/owlplanner/data/awi.csv +75 -0
  92. owlplanner-2025.12.20/src/owlplanner/data/bendpoints.csv +49 -0
  93. owlplanner-2025.12.20/src/owlplanner/data/newawi.csv +75 -0
  94. owlplanner-2025.12.20/src/owlplanner/debts.py +287 -0
  95. owlplanner-2025.12.20/src/owlplanner/fixedassets.py +214 -0
  96. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/src/owlplanner/plan.py +324 -55
  97. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/src/owlplanner/plotting/plotly_backend.py +1 -1
  98. owlplanner-2025.12.20/src/owlplanner/progress.py +68 -0
  99. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/src/owlplanner/rates.py +1 -1
  100. owlplanner-2025.12.20/src/owlplanner/socialsecurity.py +200 -0
  101. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/src/owlplanner/tax2025.py +20 -0
  102. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/src/owlplanner/tax2026.py +61 -27
  103. owlplanner-2025.12.20/src/owlplanner/timelists.py +230 -0
  104. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/src/owlplanner/utils.py +25 -1
  105. owlplanner-2025.12.20/src/owlplanner/version.py +1 -0
  106. owlplanner-2025.12.20/tests/test_debts.py +425 -0
  107. owlplanner-2025.12.20/tests/test_fixedassets.py +418 -0
  108. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/tests/test_regressions.py +20 -24
  109. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/tests/test_repro.py +14 -15
  110. owlplanner-2025.12.20/tests/test_socsec.py +78 -0
  111. owlplanner-2025.12.20/tests/test_toml_cases.py +57 -0
  112. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/About_Owl.py +15 -11
  113. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/Asset_Allocation.py +14 -10
  114. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/Create_Case.py +49 -29
  115. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/Documentation.py +125 -49
  116. owlplanner-2025.12.20/ui/Fixed_Income.py +166 -0
  117. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/Graphs.py +1 -1
  118. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/Historical_Range.py +2 -4
  119. owlplanner-2025.12.20/ui/Household_Financial_Profile.py +259 -0
  120. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/Monte_Carlo.py +1 -1
  121. owlplanner-2025.12.20/ui/NewDocumentation.py +987 -0
  122. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/Optimization_Parameters.py +52 -32
  123. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/Output_Files.py +11 -13
  124. owlplanner-2025.12.20/ui/Quick_Start.py +89 -0
  125. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/Rates_Selection.py +72 -53
  126. owlplanner-2025.12.3/ui/Current_Assets.py → owlplanner-2025.12.20/ui/Savings_Assets.py +11 -7
  127. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/Settings.py +6 -6
  128. owlplanner-2025.12.20/ui/case_progress.py +244 -0
  129. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/main.py +6 -3
  130. owlplanner-2025.12.20/ui/owl.png +0 -0
  131. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/owlbridge.py +147 -49
  132. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/sskeys.py +60 -11
  133. owlplanner-2025.12.20/ui/tomlexamples.py +34 -0
  134. owlplanner-2025.12.3/INSTALL.md +0 -76
  135. owlplanner-2025.12.3/examples/jack+jill.xlsx +0 -0
  136. owlplanner-2025.12.3/examples/joe.xlsx +0 -0
  137. owlplanner-2025.12.3/examples/john+sally.xlsx +0 -0
  138. owlplanner-2025.12.3/examples/jon+jane.xlsx +0 -0
  139. owlplanner-2025.12.3/examples/kim+sam.xlsx +0 -0
  140. owlplanner-2025.12.3/examples/template.xlsx +0 -0
  141. owlplanner-2025.12.3/src/owlplanner/progress.py +0 -24
  142. owlplanner-2025.12.3/src/owlplanner/socialsecurity.py +0 -89
  143. owlplanner-2025.12.3/src/owlplanner/timelists.py +0 -122
  144. owlplanner-2025.12.3/src/owlplanner/version.py +0 -1
  145. owlplanner-2025.12.3/tests/test_socsec.py +0 -72
  146. owlplanner-2025.12.3/tests/test_toml_cases.py +0 -52
  147. owlplanner-2025.12.3/ui/Fixed_Income.py +0 -92
  148. owlplanner-2025.12.3/ui/Quick_Start.py +0 -84
  149. owlplanner-2025.12.3/ui/Wages_and_Contributions.py +0 -91
  150. owlplanner-2025.12.3/ui/tomlexamples.py +0 -31
  151. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/.devcontainer/devcontainer.json +0 -0
  152. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/.flake8 +0 -0
  153. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/.gitattributes +0 -0
  154. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/.github/workflows/github-actions-runtests.yml +0 -0
  155. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/.streamlit/config.toml +0 -0
  156. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/.streamlit/fullconfig.toml +0 -0
  157. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/LICENSE +0 -0
  158. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/USER_GUIDE.md +0 -0
  159. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/docker/Dockerfile.bare +0 -0
  160. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/docker/Dockerfile.static +0 -0
  161. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/docker/README.md +0 -0
  162. /owlplanner-2025.12.3/docker/build.cmd → /owlplanner-2025.12.20/docker/buildContainers.cmd +0 -0
  163. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/docker/buildentrypoint.sh +0 -0
  164. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/docker/docker-compose.yml +0 -0
  165. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/docker/runentrypoint.sh +0 -0
  166. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/docs/papers}/owl.pdf +0 -0
  167. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/owlplanner.sh +0 -0
  168. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/AD-taxDef.png +0 -0
  169. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/AD-taxFree.png +0 -0
  170. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/AD-taxable.png +0 -0
  171. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/Hist_Bequest.png +0 -0
  172. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/Hist_Spending.png +0 -0
  173. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/MC-tutorial2a.png +0 -0
  174. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/MC-tutorial2b.png +0 -0
  175. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/OwlUI.png +0 -0
  176. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/allocations.png +0 -0
  177. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/owl.png +0 -0
  178. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/piecewiseConstant.png +0 -0
  179. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/profile.png +0 -0
  180. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/ratesCorrelations.png +0 -0
  181. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/ratesPlot.png +0 -0
  182. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/savingsPlot.png +0 -0
  183. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/sourcesPlot.png +0 -0
  184. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/spendingPlot.png +0 -0
  185. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/taxIncomePlot.png +0 -0
  186. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/images/taxesPlot.png +0 -0
  187. {owlplanner-2025.12.3/docs → owlplanner-2025.12.20/papers}/owl.tex +0 -0
  188. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/pytest.ini +0 -0
  189. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/src/owlplanner/__init__.py +0 -0
  190. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/src/owlplanner/data/__init__.py +0 -0
  191. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/src/owlplanner/data/rates.csv +0 -0
  192. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/src/owlplanner/mylogging.py +0 -0
  193. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/src/owlplanner/plotting/__init__.py +0 -0
  194. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/src/owlplanner/plotting/base.py +0 -0
  195. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/src/owlplanner/plotting/factory.py +0 -0
  196. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/src/owlplanner/plotting/matplotlib_backend.py +0 -0
  197. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/tests/test_logger.py +0 -0
  198. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/tests/test_ui_asset_allocation.py +0 -0
  199. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/tests/test_ui_compare_summaries.py +0 -0
  200. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/tests/test_ui_sskeys.py +0 -0
  201. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/tests/test_units.py +0 -0
  202. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/AI +0 -0
  203. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/Logs.py +0 -0
  204. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/README.md +0 -0
  205. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/Worksheets.py +0 -0
  206. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/__init__.py +0 -0
  207. {owlplanner-2025.12.3 → owlplanner-2025.12.20}/ui/progress.py +0 -0
@@ -8,3 +8,4 @@ dist
8
8
  otherFiles
9
9
  myfiles
10
10
  secrets
11
+ uv.lock
@@ -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
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: owlplanner
3
- Version: 2025.12.3
3
+ Version: 2025.12.20
4
4
  Summary: Owl - Optimal Wealth Lab: Retirement planner with great wisdom
5
5
  Project-URL: HomePage, https://github.com/mdlacasse/owl
6
6
  Project-URL: Repository, https://github.com/mdlacasse/owl
@@ -692,6 +692,7 @@ Classifier: Programming Language :: Python :: 3
692
692
  Classifier: Topic :: Office/Business :: Financial :: Investment
693
693
  Requires-Python: >=3.10
694
694
  Requires-Dist: highspy
695
+ Requires-Dist: jupyter>=1.1.1
695
696
  Requires-Dist: matplotlib
696
697
  Requires-Dist: numpy
697
698
  Requires-Dist: odfpy
@@ -699,6 +700,7 @@ Requires-Dist: openpyxl
699
700
  Requires-Dist: pandas
700
701
  Requires-Dist: plotly>=6.3
701
702
  Requires-Dist: pulp
703
+ Requires-Dist: pyyaml>=6.0.3
702
704
  Requires-Dist: scipy
703
705
  Requires-Dist: seaborn
704
706
  Requires-Dist: streamlit
@@ -733,154 +735,6 @@ Follow these [instructions](docker/README.md) for using this option.
733
735
  - **Self-hosting:** Run Owl locally on your computer using Python code and libraries.
734
736
  Follow these [instructions](INSTALL.md) to install from the source code and self-host on your own computer.
735
737
 
736
- -------------------------------------------------------------------------------------
737
- ## Overview
738
- This package is a modeling framework for exploring the sensitivity of retirement financial decisions.
739
- Strictly speaking, it is not a planning tool, but more an environment for exploring *what if* scenarios.
740
- It provides different realizations of a financial strategy through the rigorous
741
- mathematical optimization of relevant decision variables. Two major objective goals can be set: either
742
- maximize net spending, or after-tax bequest under various constraints.
743
- Look at the *Capabilities* section below for more detail.
744
-
745
- One can certainly have a savings plan, but due to the volatility of financial investments,
746
- it is impossible to have a certain asset earnings plan. This does not mean one cannot make decisions.
747
- These decisions need to be guided with an understanding of the sensitivity of the parameters.
748
- This is exactly where this tool fits in. Given your savings capabilities and spending desires,
749
- it can generate different future realizations of
750
- your strategy under different market assumptions, helping to better understand your financial situation.
751
-
752
- -------------------------------------------------------------------------------------
753
- ## Purpose and vision
754
- One goal of Owl is to provide a free and open-source ecosystem that has cutting-edge optimization capabilities,
755
- allowing for the next generation of Python-literate retirees to experiment with their own financial future
756
- while providing a codebase where they can learn and contribute. At the same time, an intuitive and easy-to-use
757
- user interface based on Streamlit allows a broad set of users to benefit from the application as it only requires basic financial knowledge.
758
-
759
- There are and were
760
- good retirement optimizers in the recent past, but the vast majority of them are either proprietary platforms
761
- collecting your data, or academic papers that share the results without really sharing the details of
762
- the underlying mathematical models.
763
- The algorithms in Owl rely on the open-source HiGHS linear programming solver but they have also been ported and tested on
764
- other platforms such as Mosek and COIN-OR. The complete formulation and
765
- detailed description of the underlying
766
- mathematical model can be found [here](https://github.com/mdlacasse/Owl/blob/main/docs/owl.pdf).
767
-
768
- It is anticipated that most end users will use Owl through the graphical interface
769
- either at [owlplanner.streamlit.app](https://owlplanner.streamlit.app)
770
- or [installed](INSTALL.md) on their own computer.
771
- The underlying Python package can also be used directly through Python scripts or Jupyter Notebooks
772
- as described [here](USER_GUIDE.md).
773
-
774
- Not every retirement decision strategy can be framed as an easy-to-solve optimization problem.
775
- In particular, if one is interested in comparing different withdrawal strategies,
776
- [FI Calc](https://ficalc.app) is an elegant application that addresses this need.
777
- If, however, you also want to optimize spending, bequest, and Roth conversions, with
778
- an approach also considering Medicare and federal income tax over the next few years,
779
- then Owl is definitely a tool that can help guide your decisions.
780
-
781
- --------------------------------------------------------------------------------------
782
- ## Capabilities
783
- Owl can optimize for either maximum net spending under the constraint of a given bequest (which can be zero),
784
- or maximize the after-tax value of a bequest under the constraint of a desired net spending profile,
785
- and under the assumption of a heirs marginal tax rate.
786
- Roth conversions are also considered, subject to an optional maximum conversion amount,
787
- and optimized to suit the goals of the selected objective function.
788
- All calculations are indexed for inflation, which is either provided as a fixed rate,
789
- or through historical values, as are all other rates used for the calculations.
790
- These rates can be used for backtesting different scenarios by choosing
791
- *historical* rates, or by choosing *historical average* rates over a historical year range,
792
- or what I coined "*histochastic*" rates which are
793
- generated using the statistical distribution of observed historical rates.
794
-
795
- Portfolios available for experimenting include assets from the S&P 500, Corporate Bonds Baa, Treasury 10-y Notes,
796
- and cash assets assumed to just follow inflation which is represented by the Consumer Price Index.
797
- Other asset classes can easily be added, but would add complexity while only providing diminishing insights.
798
- Historical data used are from
799
- [Aswath Damodaran](https://pages.stern.nyu.edu/~adamodar/) at the Stern School of Business.
800
- Asset allocations are selected for the duration of the plan, and these can glide linearly
801
- or along a configurable s-curve over the lifespan of the individual.
802
-
803
- Spending profiles are adjusted for inflation, and so are all other indexable quantities. Proflies can be
804
- flat or follow a *smile* curve which is also adjustable through three simple parameters.
805
-
806
- Available rates are from 1928 to last year and can be used to test historical performance.
807
- Fixed rates can also be provided, as well as *histochastic* rates, which are generated using
808
- the statistical characteristics (means and covariance matrix) of
809
- a selected historical year range. Pure *stochastic* rates can also be generated
810
- if the user provides means, volatility (expressed as standard deviation), and optionally
811
- the correlations between the different assets return rates provided as a matrix, or a list of
812
- the off-diagonal elements (see documentation for details).
813
- Average rates calculated over a historical data period can also be chosen.
814
-
815
- Monte Carlo simulations capabilities are included and provide a probability of success and a histogram of
816
- outcomes. These simulations can be used for either determining the probability distribution of the
817
- maximum net spending amount under
818
- the constraint of a desired bequest, or the probability distribution of the maximum
819
- bequest under the constraint of a desired net spending amount. Unlike discrete-event
820
- simulators, Owl uses an optimization algorithm for every new scenario, which results in more
821
- calculations being performed. As a result, the number of cases to be considered should be kept
822
- to a reasonable number. For a few hundred cases, a few minutes of calculations can provide very good estimates
823
- and reliable probability distributions.
824
-
825
- Optimizing each solution is more representative than event-base simulators
826
- in the sense that optimal solutions
827
- will naturally adjust to the return scenarios being considered.
828
- This is more realistic as retirees would certainly re-evaluate
829
- their expectations under severe market drops or gains.
830
- This optimal approach provides a net benefit over event-based simulators,
831
- which maintain a distribution strategy either fixed, or within guardrails for capturing the
832
- retirees' reactions to the market.
833
-
834
- Basic input parameters can be entered through the user interface
835
- while optional additional time series can be read from
836
- an Excel spreadsheet that contains future wages, contributions
837
- to savings accounts, and planned *big-ticket items* such as the purchase of a lake house,
838
- the sale of a boat, large gifts, or inheritance.
839
-
840
- Three types of savings accounts are considered: taxable, tax-deferred, and tax-free,
841
- which are all tracked separately for married individuals. Asset transition to the surviving spouse
842
- is done according to beneficiary fractions for each type of savings account.
843
- Tax status covers married filing jointly and single, depending on the number of individuals reported.
844
-
845
- Maturation rules for Roth contributions and conversions are implemented as constraints
846
- limiting withdrawal amounts to cover Roth account balances for 5 years after the events.
847
- Medicare and IRMAA calculations are performed through a self-consistent loop on cash flow constraints.
848
- They can also be optimized explicitly as an option, but this choice can lead to longer calculations
849
- due to the use of the many additional binary variables required by the formulation.
850
- Future Medicare and IRMAA values are simple projections of current values with the assumed inflation rates.
851
-
852
- Owl has a basic social security calculator that determines the actual benefits based on the individual's
853
- primary insurance amount (PIA), full retirement age (FRA), and claiming age. Both
854
- spousal's benefits and survivor's benefits are calculated for non-complex cases.
855
-
856
- ### Limitations
857
- Owl is work in progress. At the current time:
858
- - Only the US federal income tax is considered (and minimized through the optimization algorithm).
859
- Head of household filing status has not been added but can easily be.
860
- - Required minimum distributions are calculated, but tables for spouses more than 10 years apart are not included.
861
- These cases are detected and will generate an error message.
862
- - Current version has no optimization of asset allocations between individuals and/or types of savings accounts.
863
- If there is interest, that could be added in the future.
864
- - In the current implementation, social securiy is always taxed at 85%, assuming that your taxable income will be larger than 34 k$ (single) or 44 k$ (married filing jointly).
865
- - When Medicare calculations are done through a self-consistent loop,
866
- the Medicare premiums are calculated after an initial solution is generated,
867
- and then a new solution is re-generated with these premiums as a constraint.
868
- In some situations, when the income (MAGI) is near an IRMAA bracket, oscillatory solutions can arise.
869
- While the solutions generated are very close to one another, Owl will pick the smallest solution
870
- for being conservative. While sometimes computationally costly,
871
- a comparison with a full Medicare optimization should always be performed.
872
- - Part D is not included in the IRMAA calculations. Only Part B is taken into account,
873
- which is considerably more significant.
874
- - Future tax brackets are pure speculations derived from the little we know now and projected to the next 30 years.
875
- Your guesses are as good as mine.
876
-
877
- The solution from an optimization algorithm has only two states: feasible and infeasible.
878
- Therefore, unlike event-driven simulators that can tell you that your distribution strategy runs
879
- out of money in year 20, an optimization-based solver can only tell you that a solution does or does not
880
- exist for the plan being considered. Examples of infeasible solutions include requesting a bequeathed
881
- estate value too large for the savings assets to support, even with zero net spending basis,
882
- or maximizing the bequest subject to a net spending basis that is already too large for the savings
883
- assets to support, even with no estate being left.
884
738
 
885
739
  ---------------------------------------------------------------
886
740
  ## Documentation
@@ -892,16 +746,46 @@ assets to support, even with no estate being left.
892
746
  ---------------------------------------------------------------------
893
747
 
894
748
  ## Credits
895
- - Historical rates from [Aswath Damodaran](https://pages.stern.nyu.edu/~adamodar/)
896
- - Image from [freepik](https://freepik.com)
897
- - Optimization solver from [HiGHS](https://highs.dev)
898
- - Streamlit Community Cloud [Streamlit](https://streamlit.io)
899
- - Contributors: Josh (noimjosh@gmail.com) for Docker image code,
900
- kg333 for fixing an error in Docker's instructions,
901
- Dale Seng (sengsational) for great insights and suggestions,
749
+ - Contributors:
902
750
  Robert E. Anderson (NH-RedAnt) for bug fixes and suggestions,
903
751
  Clark Jefcoat (hubcity) for fruitful interactions,
904
- Benjamin Quinn (blquinn) and Gene Wood (gene1wood) for improvements and bug fixes.
752
+ kg333 for fixing an error in Docker's instructions,
753
+ John Leonard (jleonard99) for great suggestions, website, and more to come,
754
+ Benjamin Quinn (blquinn) for improvements and bug fixes,
755
+ Dale Seng (sengsational) for great insights, testing, and suggestions,
756
+ Josh Williams (noimjosh) for Docker image code,
757
+ Gene Wood (gene1wood) for improvements and bug fixes.
758
+ - Greg Grothaus for developing [ssa.tools](https://ssa.tools) and providing an integration with Owl.
759
+ - Owl image is from [freepik](https://freepik.com).
760
+ - Historical rates are from [Aswath Damodaran](https://pages.stern.nyu.edu/~adamodar/).
761
+ - Linear programming optimization solvers are from
762
+ [HiGHS](https://highs.dev) and [PuLP](https://coin-or.github.io/pulp/).
763
+ It can also run on [MOSEK](https://mosek.com) if available on your computer.
764
+ - Owl planner relies on the following [Python](https://python.org) packages:
765
+ - [highspy](https://highs.dev),
766
+ [Matplotlib](https://matplotlib.org),
767
+ [Numpy](https://numpy.org),
768
+ [odfpy](https://https://pypi.org/project/odfpy),
769
+ [openpyxl](https://openpyxl.readthedocs.io),
770
+ [Pandas](https://pandas.pydata.org),
771
+ [Plotly](https://plotly.com),
772
+ [PuLP](https://coin-or.github.io/pulp),
773
+ [Scipy](https://scipy.org),
774
+ [Seaborn](https://seaborn.pydata.org),
775
+ [toml](https://toml.io),
776
+ and [Streamlit](https://streamlit.io) for the front-end.
777
+
778
+ ## Bugs and Feature Requests
779
+ Please submit bugs and feature requests through
780
+ [GitHub](https://github.com/mdlacasse/owl/issues) if you have a GitHub account
781
+ or directly by [email](mailto:martin.d.lacasse@gmail.com).
782
+ Or just drop me a line to report your experience with the tool.
783
+
784
+ ## Privacy
785
+ This app does not store or forward any information. All data entered is lost
786
+ after a session is closed. However, you can choose to download selected parts of your
787
+ own data to your computer before closing the session. These data will be stored strictly on
788
+ your computer and can be used to reproduce a case at a later time.
905
789
 
906
790
  ---------------------------------------------------------------------
907
791
 
@@ -0,0 +1,91 @@
1
+
2
+ # Owl - Optimal Wealth Lab
3
+
4
+ ## A retirement exploration tool based on linear programming
5
+
6
+ <img align=right src="https://github.com/mdlacasse/Owl/blob/main/docs/images/owl.png?raw=true" width="250">
7
+
8
+ -------------------------------------------------------------------------------------
9
+
10
+ ### TL;DR
11
+ Owl is a retirement financial planning tool that uses a linear programming
12
+ optimization algorithm to provide guidance on retirement decisions
13
+ such as contributions, withdrawals, Roth conversions, and more.
14
+ Users can select varying return rates to perform historical back testing,
15
+ stochastic rates for performing Monte Carlo analyses,
16
+ or fixed rates either derived from historical averages, or set by the user.
17
+
18
+ There are three ways to run Owl:
19
+
20
+ - **Streamlit Hub:** Run Owl remotely as hosted on the Streamlit Community Server at
21
+ [owlplanner.streamlit.app](https://owlplanner.streamlit.app).
22
+
23
+ - **Docker Container:** Run Owl locally on your computer using a Docker image.
24
+ Follow these [instructions](docker/README.md) for using this option.
25
+
26
+ - **Self-hosting:** Run Owl locally on your computer using Python code and libraries.
27
+ Follow these [instructions](INSTALL.md) to install from the source code and self-host on your own computer.
28
+
29
+
30
+ ---------------------------------------------------------------
31
+ ## Documentation
32
+
33
+ - Documentation for the app user interface is available from the interface [itself](https://owlplanner.streamlit.app/Documentation).
34
+ - Installation guide and software requirements can be found [here](INSTALL.md).
35
+ - User guide for the underlying Python package as used in a Jupyter notebook can be found [here](USER_GUIDE.md).
36
+
37
+ ---------------------------------------------------------------------
38
+
39
+ ## Credits
40
+ - Contributors:
41
+ Robert E. Anderson (NH-RedAnt) for bug fixes and suggestions,
42
+ Clark Jefcoat (hubcity) for fruitful interactions,
43
+ kg333 for fixing an error in Docker's instructions,
44
+ John Leonard (jleonard99) for great suggestions, website, and more to come,
45
+ Benjamin Quinn (blquinn) for improvements and bug fixes,
46
+ Dale Seng (sengsational) for great insights, testing, and suggestions,
47
+ Josh Williams (noimjosh) for Docker image code,
48
+ Gene Wood (gene1wood) for improvements and bug fixes.
49
+ - Greg Grothaus for developing [ssa.tools](https://ssa.tools) and providing an integration with Owl.
50
+ - Owl image is from [freepik](https://freepik.com).
51
+ - Historical rates are from [Aswath Damodaran](https://pages.stern.nyu.edu/~adamodar/).
52
+ - Linear programming optimization solvers are from
53
+ [HiGHS](https://highs.dev) and [PuLP](https://coin-or.github.io/pulp/).
54
+ It can also run on [MOSEK](https://mosek.com) if available on your computer.
55
+ - Owl planner relies on the following [Python](https://python.org) packages:
56
+ - [highspy](https://highs.dev),
57
+ [Matplotlib](https://matplotlib.org),
58
+ [Numpy](https://numpy.org),
59
+ [odfpy](https://https://pypi.org/project/odfpy),
60
+ [openpyxl](https://openpyxl.readthedocs.io),
61
+ [Pandas](https://pandas.pydata.org),
62
+ [Plotly](https://plotly.com),
63
+ [PuLP](https://coin-or.github.io/pulp),
64
+ [Scipy](https://scipy.org),
65
+ [Seaborn](https://seaborn.pydata.org),
66
+ [toml](https://toml.io),
67
+ and [Streamlit](https://streamlit.io) for the front-end.
68
+
69
+ ## Bugs and Feature Requests
70
+ Please submit bugs and feature requests through
71
+ [GitHub](https://github.com/mdlacasse/owl/issues) if you have a GitHub account
72
+ or directly by [email](mailto:martin.d.lacasse@gmail.com).
73
+ Or just drop me a line to report your experience with the tool.
74
+
75
+ ## Privacy
76
+ This app does not store or forward any information. All data entered is lost
77
+ after a session is closed. However, you can choose to download selected parts of your
78
+ own data to your computer before closing the session. These data will be stored strictly on
79
+ your computer and can be used to reproduce a case at a later time.
80
+
81
+ ---------------------------------------------------------------------
82
+
83
+ Copyright &copy; 2024 - Martin-D. Lacasse
84
+
85
+ Disclaimers: This code is for educatonal purposes only and does not constitute financial advice.
86
+
87
+ Code output has been verified with analytical solutions when applicable, and comparative approaches otherwise.
88
+ Nevertheless, accuracy of results is not guaranteed.
89
+
90
+ --------------------------------------------------------
91
+
@@ -1,3 +1,36 @@
1
+ ### Version 2025.12.20
2
+ - Implemented Debts and Fixed Assets capabilities
3
+ - Mortgages, loans, restricted stocks, etc. and fixed lump-sum annuities can now be modeled
4
+ - Debts and fixed assets at end of plan included in bequest
5
+ - Extended Wages and Contributions page which was renamed Household Financial Profile
6
+ - Added debt payment and fixed assets bequest reporting to Synopsis
7
+ - Improved user interface
8
+ - Improved integration with ssa.tools
9
+
10
+ ### Version 2025.12.16
11
+ - Fix error message when dates are empty in Create_Case
12
+ - Carry minor fixes from dev version
13
+
14
+ ### Version 2025.12.11
15
+ - Add more bubble help messages in Create Case
16
+ - Fixed bug in rates selection UI
17
+ - Remove reliance on GitHub for graphics and example files
18
+
19
+ ### Version 2025.12.10
20
+ - Added date of birth due to funny social security rules when birthday on 1st and 2nd
21
+ - Modified FRA calculations accordingly
22
+ - Added integration to ssa.tools
23
+
24
+ ### Version 2025.12.09
25
+ - Improved instructions for developers
26
+ - Added link to ssa.tools on `Fixed Income` page
27
+ - Fixed bug on max age range for SS when month != 0
28
+ - Added table of federal income tax itemized by bracket
29
+
30
+ ### Version 2025.12.05
31
+ - Added instructions for obtaining PIA
32
+ - Bug fix in Fixed Income UI
33
+
1
34
  ### Version 2025.12.03
2
35
  - Coded social security to use monthly PIA instead of annual amount
3
36
  - Added exact routines for FRA and increase/decrease factors due to claiming age
@@ -0,0 +1,75 @@
1
+ # https://www.ssa.gov/OACT/COLA/awiseries.html
2
+ 1951 "2,799.16" �
3
+ 1952 "2,973.32" 6.22%
4
+ 1953 "3,139.44" 5.59%
5
+ 1954 "3,155.64" 0.52%
6
+ 1955 "3,301.44" 4.62%
7
+ 1956 "3,532.36" 6.99%
8
+ 1957 "3,641.72" 3.10%
9
+ 1958 "3,673.80" 0.88%
10
+ 1959 "3,855.80" 4.95%
11
+ 1960 "4,007.12" 3.92%
12
+ 1961 "4,086.76" 1.99%
13
+ 1962 "4,291.40" 5.01%
14
+ 1963 "4,396.64" 2.45%
15
+ 1964 "4,576.32" 4.09%
16
+ 1965 "4,658.72" 1.80%
17
+ 1966 "4,938.36" 6.00%
18
+ 1967 "5,213.44" 5.57%
19
+ 1968 "5,571.76" 6.87%
20
+ 1969 "5,893.76" 5.78%
21
+ 1970 "6,186.24" 4.96%
22
+ 1971 "6,497.08" 5.02%
23
+ 1972 "7,133.80" 9.80%
24
+ 1973 "7,580.16" 6.26%
25
+ 1974 "8,030.76" 5.94%
26
+ 1975 "8,630.92" 7.47%
27
+ 1976 "9,226.48" 6.90%
28
+ 1977 "9,779.44" 5.99%
29
+ 1978 "10,556.03" 7.94%
30
+ 1979 "11,479.46" 8.75%
31
+ 1980 "12,513.46" 9.01%
32
+ 1981 "13,773.10" 10.07%
33
+ 1982 "14,531.34" 5.51%
34
+ 1983 "15,239.24" 4.87%
35
+ 1984 "16,135.07" 5.88%
36
+ 1985 "16,822.51" 4.26%
37
+ 1986 "17,321.82" 2.97%
38
+ 1987 "18,426.51" 6.38%
39
+ 1988 "19,334.04" 4.93%
40
+ 1989 "20,099.55" 3.96%
41
+ 1990 "21,027.98" 4.62%
42
+ 1991 "21,811.60" 3.73%
43
+ 1992 "22,935.42" 5.15%
44
+ 1993 "23,132.67" 0.86%
45
+ 1994 "23,753.53" 2.68%
46
+ 1995 "24,705.66" 4.01%
47
+ 1996 "25,913.90" 4.89%
48
+ 1997 "27,426.00" 5.84%
49
+ 1998 "28,861.44" 5.23%
50
+ 1999 "30,469.84" 5.57%
51
+ 2000 "32,154.82" 5.53%
52
+ 2001 "32,921.92" 2.39%
53
+ 2002 "33,252.09" 1.00%
54
+ 2003 "34,064.95" 2.44%
55
+ 2004 "35,648.55" 4.65%
56
+ 2005 "36,952.94" 3.66%
57
+ 2006 "38,651.41" 4.60%
58
+ 2007 "40,405.48" 4.54%
59
+ 2008 "41,334.97" 2.30%
60
+ 2009 "40,711.61" -1.51%
61
+ 2010 "41,673.83" 2.36%
62
+ 2011 "42,979.61" 3.13%
63
+ 2012 "44,321.67" 3.12%
64
+ 2013 "44,888.16" 1.28%
65
+ 2014 "46,481.52" 3.55%
66
+ 2015 "48,098.63" 3.48%
67
+ 2016 "48,642.15" 1.13%
68
+ 2017 "50,321.89" 3.45%
69
+ 2018 "52,145.80" 3.62%
70
+ 2019 "54,099.99" 3.75%
71
+ 2020 "55,628.60" 2.83%
72
+ 2021 "60,575.07" 8.89%
73
+ 2022 "63,795.13" 5.32%
74
+ 2023 "66,621.80" 4.43%
75
+ 2024 "69,846.57" 4.84%
@@ -0,0 +1,10 @@
1
+ ::
2
+ :: A simple script to build Python package
3
+ ::
4
+ cd ..
5
+ del /Q dist\*
6
+ type nul > uv.lock
7
+ python -m build .
8
+ del uv.lock
9
+
10
+ twine upload --repository pypi dist\*
@@ -0,0 +1,10 @@
1
+ ## !/bin/bash or similar
2
+
3
+ cd ..
4
+ rm dist/*.whl dist/*.tar.gz
5
+
6
+ touch uv.lock
7
+ python -m build .
8
+ rm uv.lock
9
+
10
+ twine upload --repository pypi dist/*