owlplanner 2025.3.11__tar.gz → 2025.3.13__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.11 → owlplanner-2025.3.13}/.devcontainer/devcontainer.json +32 -32
  2. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/PKG-INFO +1 -1
  3. owlplanner-2025.3.13/Papers/FE00006821-Class-VI-Injection-Permit--Salient-Features-and-Regulatory-Challenges_Final.pdf +0 -0
  4. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/pyproject.toml +1 -1
  5. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/src/owlplanner/plan.py +19 -19
  6. owlplanner-2025.3.13/src/owlplanner/version.py +1 -0
  7. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/About_Owl.py +1 -1
  8. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/Documentation.py +7 -0
  9. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/Output_Files.py +3 -2
  10. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/Rates_Selection.py +1 -1
  11. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/requirements.txt +1 -1
  12. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/sskeys.py +6 -1
  13. owlplanner-2025.3.11/src/owlplanner/version.py +0 -1
  14. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/.flake8 +0 -0
  15. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/.gitattributes +0 -0
  16. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/.github/workflows/github-actions-runtests.yml +0 -0
  17. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/.gitignore +0 -0
  18. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/INSTALL.md +0 -0
  19. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/LICENSE +0 -0
  20. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/Papers/Kou-OptionPricingDouble-2004.pdf +0 -0
  21. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/Papers/Multi-Period Mean Expected-Shortfall Strategies Cut Your Losses and Ride Your Gains .pdf +0 -0
  22. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/Papers/Optimal Asset Allocation for Retirement Saving Deterministic Vs. Time Consistent Adaptive Strategies.pdf +0 -0
  23. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/Papers/Rule-based_strategies_for_dynamic_life_cycle_inves.pdf +0 -0
  24. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/Papers/s10436-006-0062-y.pdf +0 -0
  25. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/README.md +0 -0
  26. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/USER_GUIDE.md +0 -0
  27. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docker/Dockerfile +0 -0
  28. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docker/README.md +0 -0
  29. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docker/docker-compose.yml +0 -0
  30. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docker/fastentrypoint.sh +0 -0
  31. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/AD-taxDef.png +0 -0
  32. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/AD-taxFree.png +0 -0
  33. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/AD-taxable.png +0 -0
  34. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/Hist_Bequest.png +0 -0
  35. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/Hist_Spending.png +0 -0
  36. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/MC-tutorial2a.png +0 -0
  37. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/MC-tutorial2b.png +0 -0
  38. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/OwlUI.png +0 -0
  39. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/allocations.png +0 -0
  40. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/owl.png +0 -0
  41. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/profile.png +0 -0
  42. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/ratesCorrelations.png +0 -0
  43. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/ratesPlot.png +0 -0
  44. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/savingsPlot.png +0 -0
  45. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/sourcesPlot.png +0 -0
  46. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/spendingPlot.png +0 -0
  47. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/taxIncomePlot.png +0 -0
  48. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/images/taxesPlot.png +0 -0
  49. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/owl.pdf +0 -0
  50. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/docs/owl.tex +0 -0
  51. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/examples/case_jack+jill.toml +0 -0
  52. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/examples/case_joe.toml +0 -0
  53. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/examples/case_john+sally.toml +0 -0
  54. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/examples/case_jon+jane.toml +0 -0
  55. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/examples/case_kim+sam-bequest.toml +0 -0
  56. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/examples/case_kim+sam-spending.toml +0 -0
  57. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/examples/jack+jill.xlsx +0 -0
  58. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/examples/joe.xlsx +0 -0
  59. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/examples/john+sally.xlsx +0 -0
  60. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/examples/jon+jane.xlsx +0 -0
  61. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/examples/template.xlsx +0 -0
  62. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/notebooks/john+sally.ipynb +0 -0
  63. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/notebooks/kim+sam.ipynb +0 -0
  64. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/notebooks/template.ipynb +0 -0
  65. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/notebooks/tutorial_1.ipynb +0 -0
  66. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/notebooks/tutorial_2.ipynb +0 -0
  67. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/notebooks/tutorial_3.ipynb +0 -0
  68. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/owlplanner.cmd +0 -0
  69. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/owlplanner.sh +0 -0
  70. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/requirements.txt +0 -0
  71. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/src/owlplanner/__init__.py +0 -0
  72. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/src/owlplanner/abcapi.py +0 -0
  73. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/src/owlplanner/config.py +0 -0
  74. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/src/owlplanner/data/__init__.py +0 -0
  75. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/src/owlplanner/data/rates.csv +0 -0
  76. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/src/owlplanner/logging.py +0 -0
  77. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/src/owlplanner/progress.py +0 -0
  78. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/src/owlplanner/rates.py +0 -0
  79. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/src/owlplanner/tax2025.py +0 -0
  80. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/src/owlplanner/timelists.py +0 -0
  81. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/src/owlplanner/utils.py +0 -0
  82. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/tests/test_logger.py +0 -0
  83. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/tests/test_regressions.py +0 -0
  84. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/tests/test_repro.py +0 -0
  85. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/tests/test_toml_cases.py +0 -0
  86. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/tests/test_units.py +0 -0
  87. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ttt.py +0 -0
  88. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/Asset_Allocation.py +0 -0
  89. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/Create_Case.py +0 -0
  90. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/Current_Assets.py +0 -0
  91. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/Fixed_Income.py +0 -0
  92. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/Graphs.py +0 -0
  93. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/Historical_Range.py +0 -0
  94. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/Logs.py +0 -0
  95. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/Monte_Carlo.py +0 -0
  96. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/Optimization_Parameters.py +0 -0
  97. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/Quick_Start.py +0 -0
  98. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/README.md +0 -0
  99. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/Settings.py +0 -0
  100. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/Wages_And_Contributions.py +0 -0
  101. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/Worksheets.py +0 -0
  102. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/main+fonts.py +0 -0
  103. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/main.py +0 -0
  104. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/owlbridge.py +0 -0
  105. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/plots.py +0 -0
  106. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/progress.py +0 -0
  107. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/style.css +0 -0
  108. {owlplanner-2025.3.11 → owlplanner-2025.3.13}/ui/tomlexamples.py +0 -0
