owlplanner 2025.3.16__py3-none-any.whl → 2025.3.30__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/plan.py +24 -4
- owlplanner/tax2025.py +1 -1
- owlplanner/version.py +1 -1
- {owlplanner-2025.3.16.dist-info → owlplanner-2025.3.30.dist-info}/METADATA +1 -1
- {owlplanner-2025.3.16.dist-info → owlplanner-2025.3.30.dist-info}/RECORD +7 -7
- {owlplanner-2025.3.16.dist-info → owlplanner-2025.3.30.dist-info}/WHEEL +0 -0
- {owlplanner-2025.3.16.dist-info → owlplanner-2025.3.30.dist-info}/licenses/LICENSE +0 -0
owlplanner/plan.py
CHANGED
|
@@ -307,6 +307,9 @@ class Plan(object):
|
|
|
307
307
|
# Previous 2 years for Medicare.
|
|
308
308
|
self.prevMAGI = np.zeros((2))
|
|
309
309
|
|
|
310
|
+
# Default slack on profile.
|
|
311
|
+
self.lambdha = 0
|
|
312
|
+
|
|
310
313
|
# Scenario starts at the beginning of this year and ends at the end of the last year.
|
|
311
314
|
s = ["", "s"][self.N_i - 1]
|
|
312
315
|
self.mylog.vprint(f"Preparing scenario of {self.N_n} years for {self.N_i} individual{s}.")
|
|
@@ -1071,6 +1074,9 @@ class Plan(object):
|
|
|
1071
1074
|
Cx = self.C["x"]
|
|
1072
1075
|
Cz = self.C["z"]
|
|
1073
1076
|
|
|
1077
|
+
spLo = 1 - self.lambdha
|
|
1078
|
+
spHi = 1 + self.lambdha
|
|
1079
|
+
|
|
1074
1080
|
tau_ijn = np.zeros((Ni, Nj, Nn))
|
|
1075
1081
|
for i in range(Ni):
|
|
1076
1082
|
for j in range(Nj):
|
|
@@ -1191,7 +1197,8 @@ class Plan(object):
|
|
|
1191
1197
|
# Account for time elapsed in the current year.
|
|
1192
1198
|
spending *= units * self.yearFracLeft
|
|
1193
1199
|
# self.mylog.vprint('Maximizing bequest with desired net spending of:', u.d(spending))
|
|
1194
|
-
|
|
1200
|
+
# To allow slack in first year, Cg can be made Nn+1 and store basis in g[Nn].
|
|
1201
|
+
A.addNewRow({_q1(Cg, 0, Nn): 1}, spending, spending)
|
|
1195
1202
|
|
|
1196
1203
|
# Set initial balances through constraints.
|
|
1197
1204
|
for i in range(Ni):
|
|
@@ -1297,8 +1304,10 @@ class Plan(object):
|
|
|
1297
1304
|
|
|
1298
1305
|
# Impose income profile.
|
|
1299
1306
|
for n in range(1, Nn):
|
|
1300
|
-
rowDic = {_q1(Cg, 0, Nn): -self.xiBar_n[n], _q1(Cg, n, Nn): self.xiBar_n[0]}
|
|
1301
|
-
A.addNewRow(rowDic, zero,
|
|
1307
|
+
rowDic = {_q1(Cg, 0, Nn): -spLo * self.xiBar_n[n], _q1(Cg, n, Nn): self.xiBar_n[0]}
|
|
1308
|
+
A.addNewRow(rowDic, zero, inf)
|
|
1309
|
+
rowDic = {_q1(Cg, 0, Nn): spHi * self.xiBar_n[n], _q1(Cg, n, Nn): -self.xiBar_n[0]}
|
|
1310
|
+
A.addNewRow(rowDic, zero, inf)
|
|
1302
1311
|
|
|
1303
1312
|
# Taxable ordinary income.
|
|
1304
1313
|
for n in range(Nn):
|
|
@@ -1362,7 +1371,9 @@ class Plan(object):
|
|
|
1362
1371
|
# Now build a solver-neutral objective vector.
|
|
1363
1372
|
c = abc.Objective(self.nvars)
|
|
1364
1373
|
if objective == "maxSpending":
|
|
1365
|
-
c.setElem(_q1(Cg, 0, Nn), -1)
|
|
1374
|
+
# c.setElem(_q1(Cg, 0, Nn), -1) # Only OK in implemention without slack.
|
|
1375
|
+
for n in range(Nn):
|
|
1376
|
+
c.setElem(_q1(Cg, n, Nn), -1/self.gamma_n[n])
|
|
1366
1377
|
elif objective == "maxBequest":
|
|
1367
1378
|
for i in range(Ni):
|
|
1368
1379
|
c.setElem(_q3(Cb, i, 0, Nn, Ni, Nj, Nn + 1), -1)
|
|
@@ -1608,6 +1619,7 @@ class Plan(object):
|
|
|
1608
1619
|
"units",
|
|
1609
1620
|
"maxRothConversion",
|
|
1610
1621
|
"netSpending",
|
|
1622
|
+
"spendingSlack",
|
|
1611
1623
|
"bequest",
|
|
1612
1624
|
"bigM",
|
|
1613
1625
|
"noRothConversions",
|
|
@@ -1642,6 +1654,7 @@ class Plan(object):
|
|
|
1642
1654
|
if objective == "maxSpending" and "bequest" not in myoptions:
|
|
1643
1655
|
self.mylog.vprint("Using bequest of $1.")
|
|
1644
1656
|
|
|
1657
|
+
self.prevMAGI = np.zeros(2)
|
|
1645
1658
|
if "previousMAGIs" in myoptions:
|
|
1646
1659
|
magi = myoptions["previousMAGIs"]
|
|
1647
1660
|
if len(magi) != 2:
|
|
@@ -1653,6 +1666,13 @@ class Plan(object):
|
|
|
1653
1666
|
units = 1000
|
|
1654
1667
|
self.prevMAGI = units * np.array(magi)
|
|
1655
1668
|
|
|
1669
|
+
self.lambdha = 0
|
|
1670
|
+
if "spendingSlack" in myoptions:
|
|
1671
|
+
lambdha = myoptions["spendingSlack"]
|
|
1672
|
+
if lambdha < 0 or lambdha > 50:
|
|
1673
|
+
raise ValueError(f"Slack value out of range {lambdha}.")
|
|
1674
|
+
self.lambdha = lambdha / 100
|
|
1675
|
+
|
|
1656
1676
|
self._adjustParameters()
|
|
1657
1677
|
|
|
1658
1678
|
if "solver" in options:
|
owlplanner/tax2025.py
CHANGED
|
@@ -36,7 +36,7 @@ rates_nonTCJA = np.array([0.10, 0.15, 0.25, 0.28, 0.33, 0.35, 0.396])
|
|
|
36
36
|
taxBrackets_TCJA = np.array(
|
|
37
37
|
[
|
|
38
38
|
[11925, 48475, 103350, 197300, 250525, 626350, 9999999],
|
|
39
|
-
[23850, 96950, 206700, 394600, 501050,
|
|
39
|
+
[23850, 96950, 206700, 394600, 501050, 751600, 9999999],
|
|
40
40
|
]
|
|
41
41
|
)
|
|
42
42
|
|
owlplanner/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "2025.03.
|
|
1
|
+
__version__ = "2025.03.30"
|
|
@@ -2,16 +2,16 @@ owlplanner/__init__.py,sha256=QqrdT0Qks20osBTg7h0vJHAxpP9lL7DA99xb0nYbtw4,254
|
|
|
2
2
|
owlplanner/abcapi.py,sha256=LbzW_KcNy0IeHp42MUHwGu_H67B2h_e1_vu-c2ACTkQ,6646
|
|
3
3
|
owlplanner/config.py,sha256=uJ6jZ9Rx2CB2P5cFRscsUCXOW6uml7I4pta2ozjW0uo,12263
|
|
4
4
|
owlplanner/logging.py,sha256=tYMw04O-XYSzjTj36fmKJGLcE1VkK6k6oJNeqtKXzuc,2530
|
|
5
|
-
owlplanner/plan.py,sha256=
|
|
5
|
+
owlplanner/plan.py,sha256=Y3CDTI4T9hXJ3Epn64eox3n__yY5QdB6uk3lkj5oAsk,116953
|
|
6
6
|
owlplanner/progress.py,sha256=8jlCvvtgDI89zXVNMBg1-lnEyhpPvKQS2X5oAIpoOVQ,384
|
|
7
7
|
owlplanner/rates.py,sha256=gJaoe-gJqWCQV5qVLlHp-Yn9TSJs-PJzeTbOwMCbqWs,15682
|
|
8
|
-
owlplanner/tax2025.py,sha256=
|
|
8
|
+
owlplanner/tax2025.py,sha256=HEXfL0HfwUvZOQRjivXO2jFeoVZ5m_yk_hoMiVi-hR0,7745
|
|
9
9
|
owlplanner/timelists.py,sha256=tYieZU67FT6TCcQQis36JaXGI7dT6NqD7RvdEjgJL4M,4026
|
|
10
10
|
owlplanner/utils.py,sha256=WpJgn79YZfH8UCkcmhd-AZlxlGuz1i1-UDBRXImsY6I,2485
|
|
11
|
-
owlplanner/version.py,sha256=
|
|
11
|
+
owlplanner/version.py,sha256=fEQSK7uDPSbqsQ3DPZ39_7pwhTGTqWEEoeAsff3bjKU,28
|
|
12
12
|
owlplanner/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
owlplanner/data/rates.csv,sha256=6fxg56BVVORrj9wJlUGFdGXKvOX5r7CSca8uhUbbuIU,3734
|
|
14
|
-
owlplanner-2025.3.
|
|
15
|
-
owlplanner-2025.3.
|
|
16
|
-
owlplanner-2025.3.
|
|
17
|
-
owlplanner-2025.3.
|
|
14
|
+
owlplanner-2025.3.30.dist-info/METADATA,sha256=_8LSN7_z0_80_0IL37XAcDRRDKCm42qtcJtaQ3J9qK4,53801
|
|
15
|
+
owlplanner-2025.3.30.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
16
|
+
owlplanner-2025.3.30.dist-info/licenses/LICENSE,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
|
|
17
|
+
owlplanner-2025.3.30.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|