owlplanner 2025.3.14__tar.gz → 2025.3.15__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 (108) hide show
  1. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/PKG-INFO +1 -1
  2. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/owl.pdf +0 -0
  3. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/owl.tex +25 -16
  4. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/pyproject.toml +1 -1
  5. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/src/owlplanner/plan.py +9 -13
  6. owlplanner-2025.3.15/src/owlplanner/version.py +1 -0
  7. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/requirements.txt +1 -1
  8. owlplanner-2025.3.14/src/owlplanner/version.py +0 -1
  9. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/.devcontainer/devcontainer.json +0 -0
  10. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/.flake8 +0 -0
  11. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/.gitattributes +0 -0
  12. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/.github/workflows/github-actions-runtests.yml +0 -0
  13. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/.gitignore +0 -0
  14. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/INSTALL.md +0 -0
  15. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/LICENSE +0 -0
  16. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/Papers/FE00006821-Class-VI-Injection-Permit--Salient-Features-and-Regulatory-Challenges_Final.pdf +0 -0
  17. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/Papers/Kou-OptionPricingDouble-2004.pdf +0 -0
  18. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/Papers/Multi-Period Mean Expected-Shortfall Strategies Cut Your Losses and Ride Your Gains .pdf +0 -0
  19. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/Papers/Optimal Asset Allocation for Retirement Saving Deterministic Vs. Time Consistent Adaptive Strategies.pdf +0 -0
  20. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/Papers/Rule-based_strategies_for_dynamic_life_cycle_inves.pdf +0 -0
  21. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/Papers/s10436-006-0062-y.pdf +0 -0
  22. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/README.md +0 -0
  23. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/USER_GUIDE.md +0 -0
  24. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docker/Dockerfile +0 -0
  25. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docker/README.md +0 -0
  26. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docker/docker-compose.yml +0 -0
  27. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docker/fastentrypoint.sh +0 -0
  28. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/AD-taxDef.png +0 -0
  29. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/AD-taxFree.png +0 -0
  30. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/AD-taxable.png +0 -0
  31. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/Hist_Bequest.png +0 -0
  32. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/Hist_Spending.png +0 -0
  33. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/MC-tutorial2a.png +0 -0
  34. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/MC-tutorial2b.png +0 -0
  35. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/OwlUI.png +0 -0
  36. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/allocations.png +0 -0
  37. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/owl.png +0 -0
  38. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/profile.png +0 -0
  39. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/ratesCorrelations.png +0 -0
  40. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/ratesPlot.png +0 -0
  41. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/savingsPlot.png +0 -0
  42. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/sourcesPlot.png +0 -0
  43. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/spendingPlot.png +0 -0
  44. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/taxIncomePlot.png +0 -0
  45. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/docs/images/taxesPlot.png +0 -0
  46. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/examples/case_jack+jill.toml +0 -0
  47. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/examples/case_joe.toml +0 -0
  48. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/examples/case_john+sally.toml +0 -0
  49. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/examples/case_jon+jane.toml +0 -0
  50. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/examples/case_kim+sam-bequest.toml +0 -0
  51. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/examples/case_kim+sam-spending.toml +0 -0
  52. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/examples/jack+jill.xlsx +0 -0
  53. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/examples/joe.xlsx +0 -0
  54. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/examples/john+sally.xlsx +0 -0
  55. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/examples/jon+jane.xlsx +0 -0
  56. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/examples/template.xlsx +0 -0
  57. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/notebooks/john+sally.ipynb +0 -0
  58. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/notebooks/kim+sam.ipynb +0 -0
  59. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/notebooks/template.ipynb +0 -0
  60. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/notebooks/tutorial_1.ipynb +0 -0
  61. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/notebooks/tutorial_2.ipynb +0 -0
  62. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/notebooks/tutorial_3.ipynb +0 -0
  63. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/owlplanner.cmd +0 -0
  64. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/owlplanner.sh +0 -0
  65. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/requirements.txt +0 -0
  66. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/src/owlplanner/__init__.py +0 -0
  67. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/src/owlplanner/abcapi.py +0 -0
  68. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/src/owlplanner/config.py +0 -0
  69. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/src/owlplanner/data/__init__.py +0 -0
  70. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/src/owlplanner/data/rates.csv +0 -0
  71. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/src/owlplanner/logging.py +0 -0
  72. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/src/owlplanner/progress.py +0 -0
  73. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/src/owlplanner/rates.py +0 -0
  74. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/src/owlplanner/tax2025.py +0 -0
  75. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/src/owlplanner/timelists.py +0 -0
  76. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/src/owlplanner/utils.py +0 -0
  77. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/tests/test_logger.py +0 -0
  78. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/tests/test_regressions.py +0 -0
  79. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/tests/test_repro.py +0 -0
  80. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/tests/test_toml_cases.py +0 -0
  81. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/tests/test_units.py +0 -0
  82. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ttt.py +0 -0
  83. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/About_Owl.py +0 -0
  84. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/Asset_Allocation.py +0 -0
  85. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/Create_Case.py +0 -0
  86. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/Current_Assets.py +0 -0
  87. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/Documentation.py +0 -0
  88. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/Fixed_Income.py +0 -0
  89. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/Graphs.py +0 -0
  90. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/Historical_Range.py +0 -0
  91. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/Logs.py +0 -0
  92. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/Monte_Carlo.py +0 -0
  93. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/Optimization_Parameters.py +0 -0
  94. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/Output_Files.py +0 -0
  95. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/Quick_Start.py +0 -0
  96. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/README.md +0 -0
  97. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/Rates_Selection.py +0 -0
  98. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/Settings.py +0 -0
  99. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/Wages_And_Contributions.py +0 -0
  100. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/Worksheets.py +0 -0
  101. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/main+fonts.py +0 -0
  102. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/main.py +0 -0
  103. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/owlbridge.py +0 -0
  104. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/plots.py +0 -0
  105. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/progress.py +0 -0
  106. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/sskeys.py +0 -0
  107. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/style.css +0 -0
  108. {owlplanner-2025.3.14 → owlplanner-2025.3.15}/ui/tomlexamples.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: owlplanner