@@ -1,33 +1,33 @@
1
- {
2
- "name": "Python 3",
3
- // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
4
- "image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye",
5
- "customizations": {
6
- "codespaces": {
7
- "openFiles": [
8
- "README.md",
9
- "ui/main.py"
10
- ]
11
- },
12
- "vscode": {
13
- "settings": {},
14
- "extensions": [
15
- "ms-python.python",
16
- "ms-python.vscode-pylance"
17
- ]
18
- }
19
- },
20
- "updateContentCommand": "[ -f packages.txt ] && sudo apt update && sudo apt upgrade -y && sudo xargs apt install -y <packages.txt; [ -f requirements.txt ] && pip3 install --user -r requirements.txt; pip3 install --user streamlit; echo '✅ Packages installed and Requirements met'",
21
- "postAttachCommand": {
22
- "server": "streamlit run ui/main.py --server.enableCORS false --server.enableXsrfProtection false"
23
- },
24
- "portsAttributes": {
25
- "8501": {
26
- "label": "Application",
27
- "onAutoForward": "openPreview"
28
- }
29
- },
30
- "forwardPorts": [
31
- 8501
32
- ]
1
+ {
2
+ "name": "Python 3",
3
+ // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
4
+ "image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye",
5
+ "customizations": {
6
+ "codespaces": {
7
+ "openFiles": [
8
+ "README.md",
9
+ "ui/main.py"
10
+ ]
11
+ },
12
+ "vscode": {
13
+ "settings": {},
14
+ "extensions": [
15
+ "ms-python.python",
16
+ "ms-python.vscode-pylance"
17
+ ]
18
+ }
19
+ },
20
+ "updateContentCommand": "[ -f packages.txt ] && sudo apt update && sudo apt upgrade -y && sudo xargs apt install -y <packages.txt; [ -f requirements.txt ] && pip3 install --user -r requirements.txt; pip3 install --user streamlit; echo '✅ Packages installed and Requirements met'",
21
+ "postAttachCommand": {
22
+ "server": "streamlit run ui/main.py --server.enableCORS false --server.enableXsrfProtection false"
23
+ },
24
+ "portsAttributes": {
25
+ "8501": {
26
+ "label": "Application",
27
+ "onAutoForward": "openPreview"
28
+ }
29
+ },
30
+ "forwardPorts": [
31
+ 8501
32
+ ]
33
33
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: owlplanner
3
- Version: 2025.3.11
3
+ Version: 2025.3.13
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.11"
7
+ version = "2025.03.13"
8
8
  authors = [
9
9
  { name="Martin-D. Lacasse", email="martin.d.lacasse@gmail.com" },
10
10
  ]
@@ -34,7 +34,7 @@ from owlplanner import logging
34
34
  from owlplanner import progress
35
35
 
36
36
 
37
- # This makes all graphs appear have the same height.
37
+ # This makes all graphs to have the same height.
38
38
  plt.rcParams.update({'figure.autolayout': True})
39
39
 
40
40
 
@@ -2094,33 +2094,33 @@ class Plan(object):
2094
2094
  totIncome = np.sum(self.g_n, axis=0)
2095
2095
  totIncomeNow = np.sum(self.g_n / self.gamma_n[:-1], axis=0)
2096
2096
  dic["Total net spending"] = f"{u.d(totIncomeNow)}"
2097
- dic["- Total net spending (nominal)"] = f"{u.d(totIncome)}"
2097
+ dic["[Total net spending]"] = f"{u.d(totIncome)}"
2098
2098
 
2099
2099
  totRoth = np.sum(self.x_in, axis=(0, 1))
2100
2100
  totRothNow = np.sum(np.sum(self.x_in, axis=0) / self.gamma_n[:-1], axis=0)
2101
2101
  dic["Total Roth conversions"] = f"{u.d(totRothNow)}"
2102
- dic["- Total Roth conversions (nominal)"] = f"{u.d(totRoth)}"
2102
+ dic["[Total Roth conversions]"] = f"{u.d(totRoth)}"
2103
2103
 
2104
2104
  taxPaid = np.sum(self.T_n, axis=0)
2105
2105
  taxPaidNow = np.sum(self.T_n / self.gamma_n[:-1], axis=0)
2106
2106
  dic["Total income tax paid on ordinary income"] = f"{u.d(taxPaidNow)}"
2107
- dic["- Total income tax paid on ordinary income (nominal)"] = f"{u.d(taxPaid)}"
2107
+ dic["[Total income tax paid on ordinary income]"] = f"{u.d(taxPaid)}"
2108
2108
  for t in range(self.N_t):
2109
2109
  taxPaid = np.sum(self.T_tn[t], axis=0)
2110
2110
  taxPaidNow = np.sum(self.T_tn[t] / self.gamma_n[:-1], axis=0)
2111
2111
  tname = tx.taxBracketNames[t]
2112
2112
  dic[f"-- Subtotal in tax bracket {tname}"] = f"{u.d(taxPaidNow)}"
2113
- dic[f"--- Subtotal in tax bracket {tname} (nominal)"] = f"{u.d(taxPaid)}"
2113
+ dic[f"-- [Subtotal in tax bracket {tname}]"] = f"{u.d(taxPaid)}"
2114
2114
 
2115
2115
  taxPaid = np.sum(self.U_n, axis=0)
2116
2116
  taxPaidNow = np.sum(self.U_n / self.gamma_n[:-1], axis=0)
2117
2117
  dic["Total tax paid on gains and dividends"] = f"{u.d(taxPaidNow)}"
2118
- dic["- Total tax paid on gains and dividends (nominal)"] = f"{u.d(taxPaid)}"
2118
+ dic["[Total tax paid on gains and dividends]"] = f"{u.d(taxPaid)}"
2119
2119
 
2120
2120
  taxPaid = np.sum(self.M_n, axis=0)
2121
2121
  taxPaidNow = np.sum(self.M_n / self.gamma_n[:-1], axis=0)
2122
2122
  dic["Total Medicare premiums paid"] = f"{u.d(taxPaidNow)}"
2123
- dic["- Total Medicare premiums paid (nominal)"] = f"{u.d(taxPaid)}"
2123
+ dic["[Total Medicare premiums paid]"] = f"{u.d(taxPaid)}"
2124
2124
 
2125
2125
  if self.N_i == 2 and self.n_d < self.N_n:
2126
2126
  p_j = self.partialEstate_j * (1 - self.phi_j)
@@ -2135,24 +2135,24 @@ class Plan(object):
2135
2135
  iname_s = self.inames[self.i_s]
2136
2136
  iname_d = self.inames[self.i_d]
2137
2137
  dic[f"Sum of spousal transfer to {iname_s} in year {ynx}"] = (f"{u.d(totSpousalNow)}")
2138
- dic[f"- Sum of spousal transfer to {iname_s} in year {ynx} (nominal)"] = (
2138
+ dic[f"[Sum of spousal transfer to {iname_s} in year {ynx}]"] = (
2139
2139
  f"{u.d(totSpousal)}")
2140
- dic[f"-- Spousal transfer to {iname_s} in year {ynx} - taxable (nominal)"] = (
2140
+ dic[f"-- [Spousal transfer to {iname_s} in year {ynx} - taxable]"] = (
2141
2141
  f"{u.d(q_j[0])}")
2142
- dic[f"-- Spousal transfer to {iname_s} in year {ynx} - tax-def (nominal)"] = (
2142
+ dic[f"-- [Spousal transfer to {iname_s} in year {ynx} - tax-def]"] = (
2143
2143
  f"{u.d(q_j[1])}")
2144
- dic[f"-- Spousal transfer to {iname_s} in year {ynx} - tax-free (nominal)"] = (
2144
+ dic[f"-- [Spousal transfer to {iname_s} in year {ynx} - tax-free]"] = (
2145
2145
  f"{u.d(q_j[2])}")
2146
2146
 
2147
2147
  dic[f"Sum of post-tax non-spousal bequests from {iname_d} in year {ynx}"] = (
2148
2148
  f"{u.d(totOthersNow)}")
2149
- dic[f"- Sum of post-tax non-spousal bequests from {iname_d} in year {ynx} (nominal)"] = (
2149
+ dic[f"[Sum of post-tax non-spousal bequests from {iname_d} in year {ynx}]"] = (
2150
2150
  f"{u.d(totOthers)}")
2151
- dic[f"-- Post-tax non-spousal bequests from {iname_d} in year {ynx} - taxable (nominal)"] = (
2151
+ dic[f"-- [Post-tax non-spousal bequests from {iname_d} in year {ynx} - taxable]"] = (
2152
2152
  f"{u.d(p_j[0])}")
2153
- dic[f"-- Post-tax non-spousal bequests from {iname_d} in year {ynx} - tax-def (nominal)"] = (
2153
+ dic[f"-- [Post-tax non-spousal bequests from {iname_d} in year {ynx} - tax-def]"] = (
2154
2154
  f"{u.d(p_j[1])}")
2155
- dic[f"-- Post-tax non-spousal bequests from {iname_d} in year {ynx} - tax-free (nominal)"] = (
2155
+ dic[f"-- [Post-tax non-spousal bequests from {iname_d} in year {ynx} - tax-free]"] = (
2156
2156
  f"{u.d(p_j[2])}")
2157
2157
 
2158
2158
  estate = np.sum(self.b_ijn[:, :, self.N_n], axis=0)
@@ -2161,10 +2161,10 @@ class Plan(object):
2161
2161
  totEstate = np.sum(estate)
2162
2162
  totEstateNow = totEstate / self.gamma_n[-1]
2163
2163
  dic[f"Total estate value at the end of {lastyear}"] = (f"{u.d(totEstateNow)}")
2164
- dic[f"- Total estate value at the end of {lastyear} (nominal)"] = (f"{u.d(totEstate)}")
2165
- dic[f"-- Post-tax account value at the end of {lastyear} - taxable (nominal)"] = (f"{u.d(estate[0])}")
2166
- dic[f"-- Post-tax account value at the end of {lastyear} - tax-def (nominal)"] = (f"{u.d(estate[1])}")
2167
- dic[f"-- Post-tax account value at the end of {lastyear} - tax-free (nominal)"] = (f"{u.d(estate[2])}")
2164
+ dic[f"[Total estate value at the end of {lastyear}]"] = (f"{u.d(totEstate)}")
2165
+ dic[f"-- [Post-tax account value at the end of {lastyear} - taxable]"] = (f"{u.d(estate[0])}")
2166
+ dic[f"-- [Post-tax account value at the end of {lastyear} - tax-def]"] = (f"{u.d(estate[1])}")
2167
+ dic[f"-- [Post-tax account value at the end of {lastyear} - tax-free]"] = (f"{u.d(estate[2])}")
2168
2168
 
2169
2169
  dic["Plan starting date"] = str(self.startDate)
2170
2170
  dic[f"Cumulative inflation factor from start date to end of {lastyear}"] = (f"{self.gamma_n[-1]:.2f}")
@@ -0,0 +1 @@
1
+ __version__ = "2025.03.13"
@@ -8,7 +8,7 @@ st.write("## About Owl 🦉")
8
8
  kz.orangeDivider()
9
9
 
10
10
  st.write(f"This is Owl version {owb.version()} running on Streamlit {st.__version__}.")
11
- st.snow()
11
+ # st.balloons()
12
12
 
13
13
  st.write(
14
14
  """
@@ -53,6 +53,13 @@ reported as yearly values. These include wages, income, rates, social security,
53
53
  Dollar values are typically entered in thousands, unless in tables, where they
54
54
  are entered and reported in unit dollars.
55
55
 
56
+ If you are accessing Owl through the Chrome browser,
57
+ the performance manager might be configured to disable hidden or inactive tabs.
58
+ This will cause your Owl session to inadvertently reset, and losing the state of the calculator.
59
+ To avoid this, configure Chrome to keep the page active using
60
+ `More Tools` -> `Performance` -> `Always keep these sites active` and
61
+ add the site *owlplanner.streamlit.app*.
62
+
56
63
  There are four sections in the user interface:
57
64
  **Case Setup**, **Single Scenario**, **Multiple Scenarios**, and **Resources**.
58
65
  The sections below follow the same logical order.
@@ -18,8 +18,9 @@ else:
18
18
  df = kz.compareSummaries()
19
19
  if df is not None:
20
20
  st.write("#### Synopsis")
21
- st.dataframe(df[1:], use_container_width=True)
22
- st.caption("Values are in today's \\$ unless marked otherwise.")
21
+ styledDf = df[1:].style.map(kz.colorBySign)
22
+ st.dataframe(styledDf, use_container_width=True)
23
+ st.caption("Values with [legend] are nominal, otherwise in today's \\$.")
23
24
  st.download_button(
24
25
  "Download synopsis", data=df[1:].to_string(), file_name=f"Synopsis_{caseName}.txt",
25
26
  mime="text/plain;charset=UTF-8"
@@ -228,5 +228,5 @@ else:
228
228
 
229
229
  with col3:
230
230
  kz.initKey("yTCJA", 2026)
231
- helpmsg = "Year at which the Tax Cut And Job Act tax rates are speculated to expire."
231
+ helpmsg = "Year at which the Tax Cut And Job Act tax rates are speculated to be expired."
232
232
  ret = kz.getIntNum("TCJA expiration year", "yTCJA", help=helpmsg)
@@ -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.11
10
+ owlplanner >= 2025.03.13
@@ -313,6 +313,12 @@ def getAccountBalances(ni):
313
313
  return bal
314
314
 
315
315
 
316
+ def colorBySign(val):
317
+ color = "green" if "\u2191" in val else "red" if "\u2193" in val else None
318
+
319
+ return f"color:{color};" if color else ""
320
+
321
+
316
322
  def compareSummaries():
317
323
  df = getKey("summaryDf")
318
324
  if df is None:
@@ -504,7 +510,6 @@ def orangeDivider():
504
510
 
505
511
 
506
512
  def titleBar(txt, choices=None):
507
- # st.html(f"<div style='text-align: left;color: orange;font-style: italic;'>{currentCaseName()}</div>")
508
513
  if choices is None:
509
514
  choices = onlyCaseNames()
510
515
  helpmsg = "Select an existing case."
@@ -1 +0,0 @@
1
- __version__ = "2025.03.11"
File without changes
File without changes
File without changes
File without changes