owlplanner 2025.1.28__py3-none-any.whl → 2025.2__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 +16 -31
- owlplanner/tax2025.py +5 -5
- owlplanner/version.py +1 -1
- {owlplanner-2025.1.28.dist-info → owlplanner-2025.2.dist-info}/METADATA +1 -1
- {owlplanner-2025.1.28.dist-info → owlplanner-2025.2.dist-info}/RECORD +7 -7
- {owlplanner-2025.1.28.dist-info → owlplanner-2025.2.dist-info}/WHEEL +0 -0
- {owlplanner-2025.1.28.dist-info → owlplanner-2025.2.dist-info}/licenses/LICENSE +0 -0
owlplanner/plan.py
CHANGED
|
@@ -295,6 +295,9 @@ class Plan(object):
|
|
|
295
295
|
self.myRothX_in = np.zeros((self.N_i, self.N_n))
|
|
296
296
|
self.kappa_ijn = np.zeros((self.N_i, self.N_j, self.N_n))
|
|
297
297
|
|
|
298
|
+
# Previous 2 years for Medicare.
|
|
299
|
+
self.prevMAGI = np.zeros((2))
|
|
300
|
+
|
|
298
301
|
# Scenario starts at the beginning of this year and ends at the end of the last year.
|
|
299
302
|
self.mylog.vprint('Preparing scenario of %d years for %d individual%s.'
|
|
300
303
|
% (self.N_n, self.N_i, ['', 's'][self.N_i - 1]))
|
|
@@ -403,8 +406,6 @@ class Plan(object):
|
|
|
403
406
|
self.mylog.vprint('Renaming plan %s -> %s.' % (self._name, newname))
|
|
404
407
|
self._name = newname
|
|
405
408
|
|
|
406
|
-
return None
|
|
407
|
-
|
|
408
409
|
def setSpousalDepositFraction(self, eta):
|
|
409
410
|
"""
|
|
410
411
|
Set spousal deposit and withdrawal fraction. Default 0.5.
|
|
@@ -424,8 +425,6 @@ class Plan(object):
|
|
|
424
425
|
self.mylog.vprint('\t%s: %.1f, %s: %.1f' % (self.inames[0], (1 - eta), self.inames[1], eta))
|
|
425
426
|
self.eta = eta
|
|
426
427
|
|
|
427
|
-
return None
|
|
428
|
-
|
|
429
428
|
def setDefaultPlots(self, value):
|
|
430
429
|
"""
|
|
431
430
|
Set plots between nominal values or today's $.
|
|
@@ -434,8 +433,6 @@ class Plan(object):
|
|
|
434
433
|
self.defaultPlots = self._checkValue(value)
|
|
435
434
|
self.mylog.vprint('Setting plots default value to %s.' % value)
|
|
436
435
|
|
|
437
|
-
return None
|
|
438
|
-
|
|
439
436
|
def setDividendRate(self, mu):
|
|
440
437
|
"""
|
|
441
438
|
Set dividend rate on equities. Rate is in percent. Default 2%.
|
|
@@ -446,8 +443,6 @@ class Plan(object):
|
|
|
446
443
|
self.mu = mu
|
|
447
444
|
self.caseStatus = 'modified'
|
|
448
445
|
|
|
449
|
-
return None
|
|
450
|
-
|
|
451
446
|
def setLongTermCapitalTaxRate(self, psi):
|
|
452
447
|
"""
|
|
453
448
|
Set long-term income tax rate. Rate is in percent. Default 15%.
|
|
@@ -458,8 +453,6 @@ class Plan(object):
|
|
|
458
453
|
self.psi = psi
|
|
459
454
|
self.caseStatus = 'modified'
|
|
460
455
|
|
|
461
|
-
return None
|
|
462
|
-
|
|
463
456
|
def setBeneficiaryFractions(self, phi):
|
|
464
457
|
"""
|
|
465
458
|
Set fractions of savings accounts that is left to surviving spouse.
|
|
@@ -477,8 +470,6 @@ class Plan(object):
|
|
|
477
470
|
self.mylog.vprint('Consider changing spousal deposit fraction for better convergence.')
|
|
478
471
|
self.mylog.vprint('\tRecommended: setSpousalDepositFraction(%d)' % self.i_d)
|
|
479
472
|
|
|
480
|
-
return None
|
|
481
|
-
|
|
482
473
|
def setHeirsTaxRate(self, nu):
|
|
483
474
|
"""
|
|
484
475
|
Set the heirs tax rate on the tax-deferred portion of the estate.
|
|
@@ -490,8 +481,6 @@ class Plan(object):
|
|
|
490
481
|
self.nu = nu
|
|
491
482
|
self.caseStatus = 'modified'
|
|
492
483
|
|
|
493
|
-
return None
|
|
494
|
-
|
|
495
484
|
def setPension(self, amounts, ages, units='k'):
|
|
496
485
|
"""
|
|
497
486
|
Set value of pension for each individual and commencement age.
|
|
@@ -521,8 +510,6 @@ class Plan(object):
|
|
|
521
510
|
self.pensionAges = np.array(ages, dtype=np.int32)
|
|
522
511
|
self.caseStatus = 'modified'
|
|
523
512
|
|
|
524
|
-
return None
|
|
525
|
-
|
|
526
513
|
def setSocialSecurity(self, amounts, ages, units='k'):
|
|
527
514
|
"""
|
|
528
515
|
Set value of social security for each individual and commencement age.
|
|
@@ -560,8 +547,6 @@ class Plan(object):
|
|
|
560
547
|
self.caseStatus = 'modified'
|
|
561
548
|
self._adjustedParameters = False
|
|
562
549
|
|
|
563
|
-
return None
|
|
564
|
-
|
|
565
550
|
def setSpendingProfile(self, profile, percent=60, dip=15, increase=12, delay=0):
|
|
566
551
|
"""
|
|
567
552
|
Generate time series for spending profile. Surviving spouse fraction can be specified
|
|
@@ -589,8 +574,6 @@ class Plan(object):
|
|
|
589
574
|
self.smileDelay = delay
|
|
590
575
|
self.caseStatus = 'modified'
|
|
591
576
|
|
|
592
|
-
return None
|
|
593
|
-
|
|
594
577
|
def setRates(self, method, frm=None, to=None, values=None, stdev=None, corr=None):
|
|
595
578
|
"""
|
|
596
579
|
Generate rates for return and inflation based on the method and
|
|
@@ -632,8 +615,6 @@ class Plan(object):
|
|
|
632
615
|
self._adjustedParameters = False
|
|
633
616
|
self.caseStatus = 'modified'
|
|
634
617
|
|
|
635
|
-
return None
|
|
636
|
-
|
|
637
618
|
def regenRates(self):
|
|
638
619
|
"""
|
|
639
620
|
Regenerate the rates using the arguments specified during last setRates() call.
|
|
@@ -648,8 +629,6 @@ class Plan(object):
|
|
|
648
629
|
corr=self.rateCorr,
|
|
649
630
|
)
|
|
650
631
|
|
|
651
|
-
return None
|
|
652
|
-
|
|
653
632
|
def value(self, amount, year):
|
|
654
633
|
"""
|
|
655
634
|
Return value of amount deflated or inflated at the beginning
|
|
@@ -711,8 +690,6 @@ class Plan(object):
|
|
|
711
690
|
u.d(np.sum(taxable) + 0.7 * np.sum(taxDeferred) + np.sum(taxFree)),
|
|
712
691
|
)
|
|
713
692
|
|
|
714
|
-
return None
|
|
715
|
-
|
|
716
693
|
def setInterpolationMethod(self, method, center=15, width=5):
|
|
717
694
|
"""
|
|
718
695
|
Interpolate assets allocation ratios from initial value (today) to
|
|
@@ -739,8 +716,6 @@ class Plan(object):
|
|
|
739
716
|
|
|
740
717
|
self.mylog.vprint('Asset allocation interpolation method set to %s.' % method)
|
|
741
718
|
|
|
742
|
-
return None
|
|
743
|
-
|
|
744
719
|
def setAllocationRatios(self, allocType, taxable=None, taxDeferred=None, taxFree=None, generic=None):
|
|
745
720
|
"""
|
|
746
721
|
Single function for setting all types of asset allocations.
|
|
@@ -874,8 +849,6 @@ class Plan(object):
|
|
|
874
849
|
|
|
875
850
|
self.mylog.vprint('Interpolating assets allocation ratios using', self.interpMethod, 'method.')
|
|
876
851
|
|
|
877
|
-
return None
|
|
878
|
-
|
|
879
852
|
def readContributions(self, filename):
|
|
880
853
|
"""
|
|
881
854
|
Provide the name of the file containing the financial events
|
|
@@ -1636,6 +1609,7 @@ class Plan(object):
|
|
|
1636
1609
|
'noRothConversions',
|
|
1637
1610
|
'withMedicare',
|
|
1638
1611
|
'solver',
|
|
1612
|
+
'previousMAGIs',
|
|
1639
1613
|
]
|
|
1640
1614
|
# We will modify options if required.
|
|
1641
1615
|
if options is None:
|
|
@@ -1664,6 +1638,17 @@ class Plan(object):
|
|
|
1664
1638
|
if objective == 'maxSpending' and 'bequest' not in myoptions:
|
|
1665
1639
|
self.mylog.vprint('Using bequest of $1.')
|
|
1666
1640
|
|
|
1641
|
+
if 'previousMAGIs' in myoptions:
|
|
1642
|
+
magi = myoptions['previousMAGIs']
|
|
1643
|
+
if len(magi) != 2:
|
|
1644
|
+
raise ValueError("previousMAGIs must have two values.")
|
|
1645
|
+
|
|
1646
|
+
if 'units' in options:
|
|
1647
|
+
units = u.getUnits(options['units'])
|
|
1648
|
+
else:
|
|
1649
|
+
units = 1000
|
|
1650
|
+
self.prevMAGI = units * np.array(magi)
|
|
1651
|
+
|
|
1667
1652
|
self._adjustParameters()
|
|
1668
1653
|
|
|
1669
1654
|
if 'solver' in options:
|
|
@@ -1897,7 +1882,7 @@ class Plan(object):
|
|
|
1897
1882
|
self.F_tn = self.F_tn.reshape((self.N_t, self.N_n))
|
|
1898
1883
|
MAGI_n = np.sum(self.F_tn, axis=0) + np.array(x[self.C['e']:self.C['F']])
|
|
1899
1884
|
|
|
1900
|
-
self.M_n = tx.mediCosts(self.yobs, self.horizons, MAGI_n, self.gamma_n[:-1], self.N_n)
|
|
1885
|
+
self.M_n = tx.mediCosts(self.yobs, self.horizons, MAGI_n, self.prevMAGI, self.gamma_n[:-1], self.N_n)
|
|
1901
1886
|
|
|
1902
1887
|
return None
|
|
1903
1888
|
|
owlplanner/tax2025.py
CHANGED
|
@@ -69,7 +69,7 @@ extra65Deduction_2025 = np.array([2000, 1600])
|
|
|
69
69
|
##############################################################################
|
|
70
70
|
|
|
71
71
|
|
|
72
|
-
def mediCosts(yobs, horizons, magi, gamma_n, Nn):
|
|
72
|
+
def mediCosts(yobs, horizons, magi, prevmagi, gamma_n, Nn):
|
|
73
73
|
"""
|
|
74
74
|
Compute Medicare costs directly.
|
|
75
75
|
"""
|
|
@@ -79,14 +79,14 @@ def mediCosts(yobs, horizons, magi, gamma_n, Nn):
|
|
|
79
79
|
for n in range(Nn):
|
|
80
80
|
for i in range(Ni):
|
|
81
81
|
if thisyear + n - yobs[i] >= 65 and n < horizons[i]:
|
|
82
|
-
#
|
|
82
|
+
# Start with the (indexed) basic Medicare part B premium.
|
|
83
83
|
costs[n] += gamma_n[n] * irmaaFees_2025[0]
|
|
84
84
|
if n < 2:
|
|
85
|
-
|
|
85
|
+
mymagi = prevmagi[n]
|
|
86
86
|
else:
|
|
87
|
-
|
|
87
|
+
mymagi = magi[n - 2]
|
|
88
88
|
for q in range(1, 6):
|
|
89
|
-
if
|
|
89
|
+
if mymagi > gamma_n[n] * irmaaBrackets_2025[Ni - 1][q]:
|
|
90
90
|
costs[n] += gamma_n[n] * irmaaFees_2025[q]
|
|
91
91
|
|
|
92
92
|
return costs
|
owlplanner/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "2025.
|
|
1
|
+
__version__ = "2025.02"
|
|
@@ -2,16 +2,16 @@ owlplanner/__init__.py,sha256=QqrdT0Qks20osBTg7h0vJHAxpP9lL7DA99xb0nYbtw4,254
|
|
|
2
2
|
owlplanner/abcapi.py,sha256=eemIsdbtzdWCIj5VuuswgphxXMcxJ_GZfUlDi6lttFM,6658
|
|
3
3
|
owlplanner/config.py,sha256=ouADb6YES5Zgv0UwnEK9Axwvs8drp-ahboQjI4WTrr0,12069
|
|
4
4
|
owlplanner/logging.py,sha256=pXg_mMgBll-kklqaDRLDNVUFo-5DAa-yqTKtiVrhNWw,2530
|
|
5
|
-
owlplanner/plan.py,sha256=
|
|
5
|
+
owlplanner/plan.py,sha256=hZhx-Dp_t1Lli2q2VdtXkM03qsdPdM7KcDu4wgAxDIE,115577
|
|
6
6
|
owlplanner/progress.py,sha256=YZjL5_m4MMgKPlWlhhKacPLt54tVhVGF1eXxxZapMYs,386
|
|
7
7
|
owlplanner/rates.py,sha256=aKOmau8i3uqxZGi7HQJpzooT3X-yAZhga5MZJ56pBzk,15627
|
|
8
|
-
owlplanner/tax2025.py,sha256=
|
|
8
|
+
owlplanner/tax2025.py,sha256=b2RgM6TBQa8ggo6ODyh0p_J7j79UUm8z5NiENqa1l_k,7016
|
|
9
9
|
owlplanner/timelists.py,sha256=ifxbyMlRW3IMwsiu8zsoodA1CKJQthgk3iPq50vQIds,4104
|
|
10
10
|
owlplanner/utils.py,sha256=adIwqGVQFfvekke0JCxYJD3PKHbptVCj3NrQT2TQIB4,2351
|
|
11
|
-
owlplanner/version.py,sha256=
|
|
11
|
+
owlplanner/version.py,sha256=1_pf7w0m_4k4eWcDSLOiWoM_lv54EH6pA9nuPETGRtk,25
|
|
12
12
|
owlplanner/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
owlplanner/data/rates.csv,sha256=6fxg56BVVORrj9wJlUGFdGXKvOX5r7CSca8uhUbbuIU,3734
|
|
14
|
-
owlplanner-2025.
|
|
15
|
-
owlplanner-2025.
|
|
16
|
-
owlplanner-2025.
|
|
17
|
-
owlplanner-2025.
|
|
14
|
+
owlplanner-2025.2.dist-info/METADATA,sha256=xII-8KNAoNNr_19KWjuS-9seZBzoBK4P9hEKLfcprto,64512
|
|
15
|
+
owlplanner-2025.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
16
|
+
owlplanner-2025.2.dist-info/licenses/LICENSE,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
|
|
17
|
+
owlplanner-2025.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|