3
- Version: 2025.3.14
3
+ Version: 2025.3.15
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
@@ -87,7 +87,7 @@ index name as a subscript, e.g., $N_i$ for index $i$.
87
87
  More asset classes could be considered at the cost of increasing
88
88
  the complexity of the problem while not generating much more insights.
89
89
  \item [$n$]
90
- Year being modeled. Period being modeled runs from the beginning of year 0 to
90
+ Index of year being modeled. Period being modeled runs from the beginning of year 0 to
91
91
  the end of year $N_n-1$, and therefore $N_n + 1$ years are considered.
92
92
  Year $N_n$ is the first year following the passing of all
93
93
  individuals in the plan. The time period for all decision variables is annual.
@@ -435,24 +435,32 @@ All intermediate variables are in uppercase letters.
435
435
  the taxable savings account is being depleted slowly. An implementation keeping track
436
436
  of stock purchases and sales is beyond the goal of providing a guide for retirement decisions.
437
437
 
438
+ \item [$P_n$]
439
+ Amount of 10\% early withdrawal penalty in year $n$,
440
+ \begin{equation}
441
+ \label{Eq:PenTax0}
442
+ P_n = 0.10 \sum_{i, j\neq0} (1 - \mathcal{H}(n - n_{i,59})) w_{ijn}.
443
+ \end{equation}
444
+ Here, $H(n - n_{i, 59})$ is a Heavyside step function which is 0 or 1, depending on the sign of
445
+ its argument:
446
+ \begin{equation}
447
+ \mathcal{H}(x) :=
448
+ \begin{cases}
449
+ 0 & x < 0 \\
450
+ 1 & x \geq 0.
451
+ \end{cases}
452
+ \end{equation}
453
+ The variable $n_{i, 59}$ is the year index when individual $i$ turns 59,
454
+ or 0 if already 59 years old or older.
455
+
438
456
  \item [$T_n$]
439
457
  Amount of income tax paid on taxable ordinary income $G_n$ in year $n$.
440
458
  This is the taxes paid on ordinary income expressed as the sum of the amounts
441
459
  paid in each tax bracket as
442
460
  \begin{equation}
443
461
  \label{Eq:IncTax0}
444
- T_n = \sum_t f_{tn}\bar{\Delta}_{tn}\theta_{tn} + 0.10 \sum_i (1 - \mathcal{H}(n - n_{i,60})) w_{i1n},
462
+ T_n = \sum_t f_{tn}\bar{\Delta}_{tn}\theta_{tn}.
445
463
  \end{equation}
