owlplanner 2025.11.9__tar.gz → 2025.12.5__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.
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/PKG-INFO +12 -9
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/README.md +11 -8
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/RELEASE_NOTES.md +16 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docker/README.md +1 -1
- owlplanner-2025.12.5/docker/buildContainers.cmd +7 -0
- owlplanner-2025.12.5/docker/buildPackage.cmd +7 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/examples/case_drawdowncalc-comparison-1.toml +2 -1
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/examples/case_jack+jill.toml +2 -1
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/examples/case_joe.toml +2 -1
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/examples/case_john+sally.toml +2 -1
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/examples/case_jon+jane.toml +3 -2
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/examples/case_kim+sam-bequest.toml +2 -1
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/examples/case_kim+sam-spending.toml +2 -1
- owlplanner-2025.12.5/examples/ttt.toml +58 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/notebooks/john+sally.ipynb +2 -2
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/notebooks/kim+sam.ipynb +2 -2
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/notebooks/template.ipynb +4 -4
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/notebooks/tutorial_1.ipynb +5 -5
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/notebooks/tutorial_2.ipynb +2 -2
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/notebooks/tutorial_3.ipynb +2 -2
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/config.py +11 -8
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/plan.py +84 -39
- owlplanner-2025.12.5/src/owlplanner/socialsecurity.py +89 -0
- owlplanner-2025.12.5/src/owlplanner/version.py +1 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/tests/test_regressions.py +16 -6
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/tests/test_repro.py +14 -13
- owlplanner-2025.12.5/tests/test_socsec.py +72 -0
- owlplanner-2025.12.5/ui/AI +48 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/About_Owl.py +1 -1
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/Create_Case.py +16 -4
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/Documentation.py +89 -42
- owlplanner-2025.12.5/ui/Fixed_Income.py +94 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/Quick_Start.py +17 -14
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/Wages_and_Contributions.py +2 -2
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/owlbridge.py +10 -5
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/sskeys.py +5 -2
- owlplanner-2025.11.9/src/owlplanner/version.py +0 -1
- owlplanner-2025.11.9/ui/Fixed_Income.py +0 -68
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/.devcontainer/devcontainer.json +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/.flake8 +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/.gitattributes +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/.github/workflows/github-actions-runtests.yml +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/.gitignore +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/.streamlit/config.toml +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/.streamlit/fullconfig.toml +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/INSTALL.md +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/LICENSE +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/USER_GUIDE.md +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docker/Dockerfile.bare +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docker/Dockerfile.static +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docker/buildentrypoint.sh +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docker/docker-compose.yml +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docker/runentrypoint.sh +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/AD-taxDef.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/AD-taxFree.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/AD-taxable.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/Hist_Bequest.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/Hist_Spending.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/MC-tutorial2a.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/MC-tutorial2b.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/OwlUI.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/allocations.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/owl.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/piecewiseConstant.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/profile.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/ratesCorrelations.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/ratesPlot.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/savingsPlot.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/sourcesPlot.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/spendingPlot.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/taxIncomePlot.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/images/taxesPlot.png +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/owl.pdf +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/docs/owl.tex +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/examples/jack+jill.xlsx +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/examples/joe.xlsx +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/examples/john+sally.xlsx +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/examples/jon+jane.xlsx +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/examples/kim+sam.xlsx +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/examples/template.xlsx +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/owlplanner.cmd +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/owlplanner.sh +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/pyproject.toml +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/pytest.ini +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/requirements.txt +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/__init__.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/abcapi.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/data/__init__.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/data/rates.csv +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/mylogging.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/plotting/__init__.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/plotting/base.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/plotting/factory.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/plotting/matplotlib_backend.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/plotting/plotly_backend.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/progress.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/rates.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/tax2025.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/tax2026.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/timelists.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/src/owlplanner/utils.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/tests/test_logger.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/tests/test_toml_cases.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/tests/test_ui_asset_allocation.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/tests/test_ui_compare_summaries.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/tests/test_ui_sskeys.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/tests/test_units.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/Asset_Allocation.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/Current_Assets.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/Graphs.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/Historical_Range.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/Logs.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/Monte_Carlo.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/Optimization_Parameters.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/Output_Files.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/README.md +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/Rates_Selection.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/Settings.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/Worksheets.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/__init__.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/main.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/progress.py +0 -0
- {owlplanner-2025.11.9 → owlplanner-2025.12.5}/ui/tomlexamples.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: owlplanner
|
|
3
|
-
Version: 2025.
|
|
3
|
+
Version: 2025.12.5
|
|
4
4
|
Summary: Owl - Optimal Wealth Lab: 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
|
|
@@ -722,16 +722,16 @@ Users can select varying return rates to perform historical back testing,
|
|
|
722
722
|
stochastic rates for performing Monte Carlo analyses,
|
|
723
723
|
or fixed rates either derived from historical averages, or set by the user.
|
|
724
724
|
|
|
725
|
-
There are
|
|
725
|
+
There are three ways to run Owl:
|
|
726
726
|
|
|
727
|
-
- Run Owl
|
|
727
|
+
- **Streamlit Hub:** Run Owl remotely as hosted on the Streamlit Community Server at
|
|
728
728
|
[owlplanner.streamlit.app](https://owlplanner.streamlit.app).
|
|
729
729
|
|
|
730
|
-
- Run locally on your computer using a Docker image.
|
|
731
|
-
Follow these [instructions](docker/README.md) for this option.
|
|
730
|
+
- **Docker Container:** Run Owl locally on your computer using a Docker image.
|
|
731
|
+
Follow these [instructions](docker/README.md) for using this option.
|
|
732
732
|
|
|
733
|
-
- Run locally on your computer using Python code and libraries.
|
|
734
|
-
Follow these [instructions](INSTALL.md) to install
|
|
733
|
+
- **Self-hosting:** Run Owl locally on your computer using Python code and libraries.
|
|
734
|
+
Follow these [instructions](INSTALL.md) to install from the source code and self-host on your own computer.
|
|
735
735
|
|
|
736
736
|
-------------------------------------------------------------------------------------
|
|
737
737
|
## Overview
|
|
@@ -760,7 +760,7 @@ There are and were
|
|
|
760
760
|
good retirement optimizers in the recent past, but the vast majority of them are either proprietary platforms
|
|
761
761
|
collecting your data, or academic papers that share the results without really sharing the details of
|
|
762
762
|
the underlying mathematical models.
|
|
763
|
-
The algorithms in Owl rely on the open-source HiGHS linear programming solver
|
|
763
|
+
The algorithms in Owl rely on the open-source HiGHS linear programming solver but they have also been ported and tested on
|
|
764
764
|
other platforms such as Mosek and COIN-OR. The complete formulation and
|
|
765
765
|
detailed description of the underlying
|
|
766
766
|
mathematical model can be found [here](https://github.com/mdlacasse/Owl/blob/main/docs/owl.pdf).
|
|
@@ -849,13 +849,16 @@ They can also be optimized explicitly as an option, but this choice can lead to
|
|
|
849
849
|
due to the use of the many additional binary variables required by the formulation.
|
|
850
850
|
Future Medicare and IRMAA values are simple projections of current values with the assumed inflation rates.
|
|
851
851
|
|
|
852
|
+
Owl has a basic social security calculator that determines the actual benefits based on the individual's
|
|
853
|
+
primary insurance amount (PIA), full retirement age (FRA), and claiming age. Both
|
|
854
|
+
spousal's benefits and survivor's benefits are calculated for non-complex cases.
|
|
855
|
+
|
|
852
856
|
### Limitations
|
|
853
857
|
Owl is work in progress. At the current time:
|
|
854
858
|
- Only the US federal income tax is considered (and minimized through the optimization algorithm).
|
|
855
859
|
Head of household filing status has not been added but can easily be.
|
|
856
860
|
- Required minimum distributions are calculated, but tables for spouses more than 10 years apart are not included.
|
|
857
861
|
These cases are detected and will generate an error message.
|
|
858
|
-
- Social security rule for surviving spouse assumes that benefits were taken at full retirement age.
|
|
859
862
|
- Current version has no optimization of asset allocations between individuals and/or types of savings accounts.
|
|
860
863
|
If there is interest, that could be added in the future.
|
|
861
864
|
- In the current implementation, social securiy is always taxed at 85%, assuming that your taxable income will be larger than 34 k$ (single) or 44 k$ (married filing jointly).
|
|
@@ -15,16 +15,16 @@ Users can select varying return rates to perform historical back testing,
|
|
|
15
15
|
stochastic rates for performing Monte Carlo analyses,
|
|
16
16
|
or fixed rates either derived from historical averages, or set by the user.
|
|
17
17
|
|
|
18
|
-
There are
|
|
18
|
+
There are three ways to run Owl:
|
|
19
19
|
|
|
20
|
-
- Run Owl
|
|
20
|
+
- **Streamlit Hub:** Run Owl remotely as hosted on the Streamlit Community Server at
|
|
21
21
|
[owlplanner.streamlit.app](https://owlplanner.streamlit.app).
|
|
22
22
|
|
|
23
|
-
- Run locally on your computer using a Docker image.
|
|
24
|
-
Follow these [instructions](docker/README.md) for this option.
|
|
23
|
+
- **Docker Container:** Run Owl locally on your computer using a Docker image.
|
|
24
|
+
Follow these [instructions](docker/README.md) for using this option.
|
|
25
25
|
|
|
26
|
-
- Run locally on your computer using Python code and libraries.
|
|
27
|
-
Follow these [instructions](INSTALL.md) to install
|
|
26
|
+
- **Self-hosting:** Run Owl locally on your computer using Python code and libraries.
|
|
27
|
+
Follow these [instructions](INSTALL.md) to install from the source code and self-host on your own computer.
|
|
28
28
|
|
|
29
29
|
-------------------------------------------------------------------------------------
|
|
30
30
|
## Overview
|
|
@@ -53,7 +53,7 @@ There are and were
|
|
|
53
53
|
good retirement optimizers in the recent past, but the vast majority of them are either proprietary platforms
|
|
54
54
|
collecting your data, or academic papers that share the results without really sharing the details of
|
|
55
55
|
the underlying mathematical models.
|
|
56
|
-
The algorithms in Owl rely on the open-source HiGHS linear programming solver
|
|
56
|
+
The algorithms in Owl rely on the open-source HiGHS linear programming solver but they have also been ported and tested on
|
|
57
57
|
other platforms such as Mosek and COIN-OR. The complete formulation and
|
|
58
58
|
detailed description of the underlying
|
|
59
59
|
mathematical model can be found [here](https://github.com/mdlacasse/Owl/blob/main/docs/owl.pdf).
|
|
@@ -142,13 +142,16 @@ They can also be optimized explicitly as an option, but this choice can lead to
|
|
|
142
142
|
due to the use of the many additional binary variables required by the formulation.
|
|
143
143
|
Future Medicare and IRMAA values are simple projections of current values with the assumed inflation rates.
|
|
144
144
|
|
|
145
|
+
Owl has a basic social security calculator that determines the actual benefits based on the individual's
|
|
146
|
+
primary insurance amount (PIA), full retirement age (FRA), and claiming age. Both
|
|
147
|
+
spousal's benefits and survivor's benefits are calculated for non-complex cases.
|
|
148
|
+
|
|
145
149
|
### Limitations
|
|
146
150
|
Owl is work in progress. At the current time:
|
|
147
151
|
- Only the US federal income tax is considered (and minimized through the optimization algorithm).
|
|
148
152
|
Head of household filing status has not been added but can easily be.
|
|
149
153
|
- Required minimum distributions are calculated, but tables for spouses more than 10 years apart are not included.
|
|
150
154
|
These cases are detected and will generate an error message.
|
|
151
|
-
- Social security rule for surviving spouse assumes that benefits were taken at full retirement age.
|
|
152
155
|
- Current version has no optimization of asset allocations between individuals and/or types of savings accounts.
|
|
153
156
|
If there is interest, that could be added in the future.
|
|
154
157
|
- In the current implementation, social securiy is always taxed at 85%, assuming that your taxable income will be larger than 34 k$ (single) or 44 k$ (married filing jointly).
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
### Version 2025.12.05
|
|
2
|
+
- Added instructions for obtaining PIA
|
|
3
|
+
- Bug fix in Fixed Income UI
|
|
4
|
+
|
|
5
|
+
### Version 2025.12.03
|
|
6
|
+
- Coded social security to use monthly PIA instead of annual amount
|
|
7
|
+
- Added exact routines for FRA and increase/decrease factors due to claiming age
|
|
8
|
+
- Added exact spousal benefits
|
|
9
|
+
- Adjusted documentation for social security
|
|
10
|
+
- Added birth month for more precise calculation on first year of social security
|
|
11
|
+
- Added month to age for claiming social security
|
|
12
|
+
|
|
13
|
+
### Version 2025.11.29
|
|
14
|
+
- Fixed social security for survivor
|
|
15
|
+
- Enhanced documentation for SS amounts
|
|
16
|
+
|
|
1
17
|
### Version 2025.11.09
|
|
2
18
|
- Moved development status to production/stable in pyproject
|
|
3
19
|
- Made version propagate everywhere needed
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
This document describes how to run Owl using a Docker container.
|
|
10
10
|
|
|
11
11
|
------------------------------------------------------------------------------------
|
|
12
|
-
###
|
|
12
|
+
### Running Owl without the source code
|
|
13
13
|
Using this approach only requires downloading the Docker image from
|
|
14
14
|
the [Docker Hub](http://hub.docker.com) and having the [Docker](http://docker.com)
|
|
15
15
|
application installed on your computer.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
::
|
|
2
|
+
:: A simple script to build both Docker images
|
|
3
|
+
::
|
|
4
|
+
docker build --no-cache -f Dockerfile.bare -t owlplanner/owldocker.bare:latest .
|
|
5
|
+
docker push owlplanner/owldocker.bare
|
|
6
|
+
docker build --no-cache -f Dockerfile.static -t owlplanner/owldocker.static:latest .
|
|
7
|
+
docker push owlplanner/owldocker.static
|
|
@@ -5,6 +5,7 @@ Description = "This is a case involving a single individual. Case is used for co
|
|
|
5
5
|
Status = "single"
|
|
6
6
|
Names = [ "Charles",]
|
|
7
7
|
"Birth year" = [ 1966,]
|
|
8
|
+
"Birth month" = [ 1,]
|
|
8
9
|
"Life expectancy" = [ 89,]
|
|
9
10
|
"Start date" = "2025-01-01"
|
|
10
11
|
|
|
@@ -20,7 +21,7 @@ Names = [ "Charles",]
|
|
|
20
21
|
"Pension amounts" = [ 0.0,]
|
|
21
22
|
"Pension ages" = [ 65,]
|
|
22
23
|
"Pension indexed" = [ true,]
|
|
23
|
-
"Social security amounts" = [
|
|
24
|
+
"Social security PIA amounts" = [ 3000,]
|
|
24
25
|
"Social security ages" = [ 70,]
|
|
25
26
|
|
|
26
27
|
["Rates Selection"]
|
|
@@ -5,6 +5,7 @@ Description = "This example aims to demonstrate some of Owl's capabilities. Jack
|
|
|
5
5
|
Status = "married"
|
|
6
6
|
Names = [ "Jack", "Jill",]
|
|
7
7
|
"Birth year" = [ 1962, 1965,]
|
|
8
|
+
"Birth month" = [ 1, 1,]
|
|
8
9
|
"Life expectancy" = [ 89, 92,]
|
|
9
10
|
"Start date" = "01-01"
|
|
10
11
|
|
|
@@ -22,7 +23,7 @@ Names = [ "Jack", "Jill",]
|
|
|
22
23
|
"Pension amounts" = [ 0.0, 10.5,]
|
|
23
24
|
"Pension ages" = [ 65, 65,]
|
|
24
25
|
"Pension indexed" = [ false, false,]
|
|
25
|
-
"Social security amounts" = [
|
|
26
|
+
"Social security PIA amounts" = [ 2360, 1642,]
|
|
26
27
|
"Social security ages" = [ 70, 62,]
|
|
27
28
|
|
|
28
29
|
["Rates Selection"]
|
|
@@ -5,6 +5,7 @@ Description = "This is an example of a case involving a single individual. Joe i
|
|
|
5
5
|
Status = "single"
|
|
6
6
|
Names = [ "Joe",]
|
|
7
7
|
"Birth year" = [ 1966,]
|
|
8
|
+
"Birth month" = [ 1,]
|
|
8
9
|
"Life expectancy" = [ 89,]
|
|
9
10
|
"Start date" = "01-01"
|
|
10
11
|
|
|
@@ -20,7 +21,7 @@ Names = [ "Joe",]
|
|
|
20
21
|
"Pension amounts" = [ 18.0,]
|
|
21
22
|
"Pension ages" = [ 65,]
|
|
22
23
|
"Pension indexed" = [ true,]
|
|
23
|
-
"Social security amounts" = [
|
|
24
|
+
"Social security PIA amounts" = [ 2360,]
|
|
24
25
|
"Social security ages" = [ 67,]
|
|
25
26
|
|
|
26
27
|
["Rates Selection"]
|
|
@@ -5,6 +5,7 @@ Description = "This example reproduces the case of John and Sally, discussed by
|
|
|
5
5
|
Status = "married"
|
|
6
6
|
Names = [ "John", "Sally",]
|
|
7
7
|
"Birth year" = [ 1962, 1962,]
|
|
8
|
+
"Birth month" = [ 1, 1,]
|
|
8
9
|
"Life expectancy" = [ 92, 92,]
|
|
9
10
|
"Start date" = "01-01"
|
|
10
11
|
|
|
@@ -22,7 +23,7 @@ Names = [ "John", "Sally",]
|
|
|
22
23
|
"Pension amounts" = [ 0.0, 0.0,]
|
|
23
24
|
"Pension ages" = [ 65, 65,]
|
|
24
25
|
"Pension indexed" = [ false, false,]
|
|
25
|
-
"Social security amounts" = [
|
|
26
|
+
"Social security PIA amounts" = [ 3000, 1800,]
|
|
26
27
|
"Social security ages" = [ 67, 67,]
|
|
27
28
|
|
|
28
29
|
["Rates Selection"]
|
|
@@ -5,13 +5,14 @@ Description = "This case reproduces a similar case discussed a while back on i-o
|
|
|
5
5
|
Status = "married"
|
|
6
6
|
Names = [ "Jon", "Jane",]
|
|
7
7
|
"Birth year" = [ 1965, 1968,]
|
|
8
|
+
"Birth month" = [ 1, 1,]
|
|
8
9
|
"Life expectancy" = [ 92, 92,]
|
|
9
10
|
"Start date" = "01-01"
|
|
10
11
|
|
|
11
12
|
[Assets]
|
|
12
13
|
"taxable savings balances" = [ 50.0, 0.0,]
|
|
13
14
|
"tax-deferred savings balances" = [ 900.0, 500.0,]
|
|
14
|
-
"tax-free savings balances" = [ 0.0,
|
|
15
|
+
"tax-free savings balances" = [ 0.0, 50.0,]
|
|
15
16
|
"Beneficiary fractions" = [ 1.0, 1.0, 1.0,]
|
|
16
17
|
"Spousal surplus deposit fraction" = 0.0
|
|
17
18
|
|
|
@@ -22,7 +23,7 @@ Names = [ "Jon", "Jane",]
|
|
|
22
23
|
"Pension amounts" = [ 0.0, 0.0,]
|
|
23
24
|
"Pension ages" = [ 65, 65,]
|
|
24
25
|
"Pension indexed" = [ false, false,]
|
|
25
|
-
"Social security amounts" = [
|
|
26
|
+
"Social security PIA amounts" = [ 1750, 1750,]
|
|
26
27
|
"Social security ages" = [ 65, 65,]
|
|
27
28
|
|
|
28
29
|
["Rates Selection"]
|
|
@@ -5,6 +5,7 @@ Description = "This is the case of Kim and Sam used as an example case for optim
|
|
|
5
5
|
Status = "married"
|
|
6
6
|
Names = [ "Kim", "Sam",]
|
|
7
7
|
"Birth year" = [ 1966, 1967,]
|
|
8
|
+
"Birth month" = [ 1, 1,]
|
|
8
9
|
"Life expectancy" = [ 86, 89,]
|
|
9
10
|
"Start date" = "01-01"
|
|
10
11
|
|
|
@@ -22,7 +23,7 @@ Names = [ "Kim", "Sam",]
|
|
|
22
23
|
"Pension amounts" = [ 0.0, 0.0,]
|
|
23
24
|
"Pension ages" = [ 65, 65,]
|
|
24
25
|
"Pension indexed" = [ false, false,]
|
|
25
|
-
"Social security amounts" = [
|
|
26
|
+
"Social security PIA amounts" = [ 3750, 2083,]
|
|
26
27
|
"Social security ages" = [ 70, 68,]
|
|
27
28
|
|
|
28
29
|
["Rates Selection"]
|
|
@@ -5,6 +5,7 @@ Description = "This is the case of Kim and Sam used as an example case for optim
|
|
|
5
5
|
Status = "married"
|
|
6
6
|
Names = [ "Kim", "Sam",]
|
|
7
7
|
"Birth year" = [ 1966, 1967,]
|
|
8
|
+
"Birth month" = [ 1, 1,]
|
|
8
9
|
"Life expectancy" = [ 86, 89,]
|
|
9
10
|
"Start date" = "01-01"
|
|
10
11
|
|
|
@@ -22,7 +23,7 @@ Names = [ "Kim", "Sam",]
|
|
|
22
23
|
"Pension amounts" = [ 0.0, 0.0,]
|
|
23
24
|
"Pension ages" = [ 65, 65,]
|
|
24
25
|
"Pension indexed" = [ false, false,]
|
|
25
|
-
"Social security amounts" = [
|
|
26
|
+
"Social security PIA amounts" = [ 3750, 2083,]
|
|
26
27
|
"Social security ages" = [ 70, 68,]
|
|
27
28
|
|
|
28
29
|
["Rates Selection"]
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"Plan Name" = "jack+jill"
|
|
2
|
+
Description = "This example aims to demonstrate some of Owl's capabilities. Jack and Jill are a married couple a few years from retirement. A wages and contributions file called 'jack+jill.xlsx' is associated with this case. This case uses the historical rate sequence of 1969 as a test case for guiding spending amounts from a near worst-case historical scenario. This case also demonstrates that the optimal strategy for Roth conversions does not necessarily involve surfing a tax bracket. \nA good exercise for learning Owl's capabilities is to duplicate this case and compare two scenarios: one with optimized Roth conversions and one without. Another possible exercise could involve comparing a historical retirement in 1969 vs. one taken in 1966. Or anything else you can think of..."
|
|
3
|
+
|
|
4
|
+
["Basic Info"]
|
|
5
|
+
Status = "married"
|
|
6
|
+
Names = [ "Jack", "Jill",]
|
|
7
|
+
"Birth year" = [ 1962, 1965,]
|
|
8
|
+
"Birth month" = [ 1, 1,]
|
|
9
|
+
"Life expectancy" = [ 89, 92,]
|
|
10
|
+
"Start date" = "01-01"
|
|
11
|
+
|
|
12
|
+
[Assets]
|
|
13
|
+
"taxable savings balances" = [ 120.5, 60.2,]
|
|
14
|
+
"tax-deferred savings balances" = [ 600.2, 150.0,]
|
|
15
|
+
"tax-free savings balances" = [ 280.6, 260.8,]
|
|
16
|
+
"Beneficiary fractions" = [ 1, 1, 1,]
|
|
17
|
+
"Spousal surplus deposit fraction" = 0.0
|
|
18
|
+
|
|
19
|
+
["Wages and Contributions"]
|
|
20
|
+
"Contributions file name" = "jack+jill.xlsx"
|
|
21
|
+
|
|
22
|
+
["Fixed Income"]
|
|
23
|
+
"Pension amounts" = [ 0.0, 10.5,]
|
|
24
|
+
"Pension ages" = [ 65, 65,]
|
|
25
|
+
"Pension indexed" = [ false, false,]
|
|
26
|
+
"Social security PIA amounts" = [ 2360, 1642,]
|
|
27
|
+
"Social security ages" = [ 70, 62,]
|
|
28
|
+
|
|
29
|
+
["Rates Selection"]
|
|
30
|
+
"Heirs rate on tax-deferred estate" = 30.0
|
|
31
|
+
"Dividend rate" = 1.8
|
|
32
|
+
"OBBBA expiration year" = 2032
|
|
33
|
+
Method = "historical"
|
|
34
|
+
From = 1969
|
|
35
|
+
To = 2002
|
|
36
|
+
|
|
37
|
+
["Asset Allocation"]
|
|
38
|
+
"Interpolation method" = "s-curve"
|
|
39
|
+
"Interpolation center" = 15
|
|
40
|
+
"Interpolation width" = 5
|
|
41
|
+
Type = "individual"
|
|
42
|
+
generic = [ [ [ 60, 40, 0, 0,], [ 70, 30, 0, 0,],], [ [ 60, 40, 0, 0,], [ 80, 0, 10, 10,],],]
|
|
43
|
+
|
|
44
|
+
["Optimization Parameters"]
|
|
45
|
+
"Spending profile" = "smile"
|
|
46
|
+
"Smile dip" = 15
|
|
47
|
+
"Smile increase" = 12
|
|
48
|
+
"Smile delay" = 0
|
|
49
|
+
"Surviving spouse spending percent" = 60
|
|
50
|
+
Objective = "maxSpending"
|
|
51
|
+
|
|
52
|
+
["Solver Options"]
|
|
53
|
+
maxRothConversion = 100
|
|
54
|
+
bequest = 500
|
|
55
|
+
noRothConversions = "Jill"
|
|
56
|
+
|
|
57
|
+
[Results]
|
|
58
|
+
"Default plots" = "today"
|
|
@@ -41,14 +41,14 @@
|
|
|
41
41
|
"%%time\n",
|
|
42
42
|
"import owlplanner as owl\n",
|
|
43
43
|
"\n",
|
|
44
|
-
"plan = owl.Plan(['John', 'Sally'], [1962, 1962], [92, 92], 'john+sally')\n",
|
|
44
|
+
"plan = owl.Plan(['John', 'Sally'], [1962, 1962], [1, 1], [92, 92], 'john+sally')\n",
|
|
45
45
|
"# plan.setPlotBackend(\"plotly\")\n",
|
|
46
46
|
"plan.setAccountBalances(taxable=[200, 200], taxDeferred=[750, 750], taxFree=[50, 50])\n",
|
|
47
47
|
"# Unrealistic empty contributions and wages\n",
|
|
48
48
|
"plan.readContributions('../examples/john+sally.xlsx')\n",
|
|
49
49
|
"# plan.setInterpolationMethod('s-curve')\n",
|
|
50
50
|
"plan.setAllocationRatios('individual', generic=[[[60, 40, 0, 0], [60, 40, 0, 0]], [[60, 40, 0, 0], [60, 40, 0, 0]]])\n",
|
|
51
|
-
"plan.setSocialSecurity([
|
|
51
|
+
"plan.setSocialSecurity([3000, 1800], [67, 67])\n",
|
|
52
52
|
"#plan.setSpendingProfile('smile')\n",
|
|
53
53
|
"plan.setSpendingProfile('flat')\n",
|
|
54
54
|
"plan.setRates('historical average', 1990, 2023)\n",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"outputs": [],
|
|
28
28
|
"source": [
|
|
29
29
|
"import owlplanner as owl\n",
|
|
30
|
-
"p = owl.Plan(['Kim', 'Sam'], [1966, 1967], [86, 89], 'kim+sam-spending', verbose=True)\n",
|
|
30
|
+
"p = owl.Plan(['Kim', 'Sam'], [1966, 1967], [1, 1], [86, 89], 'kim+sam-spending', verbose=True)\n",
|
|
31
31
|
"# p.setPlotBackend(\"plotly\")"
|
|
32
32
|
]
|
|
33
33
|
},
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"outputs": [],
|
|
40
40
|
"source": [
|
|
41
41
|
"# p.setPension([0, 0], [65, 65])\n",
|
|
42
|
-
"p.setSocialSecurity([
|
|
42
|
+
"p.setSocialSecurity([3750, 2083], [70, 68])"
|
|
43
43
|
]
|
|
44
44
|
},
|
|
45
45
|
{
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
"metadata": {},
|
|
136
136
|
"outputs": [],
|
|
137
137
|
"source": [
|
|
138
|
-
"plan = owl.Plan(['Kim', 'Sam'], [YYYY, YYYY], [AA, AA], 'Kim+Sam-spending', verbose=True)"
|
|
138
|
+
"plan = owl.Plan(['Kim', 'Sam'], [YYYY, YYYY], [MM, MM], [AA, AA], 'Kim+Sam-spending', verbose=True)"
|
|
139
139
|
]
|
|
140
140
|
},
|
|
141
141
|
{
|
|
@@ -340,13 +340,13 @@
|
|
|
340
340
|
"metadata": {},
|
|
341
341
|
"source": [
|
|
342
342
|
"## What about anticipated fixed income?\n",
|
|
343
|
-
"Pension and social security are fixed income.
|
|
343
|
+
"Pension and social security are fixed income. Pension income can be adjusted for inflation as social security benefits are. Numbers to be provided are the predicted annual amount for each spouse and the age of the commencement of benefits.\n",
|
|
344
344
|
"\n",
|
|
345
345
|
"By default, no pension benefits are assumed. This can also be specified explicitly by entering zeros (0) as entries, as in\n",
|
|
346
346
|
"\n",
|
|
347
|
-
" plan.setPension([0, 0], [65, 65])\n",
|
|
347
|
+
" plan.setPension([0, 0], [65, 65], [False, False])\n",
|
|
348
348
|
" \n",
|
|
349
|
-
"For social security, one must provide the predicted
|
|
349
|
+
"For social security, one must provide the predicted monthly Primary Insurance Amount(s) and the starting age(s) at which benefits are anticipated to be received. There are plenty of social security benefit estimators on the web, including the info you can get directly from your own account at the Social Security Administration (ssa.gov). Another interesting calculator can be found at www.opensocialsecurity.com. This calculator allows you to compare different scenarios regarding your commencement age through a sensitivity plot.\n"
|
|
350
350
|
]
|
|
351
351
|
},
|
|
352
352
|
{
|
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
"metadata": {},
|
|
134
134
|
"outputs": [],
|
|
135
135
|
"source": [
|
|
136
|
-
"plan = owl.Plan(['Jack', 'Jill'], [1962, 1965], [89, 92], 'jack+jill-spending-69')"
|
|
136
|
+
"plan = owl.Plan(['Jack', 'Jill'], [1962, 1965], [1, 1], [89, 92], 'jack+jill-spending-69')"
|
|
137
137
|
]
|
|
138
138
|
},
|
|
139
139
|
{
|
|
@@ -332,13 +332,13 @@
|
|
|
332
332
|
"metadata": {},
|
|
333
333
|
"source": [
|
|
334
334
|
"## What about anticipated fixed income?\n",
|
|
335
|
-
"Pension and social security are fixed income.
|
|
335
|
+
"Pension and social security are fixed income. Pension income can be inflation adjusted as social security benefits are. Numbers to be provided are the predicted annual amount for each spouse and the age of the commencement of benefits. Values are expressed in today's dollars (as do statements from the Social Security Administration).\n",
|
|
336
336
|
"\n",
|
|
337
337
|
"By default, no pension benefits are assumed. This can also be specified explicitly by entering zeros (0) as entries, as in\n",
|
|
338
338
|
"\n",
|
|
339
339
|
" plan.setPension([0, 0], [65, 65])\n",
|
|
340
340
|
" \n",
|
|
341
|
-
"For social security, one must provide the predicted
|
|
341
|
+
"For social security, one must provide the predicted monthly Primary Insurance Amount(s) and the starting age(s) at which benefits are anticipated to be received. There are plenty of social security benefit estimators on the web, including the info you can get directly from your own account at the Social Security Administration (ssa.gov). Another interesting calculator can be found at www.opensocialsecurity.com. This calculator allows you to compare different scenarios regarding your commencement age through a sensitivity plot.\n"
|
|
342
342
|
]
|
|
343
343
|
},
|
|
344
344
|
{
|
|
@@ -346,7 +346,7 @@
|
|
|
346
346
|
"id": "43bd9a2a-e2bf-434f-88ac-b0a70dcdd1fd",
|
|
347
347
|
"metadata": {},
|
|
348
348
|
"source": [
|
|
349
|
-
"Here, Jill has an unindexed pension of \\\\$10 k per year. Both Jack and Jill believe they have good genes and decided to take their social security benefits at age 70. The amounts provided (28k\\\\$ and 25k\\\\$) are estimation of the amounts they would receive at
|
|
349
|
+
"Here, Jill has an unindexed pension of \\\\$10 k per year. Both Jack and Jill believe they have good genes and decided to take their social security benefits at age 70. The amounts provided (28k\\\\$ and 25k\\\\$) are estimation of the amounts they would receive at Full Retirement Age (FRA)."
|
|
350
350
|
]
|
|
351
351
|
},
|
|
352
352
|
{
|
|
@@ -357,7 +357,7 @@
|
|
|
357
357
|
"outputs": [],
|
|
358
358
|
"source": [
|
|
359
359
|
"plan.setPension([0, 10], [65, 65])\n",
|
|
360
|
-
"plan.setSocialSecurity([
|
|
360
|
+
"plan.setSocialSecurity([2333, 2083], [70, 70])"
|
|
361
361
|
]
|
|
362
362
|
},
|
|
363
363
|
{
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
"metadata": {},
|
|
96
96
|
"outputs": [],
|
|
97
97
|
"source": [
|
|
98
|
-
"plan = owl.Plan(['Jack', 'Jill'], [1962, 1965], [89, 92], 'jack+jill-spending-MC', verbose=True)"
|
|
98
|
+
"plan = owl.Plan(['Jack', 'Jill'], [1962, 1965], [1, 1], [89, 92], 'jack+jill-spending-MC', verbose=True)"
|
|
99
99
|
]
|
|
100
100
|
},
|
|
101
101
|
{
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
"outputs": [],
|
|
146
146
|
"source": [
|
|
147
147
|
"plan.setPension([0, 10], [65, 65])\n",
|
|
148
|
-
"plan.setSocialSecurity([
|
|
148
|
+
"plan.setSocialSecurity([2333, 2083], [70, 70])"
|
|
149
149
|
]
|
|
150
150
|
},
|
|
151
151
|
{
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
"metadata": {},
|
|
96
96
|
"outputs": [],
|
|
97
97
|
"source": [
|
|
98
|
-
"plan = owl.Plan(['Jack', 'Jill'], [1962, 1965], [89, 92], 'jack+jill-tutorial3', verbose=True)"
|
|
98
|
+
"plan = owl.Plan(['Jack', 'Jill'], [1962, 1965], [1, 1], [89, 92], 'jack+jill-tutorial3', verbose=True)"
|
|
99
99
|
]
|
|
100
100
|
},
|
|
101
101
|
{
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
"outputs": [],
|
|
146
146
|
"source": [
|
|
147
147
|
"plan.setPension([0, 10], [65, 65])\n",
|
|
148
|
-
"plan.setSocialSecurity([
|
|
148
|
+
"plan.setSocialSecurity([2333, 2083], [70, 70])"
|
|
149
149
|
]
|
|
150
150
|
},
|
|
151
151
|
{
|
|
@@ -37,6 +37,7 @@ def saveConfig(myplan, file, mylog):
|
|
|
37
37
|
"Status": ["unknown", "single", "married"][myplan.N_i],
|
|
38
38
|
"Names": myplan.inames,
|
|
39
39
|
"Birth year": myplan.yobs.tolist(),
|
|
40
|
+
"Birth month": myplan.mobs.tolist(),
|
|
40
41
|
"Life expectancy": myplan.expectancy.tolist(),
|
|
41
42
|
"Start date": myplan.startDate,
|
|
42
43
|
}
|
|
@@ -55,10 +56,10 @@ def saveConfig(myplan, file, mylog):
|
|
|
55
56
|
|
|
56
57
|
# Fixed Income.
|
|
57
58
|
diconf["Fixed Income"] = {
|
|
58
|
-
"Pension amounts": (myplan.pensionAmounts
|
|
59
|
+
"Pension monthly amounts": (myplan.pensionAmounts).tolist(),
|
|
59
60
|
"Pension ages": myplan.pensionAges.tolist(),
|
|
60
61
|
"Pension indexed": myplan.pensionIsIndexed,
|
|
61
|
-
"Social security amounts": (myplan.ssecAmounts
|
|
62
|
+
"Social security PIA amounts": (myplan.ssecAmounts).tolist(),
|
|
62
63
|
"Social security ages": myplan.ssecAges.tolist(),
|
|
63
64
|
}
|
|
64
65
|
|
|
@@ -181,11 +182,13 @@ def readConfig(file, *, verbose=True, logstreams=None, readContributions=True):
|
|
|
181
182
|
inames = diconf["Basic Info"]["Names"]
|
|
182
183
|
# status = diconf['Basic Info']['Status']
|
|
183
184
|
yobs = diconf["Basic Info"]["Birth year"]
|
|
184
|
-
expectancy = diconf["Basic Info"]["Life expectancy"]
|
|
185
185
|
icount = len(yobs)
|
|
186
|
+
# Default to January if no month entry found.
|
|
187
|
+
mobs = diconf["Basic Info"].get("Birth month", [1]*icount)
|
|
188
|
+
expectancy = diconf["Basic Info"]["Life expectancy"]
|
|
186
189
|
s = ["", "s"][icount - 1]
|
|
187
190
|
mylog.vprint(f"Plan for {icount} individual{s}: {inames}.")
|
|
188
|
-
p = plan.Plan(inames, yobs, expectancy, name, verbose=True, logstreams=logstreams)
|
|
191
|
+
p = plan.Plan(inames, yobs, mobs, expectancy, name, verbose=True, logstreams=logstreams)
|
|
189
192
|
p._description = diconf.get("Description", "")
|
|
190
193
|
|
|
191
194
|
# Assets.
|
|
@@ -217,11 +220,11 @@ def readConfig(file, *, verbose=True, logstreams=None, readContributions=True):
|
|
|
217
220
|
mylog.vprint(f"Ignoring to read contributions file {timeListsFileName}.")
|
|
218
221
|
|
|
219
222
|
# Fixed Income.
|
|
220
|
-
ssecAmounts = np.array(diconf["Fixed Income"]
|
|
221
|
-
ssecAges = np.array(diconf["Fixed Income"]["Social security ages"]
|
|
223
|
+
ssecAmounts = np.array(diconf["Fixed Income"].get("Social security PIA amounts", [0]*icount), dtype=np.int32)
|
|
224
|
+
ssecAges = np.array(diconf["Fixed Income"]["Social security ages"])
|
|
222
225
|
p.setSocialSecurity(ssecAmounts, ssecAges)
|
|
223
|
-
pensionAmounts = np.array(diconf["Fixed Income"]
|
|
224
|
-
pensionAges = np.array(diconf["Fixed Income"]["Pension ages"]
|
|
226
|
+
pensionAmounts = np.array(diconf["Fixed Income"].get("Pension monthly amounts", [0]*icount), dtype=np.float32)
|
|
227
|
+
pensionAges = np.array(diconf["Fixed Income"]["Pension ages"])
|
|
225
228
|
pensionIsIndexed = diconf["Fixed Income"]["Pension indexed"]
|
|
226
229
|
p.setPension(pensionAmounts, pensionAges, pensionIsIndexed)
|
|
227
230
|
|