owlplanner 2025.12.20__py3-none-any.whl → 2026.1.26__py3-none-any.whl
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.
- owlplanner/In Discussion #58, the case of Kim and Sam.md +307 -0
- owlplanner/__init__.py +20 -1
- owlplanner/abcapi.py +18 -17
- owlplanner/cli/README.md +50 -0
- owlplanner/cli/_main.py +52 -0
- owlplanner/cli/cli_logging.py +56 -0
- owlplanner/cli/cmd_list.py +83 -0
- owlplanner/cli/cmd_run.py +86 -0
- owlplanner/config.py +300 -117
- owlplanner/data/__init__.py +21 -0
- owlplanner/data/rates.csv +99 -98
- owlplanner/debts.py +36 -8
- owlplanner/fixedassets.py +95 -21
- owlplanner/mylogging.py +157 -25
- owlplanner/plan.py +793 -349
- owlplanner/plotting/__init__.py +16 -3
- owlplanner/plotting/base.py +17 -3
- owlplanner/plotting/factory.py +16 -3
- owlplanner/plotting/matplotlib_backend.py +30 -7
- owlplanner/plotting/plotly_backend.py +32 -9
- owlplanner/progress.py +16 -3
- owlplanner/rates.py +366 -361
- owlplanner/socialsecurity.py +28 -19
- owlplanner/tax2026.py +109 -30
- owlplanner/timelists.py +194 -18
- owlplanner/utils.py +179 -4
- owlplanner/version.py +20 -1
- {owlplanner-2025.12.20.dist-info → owlplanner-2026.1.26.dist-info}/METADATA +10 -2
- owlplanner-2026.1.26.dist-info/RECORD +36 -0
- owlplanner-2026.1.26.dist-info/entry_points.txt +2 -0
- owlplanner-2026.1.26.dist-info/licenses/AUTHORS +15 -0
- owlplanner/tax2025.py +0 -359
- owlplanner-2025.12.20.dist-info/RECORD +0 -29
- {owlplanner-2025.12.20.dist-info → owlplanner-2026.1.26.dist-info}/WHEEL +0 -0
- {owlplanner-2025.12.20.dist-info → owlplanner-2026.1.26.dist-info}/licenses/LICENSE +0 -0
owlplanner/plotting/__init__.py
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Plotting backends for Owl.
|
|
2
|
+
Plotting backends package for Owl retirement planner.
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
This package provides a factory pattern for creating plot backends (matplotlib,
|
|
5
|
+
plotly) for visualizing retirement planning results.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
Copyright (C) 2025-2026 The Owlplanner Authors
|
|
7
8
|
|
|
9
|
+
This program is free software: you can redistribute it and/or modify
|
|
10
|
+
it under the terms of the GNU General Public License as published by
|
|
11
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
(at your option) any later version.
|
|
13
|
+
|
|
14
|
+
This program is distributed in the hope that it will be useful,
|
|
15
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
GNU General Public License for more details.
|
|
18
|
+
|
|
19
|
+
You should have received a copy of the GNU General Public License
|
|
20
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
8
21
|
"""
|
|
9
22
|
|
|
10
23
|
from .factory import PlotFactory
|
owlplanner/plotting/base.py
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Abstract base classes for plot backends.
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
This module defines the abstract base class interface that all plotting
|
|
5
|
+
backends must implement for consistent plotting functionality across
|
|
6
|
+
different visualization libraries.
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
Copyright (C) 2025-2026 The Owlplanner Authors
|
|
7
9
|
|
|
10
|
+
This program is free software: you can redistribute it and/or modify
|
|
11
|
+
it under the terms of the GNU General Public License as published by
|
|
12
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
13
|
+
(at your option) any later version.
|
|
14
|
+
|
|
15
|
+
This program is distributed in the hope that it will be useful,
|
|
16
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
17
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
18
|
+
GNU General Public License for more details.
|
|
19
|
+
|
|
20
|
+
You should have received a copy of the GNU General Public License
|
|
21
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
8
22
|
"""
|
|
9
23
|
|
|
10
24
|
from abc import ABC, abstractmethod
|
owlplanner/plotting/factory.py
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Factory for creating plot
|
|
2
|
+
Factory for creating plot backend instances.
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
This module provides a factory class to create plot backends (matplotlib or
|
|
5
|
+
plotly) based on the specified backend type.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
Copyright (C) 2025-2026 The Owlplanner Authors
|
|
7
8
|
|
|
9
|
+
This program is free software: you can redistribute it and/or modify
|
|
10
|
+
it under the terms of the GNU General Public License as published by
|
|
11
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
(at your option) any later version.
|
|
13
|
+
|
|
14
|
+
This program is distributed in the hope that it will be useful,
|
|
15
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
GNU General Public License for more details.
|
|
18
|
+
|
|
19
|
+
You should have received a copy of the GNU General Public License
|
|
20
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
8
21
|
"""
|
|
9
22
|
|
|
10
23
|
from .base import PlotBackend
|
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Matplotlib implementation
|
|
2
|
+
Matplotlib backend implementation for plotting retirement planning results.
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
This module provides the Matplotlib-based implementation of the plot backend
|
|
5
|
+
interface for creating static visualizations of retirement planning data.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
Copyright (C) 2025-2026 The Owlplanner Authors
|
|
7
8
|
|
|
9
|
+
This program is free software: you can redistribute it and/or modify
|
|
10
|
+
it under the terms of the GNU General Public License as published by
|
|
11
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
(at your option) any later version.
|
|
13
|
+
|
|
14
|
+
This program is distributed in the hope that it will be useful,
|
|
15
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
GNU General Public License for more details.
|
|
18
|
+
|
|
19
|
+
You should have received a copy of the GNU General Public License
|
|
20
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
8
21
|
"""
|
|
9
22
|
|
|
10
23
|
import numpy as np
|
|
@@ -65,10 +78,20 @@ class MatplotlibBackend(PlotBackend):
|
|
|
65
78
|
"""Core function for stacked plots."""
|
|
66
79
|
nonzeroSeries = {}
|
|
67
80
|
for sname in snames:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
81
|
+
source_data = series[sname]
|
|
82
|
+
# Check if this is a household-level source (shape (1, N_n) when N_i > 1)
|
|
83
|
+
is_household = source_data.shape[0] == 1 and len(inames) > 1
|
|
84
|
+
if is_household:
|
|
85
|
+
# Show household total once without individual name
|
|
86
|
+
tmp = source_data[0]
|
|
87
|
+
if abs(sum(tmp)) > 1.0: # Use abs for debts
|
|
88
|
+
nonzeroSeries[sname] = tmp
|
|
89
|
+
else:
|
|
90
|
+
# Show per individual
|
|
91
|
+
for i in irange:
|
|
92
|
+
tmp = source_data[i]
|
|
93
|
+
if abs(sum(tmp)) > 1.0: # Use abs for debts
|
|
94
|
+
nonzeroSeries[sname + " " + inames[i]] = tmp
|
|
72
95
|
|
|
73
96
|
if len(nonzeroSeries) == 0:
|
|
74
97
|
return None, None
|
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Plotly implementation
|
|
2
|
+
Plotly backend implementation for plotting retirement planning results.
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
This module provides the Plotly-based implementation of the plot backend
|
|
5
|
+
interface for creating interactive visualizations of retirement planning data.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
Copyright (C) 2025-2026 The Owlplanner Authors
|
|
7
8
|
|
|
9
|
+
This program is free software: you can redistribute it and/or modify
|
|
10
|
+
it under the terms of the GNU General Public License as published by
|
|
11
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
(at your option) any later version.
|
|
13
|
+
|
|
14
|
+
This program is distributed in the hope that it will be useful,
|
|
15
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
GNU General Public License for more details.
|
|
18
|
+
|
|
19
|
+
You should have received a copy of the GNU General Public License
|
|
20
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
8
21
|
"""
|
|
9
22
|
|
|
10
23
|
import numpy as np
|
|
@@ -749,7 +762,7 @@ class PlotlyBackend(PlotBackend):
|
|
|
749
762
|
|
|
750
763
|
# Add each individual's data as a separate series
|
|
751
764
|
for i in range(len(inames)):
|
|
752
|
-
if np.sum(values[i]) > 1.0: # Only show non-zero series
|
|
765
|
+
if np.abs(np.sum(values[i])) > 1.0: # Only show non-zero series (use abs for debts)
|
|
753
766
|
stack_data.append((values[i], f"{namek} {inames[i]}"))
|
|
754
767
|
|
|
755
768
|
# Add stacked area traces
|
|
@@ -887,7 +900,7 @@ class PlotlyBackend(PlotBackend):
|
|
|
887
900
|
for sname in savings:
|
|
888
901
|
for i in range(len(inames)):
|
|
889
902
|
data = savings[sname][i] / 1000
|
|
890
|
-
if np.sum(data) > 1.0e-3: # Only show non-zero series
|
|
903
|
+
if np.abs(np.sum(data)) > 1.0e-3: # Only show non-zero series (use abs for debts)
|
|
891
904
|
nonzero_series[f"{sname} {inames[i]}"] = data
|
|
892
905
|
|
|
893
906
|
# Add stacked area traces for each account type
|
|
@@ -942,10 +955,20 @@ class PlotlyBackend(PlotBackend):
|
|
|
942
955
|
# Filter out zero series and create individual series names
|
|
943
956
|
nonzero_series = {}
|
|
944
957
|
for sname in sources:
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
958
|
+
source_data = sources[sname]
|
|
959
|
+
# Check if this is a household-level source (shape (1, N_n) when N_i > 1)
|
|
960
|
+
is_household = source_data.shape[0] == 1 and len(inames) > 1
|
|
961
|
+
if is_household:
|
|
962
|
+
# Show household total once without individual name
|
|
963
|
+
data = source_data[0] / 1000
|
|
964
|
+
if np.abs(np.sum(data)) > 1.0e-3: # Only show non-zero series (use abs for debts)
|
|
965
|
+
nonzero_series[sname] = data
|
|
966
|
+
else:
|
|
967
|
+
# Show per individual
|
|
968
|
+
for i in range(len(inames)):
|
|
969
|
+
data = source_data[i] / 1000
|
|
970
|
+
if np.abs(np.sum(data)) > 1.0e-3: # Only show non-zero series (use abs for debts)
|
|
971
|
+
nonzero_series[f"{sname} {inames[i]}"] = data
|
|
949
972
|
|
|
950
973
|
# Add stacked area traces for each source type
|
|
951
974
|
for source_name, data in nonzero_series.items():
|
owlplanner/progress.py
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Progress indicator for long-running operations.
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
This module provides a simple progress indicator class that displays
|
|
5
|
+
progress as a percentage on a single line that updates in place.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
Copyright (C) 2025-2026 The Owlplanner Authors
|
|
7
8
|
|
|
9
|
+
This program is free software: you can redistribute it and/or modify
|
|
10
|
+
it under the terms of the GNU General Public License as published by
|
|
11
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
(at your option) any later version.
|
|
13
|
+
|
|
14
|
+
This program is distributed in the hope that it will be useful,
|
|
15
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
GNU General Public License for more details.
|
|
18
|
+
|
|
19
|
+
You should have received a copy of the GNU General Public License
|
|
20
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
8
21
|
"""
|
|
9
22
|
|
|
10
23
|
from typing import Optional
|