446
- where $H(n - n_{i, 60})$ is a Heavyside step function which is 0 or 1, depending on the sign of
447
- its argument:
448
- \[
449
- \mathcal{H}(x) \def
450
- \begin{cases}
451
- 0 & x < 0 \\
452
- 1 & x \geq 0. \\
453
- \end{cases}
454
- \]
455
- Here, $n_{i, 60}$ is the year when individual $i$ will turn 60.
456
464
  Notice that $G_n$ is also defined by Eq.~(\ref{Eq:Tx1}), and that optimal
457
465
  values of $f_{tn}$ have to
458
466
  minimize $T_n$ when either the bequest or the desired net spending are maximized.
@@ -463,8 +471,9 @@ All intermediate variables are in uppercase letters.
463
471
  filling in the lower brackets first when optimizing. In that case
464
472
  \begin{equation}
465
473
  \label{Eq:IncTax1}
466
- T_n = \sum_t \bar{F}_{tn} \theta_{tn}.
474
+ T_n = \sum_t \bar{F}_{tn} \theta_{tn}
467
475
  \end{equation}
476
+
468
477
  \item [$U_n$]
469
478
  Amount of income tax paid on long-term capital gains and qualified dividends in year $n$,
470
479
  \begin{equation}
@@ -698,7 +707,7 @@ add the market returns to the savings balances.
698
707
  \begin{eqnarray}
699
708
  g_n = \sum_i [\omega_{in} + \bar{\zeta}_{in} + \pi_{in} ]
700
709
  + \sum_{ij} w_{ijn} + \sum_i \Lambda^\pm_{in} - s_{n}
701
- - T_n - U_n - \mathcal{M}^\ell_n.
710
+ - P_n - T_n - U_n - \mathcal{M}^\ell_n.
702
711
  \end{eqnarray}
703
712
  When both spouses are alive, surplus $s_n$ gets deposited in the taxable accounts
704
713
  according to variable $\eta$ as described in Eq.~(\ref{Eq:eta}),
@@ -712,7 +721,7 @@ add the market returns to the savings balances.
712
721
  Replacing intermediate variables and bringing all variables to the left-hand side, we get
713
722
  \begin{eqnarray}
714
723
  \label{Eq:C4}
715
- g_n - \sum_{ij} w_{ijn} + s_{n}
724
+ g_n - \sum_{ij} w_{ijn} + 0.1 \sum_{i,j\neq0} (1-\mathcal{H}(n - n_{i, 59})) w_{ijn} + s_n
716
725
  + \sum_t \bar{F}_{tn} \theta_{t n} &&\nonumber \\
717
726
  + \psi\alpha_{i00n} \sum_{i} \left[\mu(b_{i0n} - w_{i0n} + d_{in})
718
727
  + w_{i0n}\max(0, \tau_{0n-1})\right]
@@ -1020,7 +1029,7 @@ For the equality constraint on net spending expressed in Eq.~(\ref{Eq:C4}),
1020
1029
  we add $N_n$ more rows to $A_ey = v$ as
1021
1030
  \begin{eqnarray}
1022
1031
  A_e[J_2(n), q_g(n)] &=& 1, \nonumber \\
1023
- A_e[J_2(n), q_w(i, j ,n)] &=& -1 + \delta(j, 0)\psi\alpha_{i00n}(\max(0, \tau_{0n-1}) - \mu), \nonumber \\
1032
+ A_e[J_2(n), q_w(i, j ,n)] &=& -1 + .1(1-\delta(j, 0))(1-\mathcal{H}(n-n_{i, 59})) + \delta(j, 0)\psi\alpha_{i00n}(\max(0, \tau_{0n-1}) - \mu), \nonumber \\
1024
1033
  A_e[J_2(n), q_d(i, n)] &=& 1 + \psi\mu\alpha_{i00n}, \nonumber \\
1025
1034
  A_e[J_2(n), q_F(t, n)] &=& \theta_{t n}, \nonumber \\
1026
1035
  A_e[J_2(n), q_b(i, 0, n)] &=& \psi\mu\alpha_{i00n}, \nonumber \\
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "owlplanner"
7
- version = "2025.03.14"
7
+ version = "2025.03.15"
8
8
  authors = [
9
9
  { name="Martin-D. Lacasse", email="martin.d.lacasse@gmail.com" },
10
10
  ]
