owlplanner 2025.3.27__tar.gz → 2025.3.30__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 (111) hide show
  1. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/PKG-INFO +1 -1
  2. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/owl.pdf +0 -0
  3. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/pyproject.toml +1 -1
  4. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/src/owlplanner/plan.py +3 -2
  5. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/src/owlplanner/tax2025.py +1 -1
  6. owlplanner-2025.3.30/src/owlplanner/version.py +1 -0
  7. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/About_Owl.py +4 -6
  8. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/Documentation.py +8 -0
  9. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/requirements.txt +1 -1
  10. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/sskeys.py +5 -4
  11. owlplanner-2025.3.27/src/owlplanner/version.py +0 -1
  12. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/.devcontainer/devcontainer.json +0 -0
  13. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/.flake8 +0 -0
  14. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/.gitattributes +0 -0
  15. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/.github/workflows/github-actions-runtests.yml +0 -0
  16. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/.gitignore +0 -0
  17. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/INSTALL.md +0 -0
  18. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/LICENSE +0 -0
  19. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/Papers/FE00006821-Class-VI-Injection-Permit--Salient-Features-and-Regulatory-Challenges_Final.pdf +0 -0
  20. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/Papers/Kou-OptionPricingDouble-2004.pdf +0 -0
  21. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/Papers/Multi-Period Mean Expected-Shortfall Strategies Cut Your Losses and Ride Your Gains .pdf +0 -0
  22. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/Papers/Optimal Asset Allocation for Retirement Saving Deterministic Vs. Time Consistent Adaptive Strategies.pdf +0 -0
  23. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/Papers/Rule-based_strategies_for_dynamic_life_cycle_inves.pdf +0 -0
  24. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/Papers/s10436-006-0062-y.pdf +0 -0
  25. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/README.md +0 -0
  26. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/USER_GUIDE.md +0 -0
  27. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docker/Dockerfile +0 -0
  28. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docker/README.md +0 -0
  29. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docker/docker-compose.yml +0 -0
  30. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docker/fastentrypoint.sh +0 -0
  31. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/AD-taxDef.png +0 -0
  32. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/AD-taxFree.png +0 -0
  33. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/AD-taxable.png +0 -0
  34. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/Hist_Bequest.png +0 -0
  35. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/Hist_Spending.png +0 -0
  36. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/MC-tutorial2a.png +0 -0
  37. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/MC-tutorial2b.png +0 -0
  38. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/OwlUI.png +0 -0
  39. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/allocations.png +0 -0
  40. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/owl.png +0 -0
  41. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/profile.png +0 -0
  42. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/ratesCorrelations.png +0 -0
  43. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/ratesPlot.png +0 -0
  44. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/savingsPlot.png +0 -0
  45. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/sourcesPlot.png +0 -0
  46. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/spendingPlot.png +0 -0
  47. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/taxIncomePlot.png +0 -0
  48. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/images/taxesPlot.png +0 -0
  49. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/docs/owl.tex +0 -0
  50. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/examples/case_jack+jill.toml +0 -0
  51. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/examples/case_joe.toml +0 -0
  52. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/examples/case_john+sally.toml +0 -0
  53. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/examples/case_jon+jane.toml +0 -0
  54. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/examples/case_kim+sam-bequest.toml +0 -0
  55. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/examples/case_kim+sam-spending.toml +0 -0
  56. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/examples/jack+jill.xlsx +0 -0
  57. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/examples/joe.xlsx +0 -0
  58. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/examples/john+sally.xlsx +0 -0
  59. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/examples/jon+jane.xlsx +0 -0
  60. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/examples/template.xlsx +0 -0
  61. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/notebooks/john+sally.ipynb +0 -0
  62. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/notebooks/kim+sam.ipynb +0 -0
  63. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/notebooks/template.ipynb +0 -0
  64. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/notebooks/tutorial_1.ipynb +0 -0
  65. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/notebooks/tutorial_2.ipynb +0 -0
  66. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/notebooks/tutorial_3.ipynb +0 -0
  67. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/owlplanner.cmd +0 -0
  68. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/owlplanner.sh +0 -0
  69. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/requirements.txt +0 -0
  70. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/src/owlplanner/__init__.py +0 -0
  71. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/src/owlplanner/abcapi.py +0 -0
  72. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/src/owlplanner/config.py +0 -0
  73. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/src/owlplanner/data/__init__.py +0 -0
  74. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/src/owlplanner/data/rates.csv +0 -0
  75. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/src/owlplanner/logging.py +0 -0
  76. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/src/owlplanner/progress.py +0 -0
  77. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/src/owlplanner/rates.py +0 -0
  78. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/src/owlplanner/timelists.py +0 -0
  79. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/src/owlplanner/utils.py +0 -0
  80. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/tests/test_logger.py +0 -0
  81. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/tests/test_regressions.py +0 -0
  82. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/tests/test_repro.py +0 -0
  83. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/tests/test_toml_cases.py +0 -0
  84. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/tests/test_units.py +0 -0
  85. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ttt.py +0 -0
  86. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ttt2.py +0 -0
  87. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ttt3.py +0 -0
  88. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/Asset_Allocation.py +0 -0
  89. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/Create_Case.py +0 -0
  90. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/Current_Assets.py +0 -0
  91. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/Fixed_Income.py +0 -0
  92. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/Graphs.py +0 -0
  93. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/Historical_Range.py +0 -0
  94. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/Logs.py +0 -0
  95. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/Monte_Carlo.py +0 -0
  96. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/Optimization_Parameters.py +0 -0
  97. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/Output_Files.py +0 -0
  98. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/Quick_Start.py +0 -0
  99. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/README.md +0 -0
  100. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/Rates_Selection.py +0 -0
  101. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/Settings.py +0 -0
  102. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/Wages_And_Contributions.py +0 -0
  103. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/Worksheets.py +0 -0
  104. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/main+fonts.py +0 -0
  105. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/main.py +0 -0
  106. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/owlbridge.py +0 -0
  107. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/plots.py +0 -0
  108. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/progress.py +0 -0
  109. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/sskeys.py.color +0 -0
  110. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/style.css +0 -0
  111. {owlplanner-2025.3.27 → owlplanner-2025.3.30}/ui/tomlexamples.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: owlplanner
