owlplanner 2025.2.20__tar.gz → 2025.2.21__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 (101) hide show
  1. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/PKG-INFO +1 -1
  2. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/owl.tex +1 -2
  3. owlplanner-2025.2.21/examples/case_jon+jane.toml +56 -0
  4. owlplanner-2025.2.21/examples/jon+jane.xlsx +0 -0
  5. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/pyproject.toml +1 -1
  6. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/src/owlplanner/config.py +6 -1
  7. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/src/owlplanner/plan.py +1 -1
  8. owlplanner-2025.2.21/src/owlplanner/version.py +1 -0
  9. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/owlbridge.py +2 -1
  10. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/requirements.txt +1 -1
  11. owlplanner-2025.2.20/src/owlplanner/version.py +0 -1
  12. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/.devcontainer/devcontainer.json +0 -0
  13. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/.flake8 +0 -0
  14. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/.gitattributes +0 -0
  15. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/.github/workflows/github-actions-runtests.yml +0 -0
  16. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/.gitignore +0 -0
  17. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/INSTALL.md +0 -0
  18. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/LICENSE +0 -0
  19. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/README.md +0 -0
  20. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/USER_GUIDE.md +0 -0
  21. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docker/Dockerfile +0 -0
  22. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docker/README.md +0 -0
  23. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docker/docker-compose.yml +0 -0
  24. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docker/fastentrypoint.sh +0 -0
  25. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/AD-taxDef.png +0 -0
  26. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/AD-taxFree.png +0 -0
  27. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/AD-taxable.png +0 -0
  28. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/Hist_Bequest.png +0 -0
  29. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/Hist_Spending.png +0 -0
  30. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/MC-tutorial2a.png +0 -0
  31. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/MC-tutorial2b.png +0 -0
  32. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/OwlUI.png +0 -0
  33. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/allocations.png +0 -0
  34. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/owl.png +0 -0
  35. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/profile.png +0 -0
  36. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/ratesCorrelations.png +0 -0
  37. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/ratesPlot.png +0 -0
  38. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/savingsPlot.png +0 -0
  39. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/sourcesPlot.png +0 -0
  40. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/spendingPlot.png +0 -0
  41. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/taxIncomePlot.png +0 -0
  42. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/images/taxesPlot.png +0 -0
  43. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/docs/owl.pdf +0 -0
  44. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/examples/case_jack+jill.toml +0 -0
  45. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/examples/case_joe.toml +0 -0
  46. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/examples/case_john+sally.toml +0 -0
  47. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/examples/case_kim+sam-bequest.toml +0 -0
  48. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/examples/case_kim+sam-spending.toml +0 -0
  49. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/examples/jack+jill.xlsx +0 -0
  50. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/examples/joe.xlsx +0 -0
  51. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/examples/john+sally.xlsx +0 -0
  52. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/examples/template.xlsx +0 -0
  53. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/notebooks/john+sally.ipynb +0 -0
  54. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/notebooks/kim+sam.ipynb +0 -0
  55. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/notebooks/template.ipynb +0 -0
  56. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/notebooks/tutorial_1.ipynb +0 -0
  57. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/notebooks/tutorial_2.ipynb +0 -0
  58. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/notebooks/tutorial_3.ipynb +0 -0
  59. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/owlplanner.cmd +0 -0
  60. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/owlplanner.sh +0 -0
  61. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/requirements.txt +0 -0
  62. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/src/owlplanner/__init__.py +0 -0
  63. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/src/owlplanner/abcapi.py +0 -0
  64. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/src/owlplanner/data/__init__.py +0 -0
  65. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/src/owlplanner/data/rates.csv +0 -0
  66. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/src/owlplanner/logging.py +0 -0
  67. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/src/owlplanner/progress.py +0 -0
  68. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/src/owlplanner/rates.py +0 -0
  69. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/src/owlplanner/tax2025.py +0 -0
  70. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/src/owlplanner/timelists.py +0 -0
  71. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/src/owlplanner/utils.py +0 -0
  72. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/tests/test_logger.py +0 -0
  73. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/tests/test_regressions.py +0 -0
  74. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/tests/test_repro.py +0 -0
  75. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/tests/test_toml_cases.py +0 -0
  76. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/tests/test_units.py +0 -0
  77. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ttt.py +0 -0
  78. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/About_Owl.py +0 -0
  79. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/Asset_Allocation.py +0 -0
  80. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/Assets.py +0 -0
  81. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/Create_Case.py +0 -0
  82. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/Documentation.py +0 -0
  83. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/Fixed_Income.py +0 -0
  84. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/Graphs.py +0 -0
  85. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/Historical_Range.py +0 -0
  86. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/Logs.py +0 -0
  87. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/Monte_Carlo.py +0 -0
  88. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/Optimization_Parameters.py +0 -0
  89. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/Output_Files.py +0 -0
  90. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/Quick_Start.py +0 -0
  91. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/README.md +0 -0
  92. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/Rates_Selection.py +0 -0
  93. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/Settings.py +0 -0
  94. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/Wages_And_Contributions.py +0 -0
  95. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/Worksheets.py +0 -0
  96. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/main+fonts.py +0 -0
  97. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/main.py +0 -0
  98. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/plots.py +0 -0
  99. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/progress.py +0 -0
  100. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/sskeys.py +0 -0
  101. {owlplanner-2025.2.20 → owlplanner-2025.2.21}/ui/style.css +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: owlplanner
3
- Version: 2025.2.20
3
+ Version: 2025.2.21
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
@@ -607,8 +607,7 @@ add the market returns to the savings balances.
607
607
  if needed due to RMDs or receiving large sums of money,
608
608
  could be made at the end of the year. Let's formulate this approach