@@ -1284,19 +1284,15 @@ class Plan(object):
1284
1284
  # Minus capital gains on taxable withdrawals using last year's rate if >=0.
1285
1285
  # Plus taxable account withdrawals, and all other withdrawals.
1286
1286
  row.addElem(_q3(Cw, i, 0, n, Ni, Nj, Nn), fac * (tau_0prev[n] - self.mu) - 1)
1287
- row.addElem(_q3(Cw, i, 1, n, Ni, Nj, Nn), -1)
1288
- row.addElem(_q3(Cw, i, 2, n, Ni, Nj, Nn), -1)
1287
+ penalty = 0.1 if n < self.n59[i] else 0
1288
+ row.addElem(_q3(Cw, i, 1, n, Ni, Nj, Nn), -1 + penalty)
1289
+ row.addElem(_q3(Cw, i, 2, n, Ni, Nj, Nn), -1 + penalty)
1289
1290
  row.addElem(_q2(Cd, i, n, Ni, Nn), fac * self.mu)
1290
1291
 
1291
1292
  # Minus tax on ordinary income, T_n.
1292
1293
  for t in range(Nt):
1293
1294
  row.addElem(_q2(CF, t, n, Nt, Nn), self.theta_tn[t, n])
1294
1295
 
1295
- # Minus 10% penalty on early withdrawals.
1296
- if n < self.n59[i]:
1297
- row.addElem(_q3(Cw, i, 1, n, Ni, Nj, Nn), 0.1)
1298
- row.addElem(_q3(Cw, i, 2, n, Ni, Nj, Nn), 0.1)
1299
-
1300
1296
  A.addRow(row, rhs, rhs)
1301
1297
 
1302
1298
  # Impose income profile.
@@ -1978,12 +1974,12 @@ class Plan(object):
1978
1974
  self.G_n = np.sum(self.F_tn, axis=0)
1979
1975
  self.T_tn = self.F_tn * self.theta_tn
1980
1976
  self.T_n = np.sum(self.T_tn, axis=0)
1981
- self.penalty_n = np.zeros(Nn)
1982
- # Add early withdrawal penalties if any.
1977
+ self.P_n = np.zeros(Nn)
1978
+ # Add early withdrawal penalty if any.
1983
1979
  for i in range(Ni):
1984
- self.penalty_n[0:self.n59[i]] += 0.1*(self.w_ijn[i, 1, 0:self.n59[i]] + self.w_ijn[i, 2, 0:self.n59[i]])
1980
+ self.P_n[0:self.n59[i]] += 0.1*(self.w_ijn[i, 1, 0:self.n59[i]] + self.w_ijn[i, 2, 0:self.n59[i]])
1985
1981
 
1986
- self.T_n += self.penalty_n
1982
+ self.T_n += self.P_n
1987
1983
 
1988
1984
  tau_0 = np.array(self.tau_kn[0, :])
1989
1985
  tau_0[tau_0 < 0] = 0
@@ -2126,8 +2122,8 @@ class Plan(object):
2126
2122
  dic[f"-- Subtotal in tax bracket {tname}"] = f"{u.d(taxPaidNow)}"
2127
2123
  dic[f"-- [Subtotal in tax bracket {tname}]"] = f"{u.d(taxPaid)}"
2128
2124
 
2129
- penaltyPaid = np.sum(self.penalty_n, axis=0)
2130
- penaltyPaidNow = np.sum(self.penalty_n / self.gamma_n[:-1], axis=0)
2125
+ penaltyPaid = np.sum(self.P_n, axis=0)
2126
+ penaltyPaidNow = np.sum(self.P_n / self.gamma_n[:-1], axis=0)
2131
2127
  dic["-- Subtotal in early withdrawal penalty"] = f"{u.d(penaltyPaidNow)}"
2132
2128
  dic["-- [Subtotal in early withdrawal penalty]"] = f"{u.d(penaltyPaid)}"
2133
2129
 
@@ -0,0 +1 @@
1
+ __version__ = "2025.03.15"
@@ -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.14
10
+ owlplanner >= 2025.03.15
@@ -1 +0,0 @@
1
- __version__ = "2025.03.14"
File without changes
File without changes
File without changes
File without changes