3
- Version: 2025.3.27
3
+ Version: 2025.3.30
4
4
  Summary: Owl: 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
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "owlplanner"
7
- version = "2025.03.27"
7
+ version = "2025.03.30"
8
8
  authors = [
9
9
  { name="Martin-D. Lacasse", email="martin.d.lacasse@gmail.com" },
10
10
  ]
@@ -1197,7 +1197,8 @@ class Plan(object):
1197
1197
  # Account for time elapsed in the current year.
1198
1198
  spending *= units * self.yearFracLeft
1199
1199
  # self.mylog.vprint('Maximizing bequest with desired net spending of:', u.d(spending))
1200
- A.addNewRow({_q1(Cg, 0): 1}, spLo * spending, spHi * spending)
1200
+ # To allow slack in first year, Cg can be made Nn+1 and store basis in g[Nn].
1201
+ A.addNewRow({_q1(Cg, 0, Nn): 1}, spending, spending)
1201
1202
 
1202
1203
  # Set initial balances through constraints.
1203
1204
  for i in range(Ni):
@@ -1370,7 +1371,7 @@ class Plan(object):
1370
1371
  # Now build a solver-neutral objective vector.
1371
1372
  c = abc.Objective(self.nvars)
1372
1373
  if objective == "maxSpending":
1373
- # c.setElem(_q1(Cg, 0, Nn), -1)
1374
+ # c.setElem(_q1(Cg, 0, Nn), -1) # Only OK in implemention without slack.
1374
1375
  for n in range(Nn):
1375
1376
  c.setElem(_q1(Cg, n, Nn), -1/self.gamma_n[n])