609
609
  in more detail and investigate for potential problems.
610
- Timing controls which terms get multiplied by the rate of return $(1 + \tau_{kn})$
611
- for a particular asset $k$.
610
+ Timing controls which terms get multiplied by the rate of return $(1 + \mathcal{T}_{ijn})$.
612
611
  Therefore, our current choice would yield
613
612
  \begin{eqnarray}
614
613
  \label{Eq:C3a}
@@ -0,0 +1,56 @@
1
+ "Plan Name" = "Jon+Jane"
2
+
3
+ ["Basic Info"]
4
+ Status = "married"
5
+ Names = [ "Jon", "Jane",]
6
+ "Birth year" = [ 1965, 1968,]
7
+ "Life expectancy" = [ 92, 92,]
8
+ "Start date" = "01-01"
9
+
10
+ [Assets]
11
+ "taxable savings balances" = [ 50.0, 0.0,]
12
+ "tax-deferred savings balances" = [ 900.0, 500.0,]
13
+ "tax-free savings balances" = [ 0.0, 0.0,]
14
+ "Beneficiary fractions" = [ 1.0, 1.0, 1.0,]
15
+ "Spousal surplus deposit fraction" = 0.0
16
+
17
+ ["Wages and Contributions"]
18
+ "Contributions file name" = "edited values"
19
+
20
+ ["Fixed Income"]
21
+ "Pension amounts" = [ 0.0, 0.0,]
22
+ "Pension ages" = [ 65, 65,]
23
+ "Pension indexed" = [ false, false,]
24
+ "Social security amounts" = [ 21.0, 21.0,]
25
+ "Social security ages" = [ 65, 65,]
26
+
27
+ ["Rates Selection"]
28
+ "Heirs rate on tax-deferred estate" = 30.0
29
+ "Long-term capital gain tax rate" = 15.0
30
+ "Dividend tax rate" = 2.0
31
+ "TCJA expiration year" = 2026
32
+ Method = "user"
33
+ Values = [ 10.0, 0.0, 0.0, 3.5000000000000004,]
34
+ From = 1928
35
+ To = 2024
36
+
37
+ ["Asset Allocation"]
38
+ "Interpolation method" = "linear"
39
+ "Interpolation center" = 15.0
40
+ "Interpolation width" = 5.0
41
+ Type = "individual"
42
+ generic = [ [ [ 100, 0, 0, 0,], [ 100, 0, 0, 0,],], [ [ 100, 0, 0, 0,], [ 100, 0, 0, 0,],],]
43
+
44
+ ["Optimization Parameters"]
45
+ "Spending profile" = "flat"
46
+ "Surviving spouse spending percent" = 60
47
+ Objective = "maxSpending"
48
+
49
+ ["Solver Options"]
50
+ maxRothConversion = 0.0
51
+ noRothConversions = "None"
52
+ withMedicare = true
53
+ bequest = 30.0
54
+
55
+ [Results]
56
+ "Default plots" = "today"
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "owlplanner"
7
- version = "2025.02.20"
7
+ version = "2025.02.21"
8
8
  authors = [
9
9
  { name="Martin-D. Lacasse", email="martin.d.lacasse@gmail.com" },
10
10
  ]
@@ -180,7 +180,7 @@ def readConfig(file, *, verbose=True, logstreams=None, readContributions=True):
180
180
  # status = diconf['Basic Info']['Status']
181
181
  yobs = diconf["Basic Info"]["Birth year"]
182
182
  expectancy = diconf["Basic Info"]["Life expectancy"]
183
- startDate = diconf["Basic Info"]["Start date"]
183
+ startDate = diconf["Basic Info"].get("Start date", "today")
184
184
  icount = len(yobs)
185
185
  s = ["", "s"][icount - 1]
186
186
  mylog.vprint(f"Plan for {icount} individual{s}: {inames}.")
@@ -295,6 +295,11 @@ def readConfig(file, *, verbose=True, logstreams=None, readContributions=True):
295
295
  # Solver Options.
296
296
  p.solverOptions = diconf["Solver Options"]
297
297
 
298
+ # Check consistency of noRothConversions.
299
+ name = p.solverOptions.get("noRothConversions", "None")
300
+ if name != "None" and name not in p.inames:
301
+ raise ValueError(f"Unknown name {name} for noRothConversions.")
302
+
298
303
  # Results.
299
304
  p.setDefaultPlots(diconf["Results"]["Default plots"])
300
305
 
@@ -2895,7 +2895,7 @@ def _stackPlot(x, inames, title, irange, series, snames, location, yformat="\\$k
2895
2895
 
2896
2896
  if len(nonzeroSeries) == 0:
2897
2897
  # print('Nothing to plot for', title)
2898
- return None
2898
+ return None, None
2899
2899
 
2900
2900
  fig, ax = plt.subplots(figsize=(6, 4))
2901
2901
  plt.grid(visible="both")
@@ -0,0 +1 @@
1
+ __version__ = "2025.02.21"
@@ -422,7 +422,8 @@ def plotSingleResults(plan):
422
422
  st.write("##### Assets Distribution")
423
423
  morecols = st.columns(3, gap="small")
424
424
  for fig in figs:
425
- morecols[c].pyplot(fig)
425
+ if fig is not None:
426
+ morecols[c].pyplot(fig)
426
427
  c = (c + 1) % 3
427
428
 
428
429
 
@@ -7,4 +7,4 @@ scipy
7
7
  streamlit
8
8
  toml
9
9
  # --extra-index-url https://test.pypi.org/simple
10
- owlplanner >= 2025.02.20
10
+ owlplanner >= 2025.02.21
@@ -1 +0,0 @@
1
- __version__ = "2025.02.20"
File without changes
File without changes
File without changes
File without changes