1376
1377
  elif objective == "maxBequest":
@@ -36,7 +36,7 @@ rates_nonTCJA = np.array([0.10, 0.15, 0.25, 0.28, 0.33, 0.35, 0.396])
36
36
  taxBrackets_TCJA = np.array(
37
37
  [
38
38
  [11925, 48475, 103350, 197300, 250525, 626350, 9999999],
39
- [23850, 96950, 206700, 394600, 501050, 751700, 9999999],
39
+ [23850, 96950, 206700, 394600, 501050, 751600, 9999999],
40
40
  ]
41
41
  )
42
42
 
@@ -0,0 +1 @@
1
+ __version__ = "2025.03.30"
@@ -41,12 +41,10 @@ or directly by [email](mailto://martin.d.lacasse@gmail.com).
41
41
 
42
42
  #### :orange[Privacy]
43
43
  - This app does not store or forward any information. All data entered is lost
44
- after a session is closed. However, you can choose to download selected data to your own
45
- computer before closing the session.
46
- Source code is publicly available and can be inspected in the repository.
44
+ after a session is closed. You can choose to download selected part of your
45
+ own data to your computer before closing the session.
47
46
 
48
- #### :orange[Disclaimers]
49
- - I am not a financial planner. You make your own decisions.
50
- - This program comes with no guarantee. Use at your own risk.
47
+ #### :orange[Disclaimer]
48
+ - This program is provided for educational purposes and comes with no guarantee. Use at your own risk.
51
49
  """
52
50
  )
@@ -291,6 +291,14 @@ and a time delay, in years from today, before the non-flat behavior starts to ac
291
291
  Values default to 15%, 12%, and 0 year respectively, but they are fully configurable
292
292
  for experimentation and to fit your anticipated lifestyle.
293
293
 
294
+ A slack variable can also be adjusted. This variable allows the net spending to deviate from
295
+ the desired profile in order to maximize the objective. This is provided mostly for educational purpose
296
+ as maximizing the total net spending will involve leaving the savings invested for as long as possible,
297
+ and therefore this will favor smaller spending early in the plan and larger towards the end.
298
+ This tension between maximizing a dollar amount and the utility of money then becomes evident.
299
+ While the health of the individuals and therefore the utility of money is higher at the beginning
300
+ of retirement, maximizing the total spending or bequest will pull in an opposite direction.
301
+
294
302
  For married couples, the survivor's
295
303
  net spending percentage is also configurable. A value of 60% is typically used.
296
304
  The selected profile multiplies
@@ -7,4 +7,4 @@ scipy
7
7
  streamlit
8
8
  toml
9
9
  # --extra-index-url https://test.pypi.org/simple
10
- owlplanner >= 2025.03.27
10
+ owlplanner >= 2025.03.30
@@ -510,8 +510,8 @@ def getToggle(text, nkey, callback=setpull, disabled=False, help=None):
510
510
  )
511
511
 
512
512
 
513
- def divider(color):
514
- st.html("<style> hr {border-color: %s;}</style><hr>" % color)
513
+ def divider(color, width="auto"):
514
+ st.html("<style> hr {border-color: %s;width: %s}</style><hr>" % (color, width))
515
515
 
516
516
 
517
517
  def getColors():
@@ -545,7 +545,7 @@ def titleBar(txt, choices=None):
545
545
  /* background-color: %s; */
546
546
  color: %s;
547
547
  top: 2.875rem;
548
- z-index: 999;
548
+ z-index: 100;
549
549
  }
550
550
  </style>""" % (bc, fc), unsafe_allow_html=True
551
551
  )
@@ -565,5 +565,6 @@ def titleBar(txt, choices=None):
565
565
  args=[nkey],
566
566
  )
567
567
 
568
- divider("white")
568
+ divider("white", "99%")
569
+
569
570
  return ret
@@ -1 +0,0 @@
1
- __version__ = "2025.03.27"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes