diff --git a/codecov.yml b/codecov.yml index 70cbddd52..481a8d37d 100644 --- a/codecov.yml +++ b/codecov.yml @@ -21,5 +21,6 @@ comment: ignore: - "setup.py" + - "update_pcl.py" - "ppp.py" - "extend_tcja.py" diff --git a/taxcalc/policy.py b/taxcalc/policy.py index c0aefa806..2b78a72ab 100644 --- a/taxcalc/policy.py +++ b/taxcalc/policy.py @@ -37,7 +37,7 @@ class instance: Policy DEFAULTS_FILE_NAME = 'policy_current_law.json' DEFAULTS_FILE_PATH = os.path.abspath(os.path.dirname(__file__)) JSON_START_YEAR = 2013 # remains the same unless earlier data added - LAST_KNOWN_YEAR = 2022 # last year for which indexed param vals are known + LAST_KNOWN_YEAR = 2023 # last year for which indexed param vals are known # should increase LAST_KNOWN_YEAR by one every calendar year LAST_BUDGET_YEAR = 2034 # last extrapolation year # should increase LAST_BUDGET_YEAR by one every calendar year diff --git a/taxcalc/policy_current_law.json b/taxcalc/policy_current_law.json index 2cc95f940..3be92b776 100644 --- a/taxcalc/policy_current_law.json +++ b/taxcalc/policy_current_law.json @@ -218,6 +218,10 @@ { "year": 2022, "value": 147000.0 + }, + { + "year": 2023, + "value": 160200.0 } ], "validators": { @@ -1149,6 +1153,10 @@ { "year": 2022, "value": 0.0 + }, + { + "year": 2023, + "value": 0.0 } ], "validators": { @@ -1211,6 +1219,10 @@ { "year": 2022, "value": 0.0 + }, + { + "year": 2023, + "value": 0.0 } ], "validators": { @@ -1531,6 +1543,31 @@ "MARS": "widow", "value": 540000.0 }, + { + "year": 2023, + "MARS": "single", + "value": 289000.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 578000.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 289000.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 289000.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 578000.0 + }, { "year": 2026, "MARS": "single", @@ -1618,6 +1655,10 @@ "year": 2022, "value": 0.0 }, + { + "year": 2023, + "value": 0.0 + }, { "year": 2026, "value": 5300.0 @@ -1894,6 +1935,31 @@ "MARS": "widow", "value": 9e+99 }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, { "year": 2026, "MARS": "single", @@ -2243,6 +2309,31 @@ "MARS": "widow", "value": 25900.0 }, + { + "year": 2023, + "MARS": "single", + "value": 13850.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 27700.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 13850.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 20800.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 27700.0 + }, { "year": 2026, "MARS": "single", @@ -2329,6 +2420,10 @@ { "year": 2022, "value": 1150.0 + }, + { + "year": 2023, + "value": 1250.0 } ], "validators": { @@ -2601,6 +2696,31 @@ "year": 2022, "MARS": "widow", "value": 1750.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 1800.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 1500.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 1500.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 1800.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 1800.0 } ], "validators": { @@ -3032,6 +3152,31 @@ "year": 2022, "MARS": "widow", "value": 0.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 0.0 } ], "validators": { @@ -3304,6 +3449,31 @@ "year": 2022, "MARS": "widow", "value": 0.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 0.0 } ], "validators": { @@ -3602,6 +3772,31 @@ "year": 2022, "MARS": "widow", "value": 0.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 0.0 } ], "validators": { @@ -3874,6 +4069,31 @@ "year": 2022, "MARS": "widow", "value": 0.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 0.0 } ], "validators": { @@ -4713,6 +4933,31 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -5037,26 +5282,51 @@ "year": 2022, "MARS": "widow", "value": 9e+99 - } - ], - "validators": { - "range": { - "min": 0, - "max": 9e+99 - } - }, - "compatible_data": { - "puf": true, - "cps": true - } - }, - "ID_RealEstate_hc": { - "title": "State, local, and foreign real estate taxes deduction haircut.", - "description": "This decimal fraction reduces real estate taxes paid eligible to deduct in itemized deduction.", - "notes": "", - "section_1": "Itemized Deductions", - "section_2": "State, Local, And Foreign Real Estate Taxes", - "indexable": false, + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + } + ], + "validators": { + "range": { + "min": 0, + "max": 9e+99 + } + }, + "compatible_data": { + "puf": true, + "cps": true + } + }, + "ID_RealEstate_hc": { + "title": "State, local, and foreign real estate taxes deduction haircut.", + "description": "This decimal fraction reduces real estate taxes paid eligible to deduct in itemized deduction.", + "notes": "", + "section_1": "Itemized Deductions", + "section_2": "State, Local, And Foreign Real Estate Taxes", + "indexable": false, "indexed": false, "type": "float", "value": [ @@ -5361,6 +5631,31 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -5982,6 +6277,31 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -6376,6 +6696,31 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -6775,6 +7120,31 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -7128,6 +7498,31 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -7401,6 +7796,31 @@ "MARS": "widow", "value": 9e+99 }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, { "year": 2026, "MARS": "single", @@ -7869,6 +8289,31 @@ "year": 2022, "MARS": "widow", "value": 0.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 0.0 } ], "validators": { @@ -8281,6 +8726,31 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -8709,6 +9179,31 @@ "year": 2022, "MARS": "widow", "value": 83350.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 44625.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 89250.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 44625.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 59750.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 89250.0 } ], "validators": { @@ -9007,6 +9502,31 @@ "year": 2022, "MARS": "widow", "value": 517200.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 492300.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 553850.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 276900.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 523050.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 553850.0 } ], "validators": { @@ -9305,6 +9825,31 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -9629,6 +10174,31 @@ "year": 2022, "MARS": "widow", "value": 83350.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 44625.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 89250.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 44625.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 59750.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 89250.0 } ], "validators": { @@ -9927,6 +10497,31 @@ "year": 2022, "MARS": "widow", "value": 517200.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 492300.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 553850.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 276900.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 523050.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 553850.0 } ], "validators": { @@ -10225,6 +10820,31 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -10339,6 +10959,10 @@ { "year": 2022, "value": 0.0 + }, + { + "year": 2023, + "value": 0.0 } ], "validators": { @@ -10704,6 +11328,31 @@ "MARS": "widow", "value": 20550.0 }, + { + "year": 2023, + "MARS": "single", + "value": 11000.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 22000.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 11000.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 15700.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 22000.0 + }, { "year": 2026, "MARS": "single", @@ -11067,6 +11716,31 @@ "MARS": "widow", "value": 83550.0 }, + { + "year": 2023, + "MARS": "single", + "value": 44725.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 89450.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 44725.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 59850.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 89450.0 + }, { "year": 2026, "MARS": "single", @@ -11428,7 +12102,32 @@ { "year": 2022, "MARS": "widow", - "value": 178150.0 + "value": 178150.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 95375.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 190750.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 95375.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 95350.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 190750.0 }, { "year": 2026, @@ -11793,6 +12492,31 @@ "MARS": "widow", "value": 340100.0 }, + { + "year": 2023, + "MARS": "single", + "value": 182100.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 364200.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 182100.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 182100.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 364200.0 + }, { "year": 2026, "MARS": "single", @@ -12156,6 +12880,31 @@ "MARS": "widow", "value": 431900.0 }, + { + "year": 2023, + "MARS": "single", + "value": 231250.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 462500.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 231250.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 231250.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 462500.0 + }, { "year": 2026, "MARS": "single", @@ -12519,6 +13268,31 @@ "MARS": "widow", "value": 647850.0 }, + { + "year": 2023, + "MARS": "single", + "value": 578125.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 693750.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 578125.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 578100.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 693750.0 + }, { "year": 2026, "MARS": "single", @@ -12882,6 +13656,31 @@ "MARS": "widow", "value": 9e+99 }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, { "year": 2026, "MARS": "single", @@ -13271,6 +14070,31 @@ "MARS": "widow", "value": 20550.0 }, + { + "year": 2023, + "MARS": "single", + "value": 11000.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 22000.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 11000.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 15700.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 22000.0 + }, { "year": 2026, "MARS": "single", @@ -13634,6 +14458,31 @@ "MARS": "widow", "value": 83550.0 }, + { + "year": 2023, + "MARS": "single", + "value": 44725.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 89450.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 44725.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 59850.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 89450.0 + }, { "year": 2026, "MARS": "single", @@ -13997,6 +14846,31 @@ "MARS": "widow", "value": 178150.0 }, + { + "year": 2023, + "MARS": "single", + "value": 95375.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 190750.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 95375.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 95350.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 190750.0 + }, { "year": 2026, "MARS": "single", @@ -14360,6 +15234,31 @@ "MARS": "widow", "value": 340100.0 }, + { + "year": 2023, + "MARS": "single", + "value": 182100.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 364200.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 182100.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 182100.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 364200.0 + }, { "year": 2026, "MARS": "single", @@ -14723,6 +15622,31 @@ "MARS": "widow", "value": 431900.0 }, + { + "year": 2023, + "MARS": "single", + "value": 231250.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 462500.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 231250.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 231250.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 462500.0 + }, { "year": 2026, "MARS": "single", @@ -15086,6 +16010,31 @@ "MARS": "widow", "value": 647850.0 }, + { + "year": 2023, + "MARS": "single", + "value": 578125.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 693750.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 578125.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 578100.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 693750.0 + }, { "year": 2026, "MARS": "single", @@ -15449,6 +16398,31 @@ "MARS": "widow", "value": 9e+99 }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 + }, { "year": 2026, "MARS": "single", @@ -15908,27 +16882,52 @@ { "year": 2022, "MARS": "single", - "value": 170050.0 + "value": 170050.0 + }, + { + "year": 2022, + "MARS": "mjoint", + "value": 340100.0 + }, + { + "year": 2022, + "MARS": "mseparate", + "value": 170050.0 + }, + { + "year": 2022, + "MARS": "headhh", + "value": 170050.0 + }, + { + "year": 2022, + "MARS": "widow", + "value": 340100.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 182100.0 }, { - "year": 2022, + "year": 2023, "MARS": "mjoint", - "value": 340100.0 + "value": 364200.0 }, { - "year": 2022, + "year": 2023, "MARS": "mseparate", - "value": 170050.0 + "value": 182100.0 }, { - "year": 2022, + "year": 2023, "MARS": "headhh", - "value": 170050.0 + "value": 182100.0 }, { - "year": 2022, + "year": 2023, "MARS": "widow", - "value": 340100.0 + "value": 182100.0 }, { "year": 2026, @@ -16686,6 +17685,31 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -17140,6 +18164,31 @@ "MARS": "widow", "value": 118100.0 }, + { + "year": 2023, + "MARS": "single", + "value": 81300.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 126500.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 63250.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 81300.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 126500.0 + }, { "year": 2026, "MARS": "single", @@ -17463,6 +18512,31 @@ "MARS": "widow", "value": 1079800.0 }, + { + "year": 2023, + "MARS": "single", + "value": 578150.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 1156300.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 578150.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 578150.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 1156300.0 + }, { "year": 2026, "MARS": "single", @@ -17549,6 +18623,10 @@ { "year": 2022, "value": 8200.0 + }, + { + "year": 2023, + "value": 8800.0 } ], "validators": { @@ -17663,6 +18741,10 @@ { "year": 2022, "value": 206100.0 + }, + { + "year": 2023, + "value": 220700.0 } ], "validators": { @@ -17752,6 +18834,10 @@ "year": 2022, "value": 776100.0 }, + { + "year": 2023, + "value": 831150.0 + }, { "year": 2026, "value": 326410.0 @@ -18973,6 +20059,26 @@ "year": 2022, "EIC": "3+kids", "value": 6935.0 + }, + { + "year": 2023, + "EIC": "0kids", + "value": 600.0 + }, + { + "year": 2023, + "EIC": "1kid", + "value": 3995.0 + }, + { + "year": 2023, + "EIC": "2kids", + "value": 6604.0 + }, + { + "year": 2023, + "EIC": "3+kids", + "value": 7430.0 } ], "validators": { @@ -19441,6 +20547,26 @@ "year": 2022, "EIC": "3+kids", "value": 20130.0 + }, + { + "year": 2023, + "EIC": "0kids", + "value": 9800.0 + }, + { + "year": 2023, + "EIC": "1kid", + "value": 21560.0 + }, + { + "year": 2023, + "EIC": "2kids", + "value": 21560.0 + }, + { + "year": 2023, + "EIC": "3+kids", + "value": 21560.0 } ], "validators": { @@ -19663,6 +20789,26 @@ "year": 2022, "EIC": "3+kids", "value": 6130.0 + }, + { + "year": 2023, + "EIC": "0kids", + "value": 6570.0 + }, + { + "year": 2023, + "EIC": "1kid", + "value": 6560.0 + }, + { + "year": 2023, + "EIC": "2kids", + "value": 6560.0 + }, + { + "year": 2023, + "EIC": "3+kids", + "value": 6560.0 } ], "validators": { @@ -19797,6 +20943,10 @@ { "year": 2022, "value": 10300.0 + }, + { + "year": 2023, + "value": 11000.0 } ], "validators": { @@ -19941,6 +21091,10 @@ { "year": 2022, "value": 0.0 + }, + { + "year": 2023, + "value": 0.0 } ], "validators": { @@ -20661,6 +21815,31 @@ "year": 2022, "MARS": "widow", "value": 0.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 0.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 0.0 } ], "validators": { @@ -21071,6 +22250,31 @@ "year": 2022, "MARS": "widow", "value": 1000000.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 1000000.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 1000000.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 500000.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 1000000.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 1000000.0 } ], "validators": { @@ -21343,6 +22547,31 @@ "year": 2022, "MARS": "widow", "value": 2000000.0 + }, + { + "year": 2023, + "MARS": "single", + "value": 2000000.0 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 2000000.0 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 1000000.0 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 2000000.0 + }, + { + "year": 2023, + "MARS": "widow", + "value": 2000000.0 } ], "validators": { @@ -21641,6 +22870,31 @@ "year": 2022, "MARS": "widow", "value": 9e+99 + }, + { + "year": 2023, + "MARS": "single", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mjoint", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "mseparate", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "headhh", + "value": 9e+99 + }, + { + "year": 2023, + "MARS": "widow", + "value": 9e+99 } ], "validators": { @@ -21729,6 +22983,10 @@ { "year": 2022, "value": 0.0 + }, + { + "year": 2023, + "value": 0.0 } ], "validators": { @@ -21791,6 +23049,10 @@ { "year": 2022, "value": 0.0 + }, + { + "year": 2023, + "value": 0.0 } ], "validators": { @@ -21853,6 +23115,10 @@ { "year": 2022, "value": 0.0 + }, + { + "year": 2023, + "value": 0.0 } ], "validators": { diff --git a/taxcalc/reforms/rounding.json b/taxcalc/reforms/rounding.json new file mode 100644 index 000000000..db7186ae1 --- /dev/null +++ b/taxcalc/reforms/rounding.json @@ -0,0 +1,253 @@ +// Rounding of parameters to return to currnet law poliy +// This file is intended to update parameter values due to IRS rounding +// rules when moving from a historical baseline to current law policy +// by layering on intervening policy changes, as is done in the +// tests/test_reforms.py::test_round_trip_reforms test +// N.B. Only valid through 2022 - will overwrite changes in policy +// beyond that year (e.g., as in TCJA.json) + + +{ + "II_brk1": { + "2019": [9700, 19400, 9700, 13850, 19400], + "2020": [9875, 19750, 9875, 14100, 19750], + "2021": [9950, 19900, 9950, 14200, 19900], + "2022": [10275, 20550, 10275, 14650, 20550], + "2023": [11000, 22000, 11000, 15700, 22000] + }, + "II_brk2": { + "2019": [39475, 78950, 39475, 52850, 78950], + "2020": [40125, 80250, 40125, 53700, 80250], + "2021": [40525, 81050, 40525, 54200, 81050], + "2022": [41775, 83550, 41775, 55900, 83550], + "2023": [44725, 89450, 44725, 59850, 89450] + }, + "II_brk3": { + "2019": [84200, 168400, 84200, 84200, 168400], + "2020": [85525, 171050, 85525, 85500, 171050], + "2021": [86375, 172750, 86375, 86350, 172750], + "2022": [89075, 178150, 89075, 89050, 178150], + "2023": [95375, 190750, 95375, 95350, 190750] + }, + "II_brk4": { + "2019": [160725, 321450, 160725, 160700, 321450], + "2020": [163300, 326600, 163300, 163300, 326600], + "2021": [164925, 329850, 164925, 164900, 329850], + "2022": [170050, 340100, 170050, 170050, 340100], + "2023": [182100, 364200, 182100, 182100, 364200] + }, + "II_brk5": { + "2019": [204100, 408200, 204100, 204100, 408200], + "2020": [207350, 414700, 207350, 207350, 414700], + "2021": [209425, 418850, 209425, 209400, 418850], + "2022": [215950, 431900, 215950, 215950, 431900], + "2023": [231250, 462500, 231250, 231250, 462500] + }, + "II_brk6": { + "2019": [510300, 612350, 306175, 510300, 612350], + "2020": [518400, 622050, 311025, 518400, 622050], + "2021": [523600, 628300, 314150, 523600, 628300], + "2022": [539900, 647850, 323925, 539900, 647850], + "2023": [578125, 693750, 578125, 578100, 693750] + }, + "PT_brk1": { + "2019": [9700, 19400, 9700, 13850, 19400], + "2020": [9875, 19750, 9875, 14100, 19750], + "2021": [9950, 19900, 9950, 14200, 19900], + "2022": [10275, 20550, 10275, 14650, 20550], + "2023": [11000, 22000, 11000, 15700, 22000] + }, + "PT_brk2": { + "2019": [39475, 78950, 39475, 52850, 78950], + "2020": [40125, 80250, 40125, 53700, 80250], + "2021": [40525, 81050, 40525, 54200, 81050], + "2022": [41775, 83550, 41775, 55900, 83550], + "2023": [44725, 89450, 44725, 59850, 89450] + }, + "PT_brk3": { + "2019": [84200, 168400, 84200, 84200, 168400], + "2020": [85525, 171050, 85525, 85500, 171050], + "2021": [86375, 172750, 86375, 86350, 172750], + "2022": [89075, 178150, 89075, 89050, 178150], + "2023": [95375, 190750, 95375, 95350, 190750] + }, + "PT_brk4": { + "2019": [160725, 321450, 160725, 160700, 321450], + "2020": [163300, 326600, 163300, 163300, 326600], + "2021": [164925, 329850, 164925, 164900, 329850], + "2022": [170050, 340100, 170050, 170050, 340100], + "2023": [182100, 364200, 182100, 182100, 364200] + }, + "PT_brk5": { + "2019": [204100, 408200, 204100, 204100, 408200], + "2020": [207350, 414700, 207350, 207350, 414700], + "2021": [209425, 418850, 209425, 209400, 418850], + "2022": [215950, 431900, 215950, 215950, 431900], + "2023": [231250, 462500, 231250, 231250, 462500] + }, + "PT_brk6": { + "2019": [510300, 612350, 306175, 510300, 612350], + "2020": [518400, 622050, 311025, 518400, 622050], + "2021": [523600, 628300, 314150, 523600, 628300], + "2022": [539900, 647850, 323925, 539900, 647850], + "2023": [578125, 693750, 578125, 578100, 693750] + }, + "PT_qbid_taxinc_thd": { + "2019": [160700, 321400, 160725, 160700, 321400], + "2020": [163300, 326600, 163300, 163300, 326600], + "2021": [164900, 329800, 164900, 164900, 329800], + "2022": [170050, 340100, 170050, 170050, 340100], + "2023": [182100, 364200, 182100, 182100, 182100] + }, + "STD": { + "2019": [12200, 24400, 12200, 18350, 24400], + "2020": [12400, 24800, 12400, 18650, 24800], + "2021": [12550, 25100, 12550, 18800, 25100], + "2022": [12950, 25900, 12950, 19400, 25900], + "2023": [13850, 27700, 13850, 20800, 27700] + }, + "AMT_em": { + "2019": [71700, 111700, 55850, 71700, 111700], + "2020": [72900, 113400, 56700, 72900, 113400], + "2021": [73600, 114600, 57300, 73600, 114600], + "2022": [75900, 118100, 59050, 75900, 118100], + "2023": [81300, 126500, 63250, 81300, 126500] + }, + "AMT_em_ps": { + "2019": [510300, 1020600, 510300, 510300, 1020600], + "2020": [518400, 1036800, 518400, 518400, 1036800], + "2021": [523600, 1047200, 523600, 523600, 1047200], + "2022": [539900, 1079800, 539900, 539900, 1079800], + "2023": [578150, 1156300, 578150, 578150, 1156300] + }, + "AMT_em_pe": { + "2019": 733700, + "2020": 745200, + "2021": 752800, + "2022": 776100, + "2023": 831150 + }, + "ALD_BusinessLosses_c": { + "2019": [255000, 510000, 255000, 255000, 510000], + "2020": [259000, 518000, 259000, 259000, 518000], + "2021": [262000, 524000, 262000, 262000, 524000], + "2022": [270000, 540000, 270000, 270000, 540000], + "2023": [289000, 578000, 289000, 289000, 578000] + }, + "STD_Dep": { + "2019": 1100, + "2020": 1100, + "2021": 1100, + "2022": 1150, + "2023": 1250 + }, + "STD_Aged": { + "2019": [1650, 1300, 1300, 1650, 1300], + "2020": [1650, 1300, 1300, 1650, 1300], + "2021": [1700, 1350, 1350, 1700, 1350], + "2022": [1750, 1400, 1400, 1750, 1750], + "2023": [1800, 1500, 1500, 1800, 1800] + }, + "CG_brk1": { + "2019": [39375, 78750, 39375, 52750, 78750], + "2020": [40000, 80000, 40000, 53600, 80000], + "2021": [40400, 80800, 40400, 54100, 80800], + "2022": [41675, 83350, 41675, 55800, 83350], + "2023": [44625, 89250, 44625, 59750, 89250] + }, + "CG_brk2": { + "2019": [434550, 488850, 244425, 461700, 488850], + "2020": [441450, 496600, 248300, 469050, 496600], + "2021": [445850, 501600, 250800, 473750, 501600], + "2022": [459750, 517200, 258600, 488500, 517200], + "2023": [492300, 553850, 276900, 523050, 553850] + }, + "AMT_CG_brk1": { + "2019": [39375, 78750, 39375, 52750, 78750], + "2020": [40000, 80000, 40000, 53600, 80000], + "2021": [40400, 80800, 40400, 54100, 80800], + "2022": [41675, 83350, 41675, 55800, 83350], + "2023": [44625, 89250, 44625, 59750, 89250] + }, + "AMT_CG_brk2": { + "2019": [434550, 488850, 244425, 461700, 488850], + "2020": [441450, 496600, 248300, 469050, 496600], + "2021": [445850, 501600, 250800, 473750, 501600], + "2022": [459750, 517200, 258600, 488500, 517200], + "2023": [492300, 553850, 276900, 523050, 553850] + }, + "AMT_child_em": { + "2019": 7750, + "2020": 7900, + "2021": 7950, + "2022": 8200, + "2023": 8800 + }, + "AMT_brk1": { + "2019": 194800, + "2020": 197900, + "2021": 199900, + "2022": 206100, + "2023": 220700 + }, + "EITC_c": { + "2019": [529, 3526, 5828, 6557], + "2020": [538, 3584, 5920, 6660], + "2021": [1502, 3618, 5980, 6728], + "2022": [560, 3733, 6164, 6935], + "2023": [600, 3995, 6604, 7430] + }, + "EITC_ps": { + "2019": [8650, 19030, 19030, 19030], + "2020": [8790, 19330, 19330, 19330], + "2021": [11610, 19520, 19520, 19520], + "2022": [9160, 20130, 20130, 20130], + "2023": [9800, 21560, 21560, 21560] + }, + "EITC_ps_MarriedJ": { + "2019": [5800, 5790, 5790, 5790], + "2020": [5890, 5890, 5890, 5890], + "2021": [5940, 5950, 5950, 5950], + "2022": [6130, 6130, 6130, 6130], + "2023": [6570, 6560, 6560, 6560] + }, + "EITC_InvestIncome_c": { + "2019": 3600, + "2020": 3650, + "2021": 10000, + "2022": 10300, + "2023": 11000 + }, + "ETC_pe_Single": { + "2019": 68, + "2020": 69, + "2021": 90, + "2022": 90 + }, + "ETC_pe_Married": { + "2019": 136, + "2020": 138, + "2021": 180, + "2022": 180 + }, + "ACTC_c": { + "2023": 1600, + "2024": 1600, + "2025": 1600, + "2026": 1000 + }, + "FST_AGI_thd_lo": { + "2019": [1000000, 1000000, 500000, 1000000, 1000000], + "2020": [1000000, 1000000, 500000, 1000000, 1000000], + "2021": [1000000, 1000000, 500000, 1000000, 1000000], + "2022": [1000000, 1000000, 500000, 1000000, 1000000], + "2023": [1000000, 1000000, 500000, 1000000, 1000000] + }, + "FST_AGI_thd_hi": { + "2019": [2000000, 2000000, 1000000, 2000000, 2000000], + "2020": [2000000, 2000000, 1000000, 2000000, 2000000], + "2021": [2000000, 2000000, 1000000, 2000000, 2000000], + "2022": [2000000, 2000000, 1000000, 2000000, 2000000], + "2023": [2000000, 2000000, 1000000, 2000000, 2000000] + } +} diff --git a/taxcalc/reforms/rounding2022.out.csv b/taxcalc/reforms/rounding.out.csv similarity index 100% rename from taxcalc/reforms/rounding2022.out.csv rename to taxcalc/reforms/rounding.out.csv diff --git a/taxcalc/reforms/rounding2022.json b/taxcalc/reforms/rounding2022.json deleted file mode 100644 index fb07bc18a..000000000 --- a/taxcalc/reforms/rounding2022.json +++ /dev/null @@ -1,153 +0,0 @@ -// Rounding of parameters to return to currnet law poliy -// This file is intended to update parameter values due to IRS rounding -// rules when moving from a historical baseline to current law policy -// by layering on intervening policy changes, as is done in the -// tests/test_reforms.py::test_round_trip_reforms test -// N.B. Only valid through 2022 - will overwrite changes in policy -// beyond that year (e.g., as in TCJA.json) - - -{ - "II_brk1": {"2019": [9700, 19400, 9700, 13850, 19400], - "2020": [9875, 19750, 9875, 14100, 19750], - "2021": [9950, 19900, 9950, 14200, 19900], - "2022": [10275, 20550, 10275, 14650, 20550]}, - "II_brk2": {"2019": [39475, 78950, 39475, 52850, 78950], - "2020": [40125, 80250, 40125, 53700, 80250], - "2021": [40525, 81050, 40525, 54200, 81050], - "2022": [41775, 83550, 41775, 55900, 83550]}, - "II_brk3": {"2019": [84200, 168400, 84200, 84200, 168400], - "2020": [85525, 171050, 85525, 85500, 171050], - "2021": [86375, 172750, 86375, 86350, 172750], - "2022": [89075, 178150, 89075, 89050, 178150]}, - "II_brk4": {"2019": [160725, 321450, 160725, 160700, 321450], - "2020": [163300, 326600, 163300, 163300, 326600], - "2021": [164925, 329850, 164925, 164900, 329850], - "2022": [170050, 340100, 170050, 170050, 340100]}, - "II_brk5": {"2019": [204100, 408200, 204100, 204100, 408200], - "2020": [207350, 414700, 207350, 207350, 414700], - "2021": [209425, 418850, 209425, 209400, 418850], - "2022": [215950, 431900, 215950, 215950, 431900]}, - "II_brk6": {"2019": [510300, 612350, 306175, 510300, 612350], - "2020": [518400, 622050, 311025, 518400, 622050], - "2021": [523600, 628300, 314150, 523600, 628300], - "2022": [539900, 647850, 323925, 539900, 647850]}, - "PT_brk1": {"2019": [9700, 19400, 9700, 13850, 19400], - "2020": [9875, 19750, 9875, 14100, 19750], - "2021": [9950, 19900, 9950, 14200, 19900], - "2022": [10275, 20550, 10275, 14650, 20550]}, - "PT_brk2": {"2019": [39475, 78950, 39475, 52850, 78950], - "2020": [40125, 80250, 40125, 53700, 80250], - "2021": [40525, 81050, 40525, 54200, 81050], - "2022": [41775, 83550, 41775, 55900, 83550]}, - "PT_brk3": {"2019": [84200, 168400, 84200, 84200, 168400], - "2020": [85525, 171050, 85525, 85500, 171050], - "2021": [86375, 172750, 86375, 86350, 172750], - "2022": [89075, 178150, 89075, 89050, 178150]}, - "PT_brk4": {"2019": [160725, 321450, 160725, 160700, 321450], - "2020": [163300, 326600, 163300, 163300, 326600], - "2021": [164925, 329850, 164925, 164900, 329850], - "2022": [170050, 340100, 170050, 170050, 340100]}, - "PT_brk5": {"2019": [204100, 408200, 204100, 204100, 408200], - "2020": [207350, 414700, 207350, 207350, 414700], - "2021": [209425, 418850, 209425, 209400, 418850], - "2022": [215950, 431900, 215950, 215950, 431900]}, - "PT_brk6": {"2019": [510300, 612350, 306175, 510300, 612350], - "2020": [518400, 622050, 311025, 518400, 622050], - "2021": [523600, 628300, 314150, 523600, 628300], - "2022": [539900, 647850, 323925, 539900, 647850]}, - "PT_qbid_taxinc_thd": {"2019": [160700, 321400, 160725, 160700, 321400], - "2020": [163300, 326600, 163300, 163300, 326600], - "2021": [164900, 329800, 164900, 164900, 329800], - "2022": [170050, 340100, 170050, 170050, 340100]}, - "STD": {"2019": [12200, 24400, 12200, 18350, 24400], - "2020": [12400, 24800, 12400, 18650, 24800], - "2021": [12550, 25100, 12550, 18800, 25100], - "2022": [12950, 25900, 12950, 19400, 25900]}, - "AMT_em": {"2019": [71700, 111700, 55850, 71700, 111700], - "2020": [72900, 113400, 56700, 72900, 113400], - "2021": [73600, 114600, 57300, 73600, 114600], - "2022": [75900, 118100, 59050, 75900, 118100]}, - "AMT_em_ps": {"2019": [510300, 1020600, 510300, 510300, 1020600], - "2020": [518400, 1036800, 518400, 518400, 1036800], - "2021": [523600, 1047200, 523600, 523600, 1047200], - "2022": [539900, 1079800, 539900, 539900, 1079800]}, - "AMT_em_pe": {"2019": 733700, - "2020": 745200, - "2021": 752800, - "2022": 776100}, - "ALD_BusinessLosses_c": { - "2019": [255000, 510000, 255000, 255000, 510000], - "2020": [259000, 518000, 259000, 259000, 518000], - "2021": [262000, 524000, 262000, 262000, 524000], - "2022": [270000, 540000, 270000, 270000, 540000]}, - "STD_Dep": {"2019": 1100, "2020": 1100, "2021": 1100, "2022": 1150}, - "STD_Aged": {"2019": [1650, 1300, 1300, 1650, 1300], - "2020": [1650, 1300, 1300, 1650, 1300], - "2021": [1700, 1350, 1350, 1700, 1350], - "2022": [1750, 1400, 1400, 1750, 1750]}, - "CG_brk1": {"2019": [39375, 78750, 39375, 52750, 78750], - "2020": [40000, 80000, 40000, 53600, 80000], - "2021": [40400, 80800, 40400, 54100, 80800], - "2022": [41675, 83350, 41675, 55800, 83350]}, - "CG_brk2": {"2019": [434550, 488850, 244425, 461700, 488850], - "2020": [441450, 496600, 248300, 469050, 496600], - "2021": [445850, 501600, 250800, 473750, 501600], - "2022": [459750, 517200, 258600, 488500, 517200]}, - "AMT_CG_brk1": {"2019": [39375, 78750, 39375, 52750, 78750], - "2020": [40000, 80000, 40000, 53600, 80000], - "2021": [40400, 80800, 40400, 54100, 80800], - "2022": [41675, 83350, 41675, 55800, 83350]}, - "AMT_CG_brk2": {"2019": [434550, 488850, 244425, 461700, 488850], - "2020": [441450, 496600, 248300, 469050, 496600], - "2021": [445850, 501600, 250800, 473750, 501600], - "2022": [459750, 517200, 258600, 488500, 517200]}, - "AMT_child_em": { "2019": 7750, - "2020": 7900, - "2021": 7950, - "2022": 8200}, - "AMT_brk1": {"2019": 194800, - "2020": 197900, - "2021": 199900, - "2022": 206100}, - "EITC_c": {"2019": [529, 3526, 5828, 6557], - "2020": [538, 3584, 5920, 6660], - "2021": [1502.0, 3618.0, 5980.0, 6728.0], - "2022": [560, 3733, 6164, 6935]}, - "EITC_ps": {"2019": [8650, 19030, 19030, 19030], - "2020": [8790, 19330, 19330, 19330], - "2021": [11610, 19520, 19520, 19520], - "2022": [9160, 20130, 20130, 20130]}, - "EITC_ps_MarriedJ": {"2019": [5800, 5790, 5790, 5790], - "2020": [5890, 5890, 5890, 5890], - "2021": [5940, 5950, 5950, 5950], - "2022": [6130, 6130, 6130, 6130]}, - "EITC_InvestIncome_c": {"2019": 3600, - "2020": 3650, - "2021": 10000, - "2022": 10300}, - "ETC_pe_Single": {"2019": 68, - "2020": 69, - "2021": 90, - "2022": 90}, - "ETC_pe_Married": {"2019": 136, - "2020": 138, - "2021": 180, - "2022": 180}, - "ACTC_c": {"2023": 1600, - "2024": 1600, - "2025": 1600, - "2026": 1000}, - "FST_AGI_thd_lo": { - "2019": [1000000, 1000000, 500000, 1000000, 1000000], - "2020": [1000000, 1000000, 500000, 1000000, 1000000], - "2021": [1000000, 1000000, 500000, 1000000, 1000000], - "2022": [1000000, 1000000, 500000, 1000000, 1000000] - }, - "FST_AGI_thd_hi": { - "2019": [2000000, 2000000, 1000000, 2000000, 2000000], - "2020": [2000000, 2000000, 1000000, 2000000, 2000000], - "2021": [2000000, 2000000, 1000000, 2000000, 2000000], - "2022": [2000000, 2000000, 1000000, 2000000, 2000000] - } -} diff --git a/taxcalc/tests/cpscsv_agg_expect.csv b/taxcalc/tests/cpscsv_agg_expect.csv index 1cb1e1a1d..99699a72a 100644 --- a/taxcalc/tests/cpscsv_agg_expect.csv +++ b/taxcalc/tests/cpscsv_agg_expect.csv @@ -1,26 +1,26 @@ ,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026 Returns (#m),187.1,199.2,201.9,204.5,207.1,209.7,212.3,214.9,217.5,220.1 -AGI ($b),9087.6,10714.8,11167.0,11573.2,13174.9,13543.8,14390.3,15077.5,15785.3,16457.7 -Itemizers (#m),62.8,23.9,25.0,27.5,31.2,31.2,29.8,29.4,30.4,81.1 -Itemized Deduction ($b),1218.6,612.0,655.1,745.4,862.7,881.9,887.6,913.8,963.1,2180.7 -Standard Deduction Filers (#m),124.3,175.3,176.9,176.9,175.8,178.5,182.5,185.5,187.2,139.1 -Standard Deduction ($b),1092.1,2951.3,3026.1,3080.8,3091.9,3231.4,3549.4,3806.5,3937.8,1613.3 +AGI ($b),9087.6,10714.8,11167.0,11573.2,13174.9,13543.8,14390.3,15077.5,15785.3,16457.6 +Itemizers (#m),62.8,23.9,25.0,27.5,31.2,31.2,30.0,29.6,30.6,81.1 +Itemized Deduction ($b),1218.6,612.0,655.1,745.4,862.7,881.9,891.8,918.2,968.4,2181.4 +Standard Deduction Filers (#m),124.3,175.3,176.9,176.9,175.8,178.5,182.3,185.3,186.9,139.0 +Standard Deduction ($b),1092.1,2951.3,3026.1,3080.8,3091.9,3231.4,3534.5,3790.6,3920.5,1609.9 Personal Exemption ($b),1383.6,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2081.6 -Taxable Income ($b),6230.6,7959.2,8322.8,8615.4,10049.9,10332.2,10948.3,11426.3,11990.0,11782.5 -Regular Tax ($b),1108.0,1380.0,1449.0,1497.4,1762.8,1837.4,1937.4,2016.4,2123.2,2339.6 -AMT Income ($b),8319.8,10212.6,10630.3,10965.7,12473.9,12821.8,13658.8,14318.8,14984.7,15074.1 +Taxable Income ($b),6230.6,7959.2,8322.8,8615.4,10049.9,10332.2,10954.0,11432.4,11996.4,11783.1 +Regular Tax ($b),1108.0,1380.0,1449.0,1497.4,1762.8,1837.4,1939.0,2018.1,2125.0,2339.7 +AMT Income ($b),8319.8,10212.6,10630.3,10965.7,12473.9,12821.8,13655.8,14315.6,14980.7,15073.6 AMT Liability ($b),8.1,0.4,0.4,0.5,1.4,0.7,0.7,0.6,0.6,17.2 AMT Filers (#m),2.6,0.1,0.1,0.1,0.2,0.1,0.1,0.1,0.1,4.1 -Tax before Credits ($b),1116.0,1380.4,1449.4,1497.9,1764.3,1838.0,1938.1,2017.0,2123.8,2356.8 -Refundable Credits ($b),70.8,102.5,102.7,655.0,827.1,98.5,106.4,111.6,112.1,97.7 -Nonrefundable Credits ($b),32.7,97.2,99.2,99.2,0.0,107.7,108.3,109.3,111.2,29.9 +Tax before Credits ($b),1116.0,1380.4,1449.4,1497.9,1764.3,1838.0,1939.7,2018.7,2125.6,2356.9 +Refundable Credits ($b),70.8,102.5,102.7,655.0,827.1,98.5,106.2,111.4,111.9,97.5 +Nonrefundable Credits ($b),32.7,97.2,99.2,99.2,0.0,107.7,108.4,109.4,111.3,29.9 Reform Surtaxes ($b),0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 Other Taxes ($b),5.5,10.7,11.3,12.6,13.9,14.4,16.5,17.6,18.8,19.9 -Ind Income Tax ($b),1018.1,1191.4,1258.9,756.3,951.0,1646.2,1740.0,1813.7,1919.2,2249.0 -Payroll Taxes ($b),1040.8,1141.6,1194.9,1217.9,1318.7,1421.6,1506.7,1582.0,1656.7,1730.7 -Combined Liability ($b),2059.0,2333.0,2453.8,1974.2,2269.7,3067.8,3246.6,3395.7,3575.9,3979.7 -With Income Tax <= 0 (#m),88.1,96.2,97.0,135.4,127.8,96.1,97.9,99.2,99.6,97.4 -With Combined Tax <= 0 (#m),62.8,65.4,66.4,98.2,97.7,67.9,69.3,70.5,71.3,70.7 +Ind Income Tax ($b),1018.1,1191.4,1258.9,756.3,951.0,1646.2,1741.7,1815.6,1921.2,2249.4 +Payroll Taxes ($b),1040.8,1141.6,1194.9,1217.9,1318.7,1421.6,1509.2,1584.6,1659.4,1733.6 +Combined Liability ($b),2059.0,2333.0,2453.8,1974.2,2269.7,3067.8,3250.9,3400.2,3580.6,3982.9 +With Income Tax <= 0 (#m),88.1,96.2,97.0,135.4,127.8,96.1,97.8,99.1,99.5,97.4 +With Combined Tax <= 0 (#m),62.8,65.4,66.4,98.2,97.7,67.9,69.3,70.4,71.2,70.7 UBI Benefits ($b),0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "Total Benefits, Consumption Value ($b)",2790.7,3225.5,3429.9,3617.0,3993.0,4069.6,4390.5,4696.3,4983.2,5266.5 Total Benefits Cost ($b),2790.7,3225.5,3429.9,3617.0,3993.0,4069.6,4390.5,4696.3,4983.2,5266.5 diff --git a/taxcalc/tests/puf_var_wght_means_by_year.csv b/taxcalc/tests/puf_var_wght_means_by_year.csv index 034ea783c..7b0ccd2de 100644 --- a/taxcalc/tests/puf_var_wght_means_by_year.csv +++ b/taxcalc/tests/puf_var_wght_means_by_year.csv @@ -1,10 +1,10 @@ ,description,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034 -c00100,Federal AGI, 50840, 54457, 54942, 55071, 58024, 60318, 61591, 63130, 73017, 72224, 75917, 77963, 80251, 82363, 84515, 86850, 89344, 91950, 94677, 98306, 99812, 102616 +c00100,Federal AGI, 50840, 54457, 54942, 55071, 58024, 60318, 61591, 63130, 73017, 72224, 75916, 77963, 80250, 82362, 84514, 86849, 89344, 91950, 94677, 98306, 99812, 102616 c02500,OASDI benefits in AGI, 1295, 1394, 1416, 1479, 1501, 1587, 1690, 1832, 2005, 2129, 2428, 2659, 2844, 3028, 3214, 3413, 3619, 3833, 4055, 4308, 4459, 4698 c04470,Post-phase-out itemized deduction, 5908, 6037, 6150, 6383, 6563, 6803, 7011, 7493, 7881, 8018, 8324, 8672, 8950, 9288, 9614, 9940, 10266, 10611, 10970, 11450, 11641, 12004 c04600,Post-phase-out personal exemption, 7105, 7131, 7163, 7217, 7149, 7247, 7380, 7471, 7481, 7806, 8373, 8834, 9054, 9248, 9434, 9612, 9797, 9988, 10186, 10398, 10579, 10791 -c04800,Federal regular taxable income, 35753, 39297, 39663, 39591, 42568, 44523, 45416, 46476, 55959, 54603, 57322, 58386, 60072, 61575, 63147, 64912, 66832, 68828, 70916, 73686, 74836, 76970 -c05200,Regular tax on taxable income, 7671, 8731, 8725, 8584, 9499, 10001, 10138, 10475, 13361, 12576, 13165, 13230, 13561, 13847, 14165, 14544, 14965, 15398, 15840, 16404, 16817, 17279 +c04800,Federal regular taxable income, 35753, 39297, 39663, 39591, 42568, 44523, 45416, 46476, 55959, 54603, 57321, 58385, 60072, 61575, 63147, 64911, 66831, 68828, 70916, 73686, 74835, 76970 +c05200,Regular tax on taxable income, 7671, 8731, 8725, 8584, 9499, 10001, 10138, 10475, 13361, 12576, 13165, 13230, 13561, 13847, 14165, 14544, 14965, 15398, 15840, 16404, 16816, 17278 c07180,Child care credit, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 16, 16 c07220,Child tax credit (adjusted), 158, 155, 147, 143, 139, 134, 129, 124, 359, 116, 107, 101, 97, 94, 91, 88, 85, 82, 80, 77, 74, 72 c09600,Federal AMT liability, 212, 227, 240, 251, 268, 280, 288, 317, 351, 339, 347, 357, 371, 387, 400, 415, 430, 446, 458, 487, 496, 513 @@ -67,7 +67,7 @@ e87530,Adjusted qualified lifetime learning expenses for all students, 93, eitc,Federal EITC, 376, 369, 364, 352, 342, 340, 341, 347, 324, 335, 363, 385, 391, 395, 399, 403, 407, 411, 417, 425, 429, 436 elderly_dependents,number of dependents age 65+ in filing unit excluding taxpayer and spouse, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 g20500,Itemizable gross (before 10% AGI disregard) casualty or theft loss, 29, 30, 31, 32, 33, 35, 36, 38, 40, 41, 42, 44, 47, 48, 50, 52, 55, 57, 60, 63, 62, 66 -iitax,Federal income tax liability, 6550, 7474, 7521, 7477, 8281, 8755, 8952, 6544, 9149, 11189, 11708, 11835, 12204, 12533, 12876, 13267, 13691, 14122, 14560, 15122, 15521, 15974 +iitax,Federal income tax liability, 6550, 7474, 7521, 7477, 8281, 8755, 8952, 6544, 9149, 11189, 11708, 11835, 12203, 12533, 12876, 13267, 13691, 14122, 14560, 15122, 15521, 15974 k1bx14p,Partner self-employment earnings/loss for taxpayer (included in e26270 total), -213, -239, -187, -162, -144, -139, -133, -129, -156, -168, -183, -181, -178, -175, -168, -158, -146, -124, -103, -67, -149, -123 k1bx14s,Partner self-employment earnings/loss for spouse (included in e26270 total), -7, -9, 0, 2, 8, 10, 11, 11, 13, 14, 14, 14, 15, 16, 18, 21, 25, 27, 31, 34, 28, 33 nu06,Number of dependents under 6 years old, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 @@ -75,6 +75,6 @@ nu13,Number of dependents under 13 years old, 0, 0, 0, 0 p08000,Other tax credits (but not including Sch R credit), 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 p22250,Sch D: Net short-term capital gains/losses, -120, -173, -172, -151, -195, -212, -202, -267, -481, -308, -330, -304, -299, -292, -288, -288, -290, -293, -284, -286, -326, -335 p23250,Sch D: Net long-term capital gains/losses, 2284, 3191, 3138, 2776, 3680, 3912, 3596, 4616, 8212, 5153, 5389, 4987, 4839, 4662, 4598, 4612, 4669, 4756, 4864, 5023, 5090, 5224 -payrolltax,Payroll taxes (ee+er) for OASDI+HI, 5193, 5382, 5440, 5516, 5676, 5834, 6009, 6042, 6437, 6824, 7146, 7406, 7654, 7894, 8123, 8356, 8597, 8851, 9119, 9479, 9575, 9841 +payrolltax,Payroll taxes (ee+er) for OASDI+HI, 5193, 5382, 5440, 5516, 5676, 5834, 6009, 6042, 6437, 6824, 7161, 7422, 7670, 7911, 8141, 8374, 8616, 8870, 9138, 9499, 9596, 9862 pencon_p,Contributions to defined-contribution pension plans for taxpayer, 856, 897, 916, 941, 963, 996, 1029, 1030, 1107, 1185, 1239, 1282, 1326, 1368, 1408, 1448, 1491, 1532, 1578, 1638, 1655, 1698 pencon_s,Contributions to defined-contribution pension plans for spouse, 393, 410, 421, 424, 440, 452, 466, 466, 500, 535, 558, 577, 595, 612, 629, 645, 661, 678, 695, 720, 738, 756 diff --git a/taxcalc/tests/pufcsv_agg_expect.csv b/taxcalc/tests/pufcsv_agg_expect.csv index d3b8c3a4a..f9862f3bb 100644 --- a/taxcalc/tests/pufcsv_agg_expect.csv +++ b/taxcalc/tests/pufcsv_agg_expect.csv @@ -1,26 +1,26 @@ ,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026 Returns (#m),190.9,194.3,197.3,200.1,202.9,205.6,208.4,211.2,214.0,216.8 -AGI ($b),11078.7,11816.6,12247.2,12722.3,14930.0,14973.9,15955.0,16597.5,17310.2,17852.5 -Itemizers (#m),45.7,19.4,20.0,21.0,22.6,22.8,21.6,21.1,21.2,51.9 -Itemized Deduction ($b),1274.3,602.7,633.9,692.3,761.9,782.7,786.5,805.6,831.9,2047.9 -Standard Deduction Filers (#m),145.2,174.8,177.2,178.5,179.6,182.8,186.8,190.0,192.8,164.8 -Standard Deduction ($b),1239.3,2865.3,2954.5,3025.8,3081.1,3234.0,3549.8,3811.2,3966.7,1856.2 +AGI ($b),11078.7,11816.6,12247.2,12722.3,14930.0,14973.9,15955.0,16597.5,17310.2,17852.4 +Itemizers (#m),45.7,19.4,20.0,21.0,22.6,22.8,21.7,21.2,21.3,51.9 +Itemized Deduction ($b),1274.3,602.7,633.9,692.3,761.9,782.7,788.7,808.0,835.0,2048.0 +Standard Deduction Filers (#m),145.2,174.8,177.2,178.5,179.6,182.8,186.7,189.9,192.6,164.8 +Standard Deduction ($b),1239.3,2865.3,2954.5,3025.8,3081.1,3234.0,3537.5,3797.9,3952.2,1853.4 Personal Exemption ($b),1365.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1959.2 -Taxable Income ($b),8112.2,9179.2,9520.5,9907.3,12003.2,11927.7,12692.4,13124.8,13697.6,13377.8 -Regular Tax ($b),1656.8,1712.3,1778.2,1838.3,2281.5,2282.7,2421.7,2488.0,2599.2,2792.6 -AMT Income ($b),10512.4,11343.5,11749.7,12180.1,14330.8,14356.1,15324.3,15944.7,16632.8,16934.0 +Taxable Income ($b),8112.2,9179.2,9520.5,9907.3,12003.2,11927.7,12697.8,13130.6,13703.7,13378.4 +Regular Tax ($b),1656.8,1712.3,1778.2,1838.3,2281.5,2282.7,2423.4,2489.8,2601.1,2792.7 +AMT Income ($b),10512.4,11343.5,11749.7,12180.1,14330.8,14356.1,15323.1,15943.2,16630.7,16933.8 AMT Liability ($b),51.3,22.1,23.0,25.1,27.8,27.4,28.8,30.3,31.8,85.1 AMT Filers (#m),5.7,0.2,0.2,0.3,0.4,0.3,0.3,0.3,0.3,7.4 -Tax before Credits ($b),1708.1,1734.4,1801.1,1863.4,2309.4,2310.1,2450.5,2518.3,2631.0,2877.6 -Refundable Credits ($b),102.9,117.5,118.5,642.0,802.6,119.2,127.0,133.0,135.2,121.9 -Nonrefundable Credits ($b),67.0,127.3,129.2,128.5,47.6,141.0,143.3,143.9,145.7,77.7 +Tax before Credits ($b),1708.1,1734.4,1801.1,1863.4,2309.4,2310.1,2452.2,2520.2,2632.9,2877.8 +Refundable Credits ($b),102.9,117.5,118.5,642.0,802.6,119.2,126.9,132.8,135.0,121.8 +Nonrefundable Credits ($b),67.0,127.3,129.2,128.5,47.6,141.0,143.3,144.0,145.7,77.7 Reform Surtaxes ($b),0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 Other Taxes ($b),40.0,44.8,43.6,52.9,84.9,61.5,66.5,65.2,66.0,64.2 -Ind Income Tax ($b),1578.2,1534.3,1597.0,1145.8,1544.0,2111.5,2246.7,2306.7,2416.1,2742.2 -Payroll Taxes ($b),1083.8,1133.3,1185.4,1209.0,1306.0,1403.4,1489.3,1563.9,1637.9,1711.0 -Combined Liability ($b),2662.0,2667.7,2782.4,2354.8,2850.0,3514.9,3736.0,3870.6,4054.0,4453.2 -With Income Tax <= 0 (#m),92.8,98.6,99.7,131.7,125.0,100.3,101.9,103.4,104.4,101.0 -With Combined Tax <= 0 (#m),63.4,65.6,66.8,102.1,94.5,68.9,70.2,71.6,72.6,72.4 +Ind Income Tax ($b),1578.2,1534.3,1597.0,1145.8,1544.0,2111.5,2248.5,2308.6,2418.2,2742.6 +Payroll Taxes ($b),1083.8,1133.3,1185.4,1209.0,1306.0,1403.4,1492.6,1567.4,1641.5,1714.7 +Combined Liability ($b),2662.0,2667.7,2782.4,2354.8,2850.0,3514.9,3741.1,3876.0,4059.6,4457.3 +With Income Tax <= 0 (#m),92.8,98.6,99.7,131.7,125.0,100.3,101.8,103.4,104.3,100.9 +With Combined Tax <= 0 (#m),63.4,65.6,66.8,102.1,94.5,68.9,70.2,71.6,72.6,72.3 UBI Benefits ($b),0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 "Total Benefits, Consumption Value ($b)",1052.3,1104.9,1175.3,1243.9,1476.4,1411.5,1569.5,1707.8,1818.1,1924.4 Total Benefits Cost ($b),1052.3,1104.9,1175.3,1243.9,1476.4,1411.5,1569.5,1707.8,1818.1,1924.4 diff --git a/taxcalc/tests/test_policy.py b/taxcalc/tests/test_policy.py index 5751321df..41ba8db3e 100644 --- a/taxcalc/tests/test_policy.py +++ b/taxcalc/tests/test_policy.py @@ -43,7 +43,7 @@ def test_incorrect_class_instantiation(): Test incorrect instantiation of Policy class object. """ with pytest.raises(ValueError): - Policy(gfactors=list()) + Policy(gfactors=[]) def test_correct_class_instantiation(): @@ -54,7 +54,7 @@ def test_correct_class_instantiation(): assert pol pol.implement_reform({}) with pytest.raises(pt.ValidationError): - pol.implement_reform(list()) + pol.implement_reform([]) with pytest.raises(pt.ValidationError): pol.implement_reform({2099: {'II_em': 99000}}) pol.set_year(2019) @@ -621,7 +621,7 @@ def generate_section_dictionary(md_text): structured like the VALID_SECTION dictionary (see below) and extracted from the specified html_text. """ - sdict = dict() + sdict = {} for line in md_text.splitlines(): # This is shown as an empty case in current law policy and # validation. @@ -647,7 +647,6 @@ def generate_section_dictionary(md_text): 'As A Percent Of Deductible Expenses') cgqd_tax_same = ('Tax All Capital Gains And Dividends The Same ' 'As Regular Taxable Income') - # pylint: disable=bad-continuation valid_dict = { '': { # empty section_1 implies parameter not displayed in Tax-Brain '': 0 @@ -737,11 +736,11 @@ def generate_section_dictionary(md_text): } # check validity of parameter section titles in policy_current_law.json path = os.path.join(tests_path, '..', 'policy_current_law.json') - with open(path, 'r') as clpfile: + with open(path, 'r', encoding='utf-8') as clpfile: clpdict = json.load(clpfile) clpdict.pop("schema", None) # ... make sure ever clpdict section title is in valid_dict - clp_dict = dict() # dictionary of clp section titles structured like valid + clp_dict = {} # dictionary of clp section titles structured like valid for pname in clpdict: param = clpdict[pname] assert isinstance(param, dict) @@ -754,28 +753,28 @@ def generate_section_dictionary(md_text): if sec2title not in clp_dict[sec1title]: clp_dict[sec1title][sec2title] = 0 # ... make sure every valid_dict section title is in clpdict - for sec1title in valid_dict: - assert isinstance(valid_dict[sec1title], dict) + for sec1title, secdict in valid_dict.items(): + assert isinstance(secdict, dict) assert sec1title in clp_dict - for sec2title in valid_dict[sec1title]: + for sec2title in secdict: assert sec2title in clp_dict[sec1title] # check validity of parameter section titles in docs/uguide.htmx skeleton path = os.path.join(tests_path, '..', '..', 'docs', 'guide', 'policy_params.md') - with open(path, 'r') as md_file: + with open(path, 'r', encoding='utf-8') as md_file: md_text = md_file.read() md_dict = generate_section_dictionary(md_text) # ... make sure every md_dict section title is in valid_dict - for sec1title in md_dict: - assert isinstance(md_dict[sec1title], dict) + for sec1title,secdict in md_dict.items(): + assert isinstance(secdict, dict) assert sec1title in valid_dict - for sec2title in md_dict[sec1title]: + for sec2title in secdict: assert sec2title in valid_dict[sec1title] # ... make sure every valid_dict section title is in md_dict - for sec1title in valid_dict: - assert isinstance(valid_dict[sec1title], dict) + for sec1title, secdict in valid_dict.items(): + assert isinstance(secdict, dict) assert sec1title in md_dict - for sec2title in valid_dict[sec1title]: + for sec2title in secdict: assert sec2title in md_dict[sec1title] @@ -785,7 +784,7 @@ def test_description_punctuation(tests_path): """ # read JSON file into a dictionary path = os.path.join(tests_path, '..', 'policy_current_law.json') - with open(path, 'r') as jsonfile: + with open(path, 'r', encoding='utf-8') as jsonfile: dct = json.load(jsonfile) dct.pop("schema", None) all_desc_ok = True @@ -931,8 +930,8 @@ def test_index_offset_reform(): policy2 = Policy() policy2.implement_reform(reform2) # caused T-C crash before PR#2364 # extract from policy1 and policy2 the parameter values of CTC_c - pvalue1 = dict() - pvalue2 = dict() + pvalue1 = {} + pvalue2 = {} for cyr in [2019, 2020, 2021]: policy1.set_year(cyr) pvalue1[cyr] = policy1.CTC_c[0] @@ -945,8 +944,7 @@ def test_index_offset_reform(): # ... indexing of CTC_c begins shows up first in 2021 parameter values assert pvalue1[2021] > pvalue1[2020] assert pvalue2[2021] > pvalue2[2020] - # ... calculate expected pvalue2[2021] from offset and pvalue1 values - indexrate1 = pvalue1[2021] / pvalue1[2020] - 1. + # ... calculate expected pvalue2[2021] from inflation rates and offset syear = Policy.JSON_START_YEAR expindexrate = cpiu_rates[2020 - syear] + offset expvalue = round(pvalue2[2020] * (1. + expindexrate), 2) @@ -1032,525 +1030,509 @@ def test_raise_errors_regression(): assert pol.errors -class TestAdjust: +def test_simple_adj(): """ - Test update and indexing rules as defined in the Parameters docstring. - - Each test implements a Tax-Calculator style reform and a pt styled - reform, checks that the updated values are equal, and then, tests that - values were extended and indexed (or not indexed) correctly. + Test updating a 2D parameter that is indexed to inflation. """ - - def test_simple_adj(self): - """ - Test updating a 2D parameter that is indexed to inflation. - """ - pol1 = Policy() - pol1.implement_reform( - { - "EITC_c": { - 2020: [10000, 10001, 10002, 10003], - 2023: [20000, 20001, 20002, 20003], - } - } - ) - - pol2 = Policy() - pol2.adjust( - { - "EITC_c": [ - {"year": 2020, "EIC": "0kids", "value": 10000}, - {"year": 2020, "EIC": "1kid", "value": 10001}, - {"year": 2020, "EIC": "2kids", "value": 10002}, - {"year": 2020, "EIC": "3+kids", "value": 10003}, - {"year": 2023, "EIC": "0kids", "value": 20000}, - {"year": 2023, "EIC": "1kid", "value": 20001}, - {"year": 2023, "EIC": "2kids", "value": 20002}, - {"year": 2023, "EIC": "3+kids", "value": 20003}, - ] - } - ) - cmp_policy_objs(pol1, pol2) - - pol0 = Policy() - pol0.set_year(2019) - pol2.set_year(2019) - - assert np.allclose(pol0.EITC_c, pol2.EITC_c) - - pol2.set_state(year=[2020, 2021, 2022, 2023, 2024]) - val2020 = np.array([[10000, 10001, 10002, 10003]]) - val2023 = np.array([[20000, 20001, 20002, 20003]]) - - exp = np.vstack([ - val2020, - val2020 * (1 + pol2.inflation_rates(year=2020)), - ( - val2020 * (1 + pol2.inflation_rates(year=2020)) - ).round(2) * (1 + pol2.inflation_rates(year=2021)), - val2023, - val2023 * (1 + pol2.inflation_rates(year=2023)), - ]).round(2) - np.testing.assert_allclose(pol2.EITC_c, exp) - - def test_adj_without_index_1(self): - """ - Test update indexed parameter after turning off its - indexed status. - """ - pol1 = Policy() - pol1.implement_reform( - { - "EITC_c": { - 2020: [10000, 10001, 10002, 10003], - 2023: [20000, 20001, 20002, 20003], - }, - "EITC_c-indexed": {2019: False}, - } - ) - - pol2 = Policy() - pol2.adjust( - { - "EITC_c": [ - {"year": 2020, "EIC": "0kids", "value": 10000}, - {"year": 2020, "EIC": "1kid", "value": 10001}, - {"year": 2020, "EIC": "2kids", "value": 10002}, - {"year": 2020, "EIC": "3+kids", "value": 10003}, - {"year": 2023, "EIC": "0kids", "value": 20000}, - {"year": 2023, "EIC": "1kid", "value": 20001}, - {"year": 2023, "EIC": "2kids", "value": 20002}, - {"year": 2023, "EIC": "3+kids", "value": 20003}, - ], - "EITC_c-indexed": [{"year": 2019, "value": False}], + pol1 = Policy() + pol1.implement_reform( + { + "EITC_c": { + 2020: [10000, 10001, 10002, 10003], + 2023: [20000, 20001, 20002, 20003], } - ) - cmp_policy_objs(pol1, pol2) + } + ) + pol2 = Policy() + pol2.adjust( + { + "EITC_c": [ + {"year": 2020, "EIC": "0kids", "value": 10000}, + {"year": 2020, "EIC": "1kid", "value": 10001}, + {"year": 2020, "EIC": "2kids", "value": 10002}, + {"year": 2020, "EIC": "3+kids", "value": 10003}, + {"year": 2023, "EIC": "0kids", "value": 20000}, + {"year": 2023, "EIC": "1kid", "value": 20001}, + {"year": 2023, "EIC": "2kids", "value": 20002}, + {"year": 2023, "EIC": "3+kids", "value": 20003}, + ] + } + ) + cmp_policy_objs(pol1, pol2) - pol0 = Policy() - pol0.set_year(2019) - pol2.set_year(2019) + pol0 = Policy() + pol0.set_year(2019) + pol2.set_year(2019) - assert np.allclose(pol0.EITC_c, pol2.EITC_c) + assert np.allclose(pol0.EITC_c, pol2.EITC_c) - pol2.set_state(year=[2020, 2021, 2022, 2023, 2024]) + pol2.set_state(year=[2020, 2021, 2022, 2023, 2024]) + val2020 = np.array([[10000, 10001, 10002, 10003]]) + val2023 = np.array([[20000, 20001, 20002, 20003]]) - val2020 = np.array([[10000, 10001, 10002, 10003]]) - val2023 = np.array([[20000, 20001, 20002, 20003]]) + exp = np.vstack([ + val2020, + val2020 * (1 + pol2.inflation_rates(year=2020)), + ( + val2020 * (1 + pol2.inflation_rates(year=2020)) + ).round(2) * (1 + pol2.inflation_rates(year=2021)), + val2023, + val2023 * (1 + pol2.inflation_rates(year=2023)), + ]).round(2) + np.testing.assert_allclose(pol2.EITC_c, exp) - exp = np.vstack([ - val2020, - val2020, - val2020, - val2023, - val2023, - ]).round(2) - np.testing.assert_allclose(pol2.EITC_c, exp) - def test_adj_without_index_2(self): - """ - Test updating an indexed parameter, making it unindexed, - and then adjusting it again. - """ - pol1 = Policy() - pol1.implement_reform( - { - "EITC_c": { - 2020: [10000, 10001, 10002, 10003], - 2023: [20000, 20001, 20002, 20003], - }, - "EITC_c-indexed": {2022: False}, - } - ) +def test_adj_without_index_1(): + """ + Test update indexed parameter after turning off its indexed status. + """ + pol1 = Policy() + pol1.implement_reform( + { + "EITC_c": { + 2020: [10000, 10001, 10002, 10003], + 2023: [20000, 20001, 20002, 20003], + }, + "EITC_c-indexed": {2019: False}, + } + ) + pol2 = Policy() + pol2.adjust( + { + "EITC_c": [ + {"year": 2020, "EIC": "0kids", "value": 10000}, + {"year": 2020, "EIC": "1kid", "value": 10001}, + {"year": 2020, "EIC": "2kids", "value": 10002}, + {"year": 2020, "EIC": "3+kids", "value": 10003}, + {"year": 2023, "EIC": "0kids", "value": 20000}, + {"year": 2023, "EIC": "1kid", "value": 20001}, + {"year": 2023, "EIC": "2kids", "value": 20002}, + {"year": 2023, "EIC": "3+kids", "value": 20003}, + ], + "EITC_c-indexed": [{"year": 2019, "value": False}], + } + ) + cmp_policy_objs(pol1, pol2) - pol2 = Policy() - pol2.adjust( - { - "EITC_c": [ - {"year": 2020, "EIC": "0kids", "value": 10000}, - {"year": 2020, "EIC": "1kid", "value": 10001}, - {"year": 2020, "EIC": "2kids", "value": 10002}, - {"year": 2020, "EIC": "3+kids", "value": 10003}, - {"year": 2023, "EIC": "0kids", "value": 20000}, - {"year": 2023, "EIC": "1kid", "value": 20001}, - {"year": 2023, "EIC": "2kids", "value": 20002}, - {"year": 2023, "EIC": "3+kids", "value": 20003}, - ], - "EITC_c-indexed": [{"year": 2022, "value": False}], - } - ) - cmp_policy_objs(pol1, pol2) + pol0 = Policy() + pol0.set_year(2019) + pol2.set_year(2019) - pol0 = Policy() - pol0.set_year(2019) - pol2.set_year(2019) + assert np.allclose(pol0.EITC_c, pol2.EITC_c) - assert np.allclose(pol0.EITC_c, pol2.EITC_c) + pol2.set_state(year=[2020, 2021, 2022, 2023, 2024]) - pol2.set_state(year=[2020, 2021, 2022, 2023, 2024]) + val2020 = np.array([[10000, 10001, 10002, 10003]]) + val2023 = np.array([[20000, 20001, 20002, 20003]]) - val2020 = np.array([[10000, 10001, 10002, 10003]]) - val2023 = np.array([[20000, 20001, 20002, 20003]]) + exp = np.vstack([ + val2020, + val2020, + val2020, + val2023, + val2023, + ]).round(2) + np.testing.assert_allclose(pol2.EITC_c, exp) - exp = np.vstack([ - val2020, - val2020 * (1 + pol2.inflation_rates(year=2020)), - ( - val2020 * (1 + pol2.inflation_rates(year=2020)) - ).round(2) * (1 + pol2.inflation_rates(year=2021)), - val2023, - val2023, - ]).round(2) - np.testing.assert_allclose(pol2.EITC_c, exp) - def test_activate_index(self): - """ - Test changing a non-indexed parameter to an indexed parameter. - """ - pol1 = Policy() - pol1.implement_reform({ - "CTC_c": {2022: 2000}, - "CTC_c-indexed": {2022: True} - }) - - pol2 = Policy() - pol2.adjust( - { - "CTC_c": [{"year": 2022, "value": 2000}], - "CTC_c-indexed": [{"year": 2022, "value": True}], - } - ) - cmp_policy_objs(pol1, pol2) +def test_adj_without_index_2(): + """ + Test updating an indexed parameter, making it unindexed, + and then adjusting it again. + """ + pol1 = Policy() + pol1.implement_reform( + { + "EITC_c": { + 2020: [10000, 10001, 10002, 10003], + 2023: [20000, 20001, 20002, 20003], + }, + "EITC_c-indexed": {2022: False}, + } + ) + pol2 = Policy() + pol2.adjust( + { + "EITC_c": [ + {"year": 2020, "EIC": "0kids", "value": 10000}, + {"year": 2020, "EIC": "1kid", "value": 10001}, + {"year": 2020, "EIC": "2kids", "value": 10002}, + {"year": 2020, "EIC": "3+kids", "value": 10003}, + {"year": 2023, "EIC": "0kids", "value": 20000}, + {"year": 2023, "EIC": "1kid", "value": 20001}, + {"year": 2023, "EIC": "2kids", "value": 20002}, + {"year": 2023, "EIC": "3+kids", "value": 20003}, + ], + "EITC_c-indexed": [{"year": 2022, "value": False}], + } + ) + cmp_policy_objs(pol1, pol2) - pol0 = Policy() - pol0.set_year(year=2021) - pol2.set_state(year=[2021, 2022, 2023]) - exp = np.array([ - pol0.CTC_c[0], - 2000, - 2000 * (1 + pol2.inflation_rates(year=2022)) - ]).round(2) + pol0 = Policy() + pol0.set_year(2019) + pol2.set_year(2019) - np.testing.assert_allclose(pol2.CTC_c, exp) + assert np.allclose(pol0.EITC_c, pol2.EITC_c) - def test_apply_cpi_offset(self): - """ - Test applying the parameter_indexing_CPI_offset parameter - without any other parameters. - """ - pol1 = Policy() - pol1.implement_reform( - {"parameter_indexing_CPI_offset": {2021: -0.001}} - ) + pol2.set_state(year=[2020, 2021, 2022, 2023, 2024]) - pol2 = Policy() - pol2.adjust( - {"parameter_indexing_CPI_offset": [ - {"year": 2021, "value": -0.001} - ]} - ) + val2020 = np.array([[10000, 10001, 10002, 10003]]) + val2023 = np.array([[20000, 20001, 20002, 20003]]) - cmp_policy_objs(pol1, pol2) + exp = np.vstack([ + val2020, + val2020 * (1 + pol2.inflation_rates(year=2020)), + ( + val2020 * (1 + pol2.inflation_rates(year=2020)) + ).round(2) * (1 + pol2.inflation_rates(year=2021)), + val2023, + val2023, + ]).round(2) + np.testing.assert_allclose(pol2.EITC_c, exp) - pol0 = Policy() - pol0.implement_reform({"parameter_indexing_CPI_offset": {2021: 0}}) - init_rates = pol0.inflation_rates() - new_rates = pol2.inflation_rates() +def test_activate_index(): + """ + Test changing a non-indexed parameter to an indexed parameter. + """ + pol1 = Policy() + pol1.implement_reform({ + "CTC_c": {2022: 2000}, + "CTC_c-indexed": {2022: True} + }) + pol2 = Policy() + pol2.adjust( + { + "CTC_c": [{"year": 2022, "value": 2000}], + "CTC_c-indexed": [{"year": 2022, "value": True}], + } + ) + cmp_policy_objs(pol1, pol2) - start_ix = 2021 - pol2.start_year + pol0 = Policy() + pol0.set_year(year=2021) + pol2.set_state(year=[2021, 2022, 2023]) + exp = np.array([ + pol0.CTC_c[0], + 2000, + 2000 * (1 + pol2.inflation_rates(year=2022)) + ]).round(2) - exp_rates = copy.deepcopy(new_rates) - exp_rates[start_ix:] -= pol2._parameter_indexing_CPI_offset[start_ix:] - np.testing.assert_allclose(init_rates, exp_rates) + np.testing.assert_allclose(pol2.CTC_c, exp) - # make sure values prior to 2021 were not affected. - cmp_policy_objs(pol0, pol2, year_range=range(pol2.start_year, 2021)) - pol2.set_state(year=[2022, 2023]) - np.testing.assert_equal( - (pol2.EITC_c[1] / pol2.EITC_c[0] - 1).round(4), - (pol0.inflation_rates(year=2022) + (-0.001)).round(4), - ) +def test_apply_cpi_offset(): + """ + Test applying the parameter_indexing_CPI_offset parameter + without any other parameters. + """ + pol1 = Policy() + pol1.implement_reform( + {"parameter_indexing_CPI_offset": {2021: -0.001}} + ) + pol2 = Policy() + pol2.adjust( + {"parameter_indexing_CPI_offset": [ + {"year": 2021, "value": -0.001} + ]} + ) + cmp_policy_objs(pol1, pol2) - def test_multiple_cpi_swaps(self): - """ - Test changing a parameter's indexed status multiple times. - """ - pol1 = Policy() - pol1.implement_reform( - { - "II_em": {2016: 6000, 2018: 7500, 2020: 9000}, - "II_em-indexed": {2016: False, 2018: True}, - } - ) + pol0 = Policy() + pol0.implement_reform({"parameter_indexing_CPI_offset": {2021: 0}}) - pol2 = Policy() - pol2.adjust( - { - "II_em": [ - {"year": 2016, "value": 6000}, - {"year": 2018, "value": 7500}, - {"year": 2020, "value": 9000}, - ], - "II_em-indexed": [ - {"year": 2016, "value": False}, - {"year": 2018, "value": True}, - ], - } - ) + init_rates = pol0.inflation_rates() + new_rates = pol2.inflation_rates() - cmp_policy_objs(pol1, pol2) + start_ix = 2021 - pol2.start_year - # check inflation is not applied. - pol2.set_state(year=[2016, 2017]) - np.testing.assert_equal( - pol2.II_em[0], pol2.II_em[1] - ) + exp_rates = copy.deepcopy(new_rates) + exp_rates[start_ix:] -= pol2._parameter_indexing_CPI_offset[start_ix:] + np.testing.assert_allclose(init_rates, exp_rates) - # check inflation rate is applied. - pol2.set_state(year=[2018, 2019]) - np.testing.assert_equal( - (pol2.II_em[1] / pol2.II_em[0] - 1).round(4), - pol2.inflation_rates(year=2018), - ) + # make sure values prior to 2021 were not affected. + cmp_policy_objs(pol0, pol2, year_range=range(pol2.start_year, 2021)) - # check inflation rate applied for rest of window. - window = list(range(2020, pol2.end_year + 1)) - pol2.set_state(year=window) - np.testing.assert_equal( - (pol2.II_em[1:] / pol2.II_em[:-1] - 1).round(4), - [pol2.inflation_rates(year=year) for year in window[:-1]], - ) + test_year = Policy.LAST_KNOWN_YEAR + pol2.set_state(year=[test_year, test_year + 1]) + np.testing.assert_equal( + (pol2.EITC_c[1] / pol2.EITC_c[0] - 1).round(4), + (pol0.inflation_rates(year=test_year) + (-0.001)).round(4), + ) - def test_multiple_cpi_swaps2(self): - """ - Test changing the indexed status of multiple parameters multiple - times. - """ - pol1 = Policy() - pol1.implement_reform( - { - "II_em": {2016: 6000, 2018: 7500, 2020: 9000}, - "II_em-indexed": {2016: False, 2018: True}, - "SS_Earnings_c": {2016: 300000, 2018: 500000}, - "SS_Earnings_c-indexed": {2017: False, 2019: True}, - "AMT_em-indexed": {2017: False, 2020: True}, - } - ) - pol2 = Policy() - pol2.adjust( - { - "SS_Earnings_c": [ - {"year": 2016, "value": 300000}, - {"year": 2018, "value": 500000}, - ], - "SS_Earnings_c-indexed": [ - {"year": 2017, "value": False}, - {"year": 2019, "value": True}, - ], - "AMT_em-indexed": [ - {"year": 2017, "value": False}, - {"year": 2020, "value": True}, - ], - "II_em": [ - {"year": 2016, "value": 6000}, - {"year": 2018, "value": 7500}, - {"year": 2020, "value": 9000}, - ], - "II_em-indexed": [ - {"year": 2016, "value": False}, - {"year": 2018, "value": True}, - ], - } - ) +def test_multiple_cpi_swaps(): + """ + Test changing a parameter's indexed status multiple times. + """ + pol1 = Policy() + pol1.implement_reform( + { + "II_em": {2016: 6000, 2018: 7500, 2020: 9000}, + "II_em-indexed": {2016: False, 2018: True}, + } + ) + pol2 = Policy() + pol2.adjust( + { + "II_em": [ + {"year": 2016, "value": 6000}, + {"year": 2018, "value": 7500}, + {"year": 2020, "value": 9000}, + ], + "II_em-indexed": [ + {"year": 2016, "value": False}, + {"year": 2018, "value": True}, + ], + } + ) + cmp_policy_objs(pol1, pol2) - cmp_policy_objs(pol1, pol2) + # check inflation is not applied. + pol2.set_state(year=[2016, 2017]) + np.testing.assert_equal( + pol2.II_em[0], pol2.II_em[1] + ) - # Test SS_Earnings_c - # check inflation is still applied from 2016 to 2017. - pol2.set_state(year=[2016, 2017]) - np.testing.assert_equal( - (pol2.SS_Earnings_c[1] / pol2.SS_Earnings_c[0] - 1).round(4), - pol2.wage_growth_rates(year=2016), - ) + # check inflation rate is applied. + pol2.set_state(year=[2018, 2019]) + np.testing.assert_equal( + (pol2.II_em[1] / pol2.II_em[0] - 1).round(4), + pol2.inflation_rates(year=2018), + ) - # check inflation rate is not applied after adjustment in 2018. - pol2.set_state(year=[2018, 2019]) - np.testing.assert_equal( - pol2.SS_Earnings_c[0], pol2.SS_Earnings_c[1] - ) + # check inflation rate applied for rest of window. + window = list(range(2020, pol2.end_year + 1)) + pol2.set_state(year=window) + np.testing.assert_equal( + (pol2.II_em[1:] / pol2.II_em[:-1] - 1).round(4), + [pol2.inflation_rates(year=year) for year in window[:-1]], + ) - # check inflation rate applied for rest of window. - window = list(range(2019, pol2.end_year + 1)) - pol2.set_state(year=window) - np.testing.assert_equal( - (pol2.SS_Earnings_c[1:] / pol2.SS_Earnings_c[:-1] - 1).round(4), - [pol2.wage_growth_rates(year=year) for year in window[:-1]], - ) - # Test AMT - # Check values for 2017 through 2020 are equal. - pol2.set_state(year=[2017, 2018, 2019, 2020]) - for i in (1, 2, 3): - np.testing.assert_equal( - pol2.AMT_em[0], pol2.AMT_em[i] - ) - - # check inflation rate applied for rest of window. - window = list(range(2020, pol2.end_year + 1)) - pol2.set_state(year=window) - # repeat inflation rates accross matrix so they can be compared to the - # rates derived from AMT_em, a 5 * N matrix. - exp_rates = [pol2.inflation_rates(year=year) for year in window[:-1]] - exp_rates = np.tile([exp_rates], (5, 1)).transpose() - np.testing.assert_equal( - (pol2.AMT_em[1:] / pol2.AMT_em[:-1] - 1).round(4), - exp_rates, - ) +def test_multiple_cpi_swaps2(): + """ + Test changing the indexed status of multiple parameters multiple times. + """ + pol1 = Policy() + pol1.implement_reform( + { + "II_em": {2016: 6000, 2018: 7500, 2020: 9000}, + "II_em-indexed": {2016: False, 2018: True}, + "SS_Earnings_c": {2016: 300000, 2018: 500000}, + "SS_Earnings_c-indexed": {2017: False, 2019: True}, + "AMT_em-indexed": {2017: False, 2020: True}, + } + ) + pol2 = Policy() + pol2.adjust( + { + "SS_Earnings_c": [ + {"year": 2016, "value": 300000}, + {"year": 2018, "value": 500000}, + ], + "SS_Earnings_c-indexed": [ + {"year": 2017, "value": False}, + {"year": 2019, "value": True}, + ], + "AMT_em-indexed": [ + {"year": 2017, "value": False}, + {"year": 2020, "value": True}, + ], + "II_em": [ + {"year": 2016, "value": 6000}, + {"year": 2018, "value": 7500}, + {"year": 2020, "value": 9000}, + ], + "II_em-indexed": [ + {"year": 2016, "value": False}, + {"year": 2018, "value": True}, + ], + } + ) + cmp_policy_objs(pol1, pol2) + + # Test SS_Earnings_c + # check inflation is still applied from 2016 to 2017. + pol2.set_state(year=[2016, 2017]) + np.testing.assert_equal( + (pol2.SS_Earnings_c[1] / pol2.SS_Earnings_c[0] - 1).round(4), + pol2.wage_growth_rates(year=2016), + ) - # Test II_em - # check inflation is not applied. - pol2.set_state(year=[2016, 2017]) - np.testing.assert_equal( - pol2.II_em[0], pol2.II_em[1] - ) + # check inflation rate is not applied after adjustment in 2018. + pol2.set_state(year=[2018, 2019]) + np.testing.assert_equal( + pol2.SS_Earnings_c[0], pol2.SS_Earnings_c[1] + ) - # check inflation rate is applied. - pol2.set_state(year=[2018, 2019]) - np.testing.assert_equal( - (pol2.II_em[1] / pol2.II_em[0] - 1).round(4), - pol2.inflation_rates(year=2018), - ) + # check inflation rate applied for rest of window. + window = list(range(2019, pol2.end_year + 1)) + pol2.set_state(year=window) + np.testing.assert_equal( + (pol2.SS_Earnings_c[1:] / pol2.SS_Earnings_c[:-1] - 1).round(4), + [pol2.wage_growth_rates(year=year) for year in window[:-1]], + ) - # check inflation rate applied for rest of window. - window = list(range(2020, pol2.end_year + 1)) - pol2.set_state(year=window) + # Test AMT + # Check values for 2017 through 2020 are equal. + pol2.set_state(year=[2017, 2018, 2019, 2020]) + for i in (1, 2, 3): np.testing.assert_equal( - (pol2.II_em[1:] / pol2.II_em[:-1] - 1).round(4), - [pol2.inflation_rates(year=year) for year in window[:-1]], - ) - - def test_adj_CPI_offset_and_index_status(self): - """ - Test changing parameter_indexing_CPI_offset and another - parameter simultaneously. - """ - pol1 = Policy() - pol1.implement_reform({ - "CTC_c-indexed": {2020: True}, - "parameter_indexing_CPI_offset": {2020: -0.005}}, - ) - - pol2 = Policy() - pol2.adjust( - { - "parameter_indexing_CPI_offset": - [{"year": 2020, "value": -0.005}], - "CTC_c-indexed": [{"year": 2020, "value": True}], - } + pol2.AMT_em[0], pol2.AMT_em[i] ) - cmp_policy_objs(pol1, pol2) - - # Check no difference prior to 2020 - pol0 = Policy() - pol0.implement_reform({"parameter_indexing_CPI_offset": {2020: 0}}) - cmp_policy_objs( - pol0, - pol2, - year_range=range(pol2.start_year, 2020 + 1), - exclude=["parameter_indexing_CPI_offset"] - ) + # check inflation rate applied for rest of window. + window = list(range(2020, pol2.end_year + 1)) + pol2.set_state(year=window) + # repeat inflation rates accross matrix so they can be compared to the + # rates derived from AMT_em, a 5 * N matrix. + exp_rates = [pol2.inflation_rates(year=year) for year in window[:-1]] + exp_rates = np.tile([exp_rates], (5, 1)).transpose() + np.testing.assert_equal( + (pol2.AMT_em[1:] / pol2.AMT_em[:-1] - 1).round(4), + exp_rates, + ) - pol2.set_state(year=[2021, 2022]) - np.testing.assert_equal( - (pol2.CTC_c[1] / pol2.CTC_c[0] - 1).round(4), - round(pol0.inflation_rates(year=2021) + (-0.005), 4), - ) + # Test II_em + # check inflation is not applied. + pol2.set_state(year=[2016, 2017]) + np.testing.assert_equal( + pol2.II_em[0], pol2.II_em[1] + ) - def test_adj_related_parameters_and_index_status(self): - """ - Test changing two related parameters simulataneously and - one of their indexed statuses. - """ + # check inflation rate is applied. + pol2.set_state(year=[2018, 2019]) + np.testing.assert_equal( + (pol2.II_em[1] / pol2.II_em[0] - 1).round(4), + pol2.inflation_rates(year=2018), + ) - pol = Policy() - pol.adjust( - { - "II_brk7-indexed": [{"year": 2020, "value": True}], - # Update II_brk5 in 2026 to make reform valid after reset. - "II_brk5": [{"value": 330000, "MARS": "single", "year": 2026}], - "II_brk6": [{"value": 316700, "MARS": "single", "year": 2020}], - "II_brk7": [{"value": 445400, "MARS": "single", "year": 2020}], - } - ) + # check inflation rate applied for rest of window. + window = list(range(2020, pol2.end_year + 1)) + pol2.set_state(year=window) + np.testing.assert_equal( + (pol2.II_em[1:] / pol2.II_em[:-1] - 1).round(4), + [pol2.inflation_rates(year=year) for year in window[:-1]], + ) - # Check no difference prior to 2020 - pol0 = Policy() - cmp_policy_objs( - pol0, - pol, - year_range=range(pol.start_year, 2019 + 1), - ) - res = ( - (pol.sel["II_brk6"]["MARS"] == "single") - & (pol.sel["II_brk6"]["year"] == 2020) - ) - assert res.isel[0]["value"] == [316700] - res = ( - (pol.sel["II_brk7"]["MARS"] == "single") - & (pol.sel["II_brk7"]["year"] == 2020) - ) - assert res.isel[0]["value"] == [445400] +def test_adj_CPI_offset_and_index_status(): + """ + Test changing parameter_indexing_CPI_offset and another + parameter simultaneously. + """ + pol1 = Policy() + pol1.implement_reform({ + "CTC_c-indexed": {2020: True}, + "parameter_indexing_CPI_offset": {2020: -0.005}}, + ) + pol2 = Policy() + pol2.adjust( + { + "parameter_indexing_CPI_offset": + [{"year": 2020, "value": -0.005}], + "CTC_c-indexed": [{"year": 2020, "value": True}], + } + ) + cmp_policy_objs(pol1, pol2) + + # Check no difference prior to 2020 + pol0 = Policy() + pol0.implement_reform({"parameter_indexing_CPI_offset": {2020: 0}}) + cmp_policy_objs( + pol0, + pol2, + year_range=range(pol2.start_year, 2020 + 1), + exclude=["parameter_indexing_CPI_offset"] + ) - II_brk7 = pol.to_array("II_brk7", year=[2021, 2022]) - II_brk7_single = II_brk7[:, 0] - np.testing.assert_equal( - (II_brk7_single[1] / II_brk7_single[0] - 1).round(4), - pol.inflation_rates(year=2021), - ) + pol2.set_state(year=[2021, 2022]) + np.testing.assert_equal( + (pol2.CTC_c[1] / pol2.CTC_c[0] - 1).round(4), + round(pol0.inflation_rates(year=2021) + (-0.005), 4), + ) - def test_indexed_status_parsing(self): - pol1 = Policy() - pol1.implement_reform({"EITC_c-indexed": {pol1.start_year: False}}) +def test_adj_related_parameters_and_index_status(): + """ + Test changing two related parameters simulataneously and + one of their indexed statuses. + """ + pol = Policy() + pol.adjust( + { + "II_brk7-indexed": [{"year": 2020, "value": True}], + # Update II_brk5 in 2026 to make reform valid after reset. + "II_brk5": [{"value": 330000, "MARS": "single", "year": 2026}], + "II_brk6": [{"value": 316700, "MARS": "single", "year": 2020}], + "II_brk7": [{"value": 445400, "MARS": "single", "year": 2020}], + } + ) - pol2 = Policy() - pol2.adjust({"EITC_c-indexed": False}) + # Check no difference prior to 2020 + pol0 = Policy() + cmp_policy_objs( + pol0, + pol, + year_range=range(pol.start_year, 2019 + 1), + ) - cmp_policy_objs(pol1, pol2) + res = ( + (pol.sel["II_brk6"]["MARS"] == "single") + & (pol.sel["II_brk6"]["year"] == 2020) + ) + assert res.isel[0]["value"] == [316700] + res = ( + (pol.sel["II_brk7"]["MARS"] == "single") + & (pol.sel["II_brk7"]["year"] == 2020) + ) + assert res.isel[0]["value"] == [445400] - with pytest.raises(pt.ValidationError): - pol2.adjust({"EITC_c-indexed": 123}) + II_brk7 = pol.to_array("II_brk7", year=[2021, 2022]) + II_brk7_single = II_brk7[:, 0] + np.testing.assert_equal( + (II_brk7_single[1] / II_brk7_single[0] - 1).round(4), + pol.inflation_rates(year=2021), + ) - def test_cpi_offset_does_not_affect_wage_indexed_params(self): - """ - Test adjusting parameter_indexing_CPI_offset does not affect unknown - values of wage indexed parameters like SS_Earnings_c. - """ - base_reform = { - "parameter_indexing_CPI_offset": {2021: -0.001}, - "SS_Earnings_c": {2024: 300000}, - } - pol0 = Policy() - pol0.implement_reform(base_reform) +def test_indexed_status_parsing(): + """ + Test parsing. + """ + pol1 = Policy() + pol1.implement_reform({"EITC_c-indexed": {pol1.start_year: False}}) + pol2 = Policy() + pol2.adjust({"EITC_c-indexed": False}) + cmp_policy_objs(pol1, pol2) - pol1 = Policy() - pol1.implement_reform(base_reform) - pol1.implement_reform(dict(base_reform, SS_Earnings_c={2025: 500000})) + with pytest.raises(pt.ValidationError): + pol2.adjust({"EITC_c-indexed": 123}) - exp_before_2025 = pol0.to_array( - "SS_Earnings_c", year=list(range(2021, 2024 + 1)) - ) - act_before_2025 = pol1.to_array( - "SS_Earnings_c", year=list(range(2021, 2024 + 1)) - ) - np.testing.assert_equal(act_before_2025, exp_before_2025) +def test_cpi_offset_does_not_affect_wage_indexed_params(): + """ + Test adjusting parameter_indexing_CPI_offset does not affect unknown + values of wage indexed parameters like SS_Earnings_c. + """ + base_reform = { + "parameter_indexing_CPI_offset": {2021: -0.001}, + "SS_Earnings_c": {2024: 300000}, + } + pol0 = Policy() + pol0.implement_reform(base_reform) + pol1 = Policy() + pol1.implement_reform(base_reform) + pol1.implement_reform(dict(base_reform, SS_Earnings_c={2025: 500000})) + + exp_before_2025 = pol0.to_array( + "SS_Earnings_c", year=list(range(2021, 2024 + 1)) + ) + act_before_2025 = pol1.to_array( + "SS_Earnings_c", year=list(range(2021, 2024 + 1)) + ) + np.testing.assert_equal(act_before_2025, exp_before_2025) def test_two_sets_of_tax_brackets(): diff --git a/taxcalc/tests/test_reforms.py b/taxcalc/tests/test_reforms.py index 5f63f7f44..8fe74799d 100644 --- a/taxcalc/tests/test_reforms.py +++ b/taxcalc/tests/test_reforms.py @@ -97,41 +97,42 @@ def test_round_trip_reforms(fyear, tests_path): rtr_pol = Policy() # Revert to 2017 law reform_file = os.path.join(tests_path, '..', 'reforms', '2017_law.json') - with open(reform_file, 'r') as rfile: + with open(reform_file, 'r', encoding='utf-8') as rfile: rtext = rfile.read() rtr_pol.implement_reform(Policy.read_json_reform(rtext)) assert not rtr_pol.parameter_warnings assert not rtr_pol.errors # Layer on TCJA reform_file = os.path.join(tests_path, '..', 'reforms', 'TCJA.json') - with open(reform_file, 'r') as rfile: + with open(reform_file, 'r', encoding='utf-8') as rfile: rtext = rfile.read() rtr_pol.implement_reform(Policy.read_json_reform(rtext)) assert not rtr_pol.parameter_warnings assert not rtr_pol.errors # Layer on the CARES Act reform_file = os.path.join(tests_path, '..', 'reforms', 'CARES.json') - with open(reform_file, 'r') as rfile: + with open(reform_file, 'r', encoding='utf-8') as rfile: rtext = rfile.read() rtr_pol.implement_reform(Policy.read_json_reform(rtext)) # Layer on the Consolidated Appropriations Act of 2021 - reform_file = os.path.join(tests_path, '..', 'reforms', - 'ConsolidatedAppropriationsAct2021.json') - with open(reform_file, 'r') as rfile: + reform_file = os.path.join( + tests_path, '..', 'reforms', 'ConsolidatedAppropriationsAct2021.json' + ) + with open(reform_file, 'r', encoding='utf-8') as rfile: rtext = rfile.read() rtr_pol.implement_reform(Policy.read_json_reform(rtext)) assert not rtr_pol.parameter_warnings assert not rtr_pol.errors # Layer on ARPA reform_file = os.path.join(tests_path, '..', 'reforms', 'ARPA.json') - with open(reform_file, 'r') as rfile: + with open(reform_file, 'r', encoding='utf-8') as rfile: rtext = rfile.read() rtr_pol.implement_reform(Policy.read_json_reform(rtext)) assert not rtr_pol.parameter_warnings assert not rtr_pol.errors - # Layer on 2022 rounding from IRS - reform_file = os.path.join(tests_path, '..', 'reforms', 'rounding2022.json') - with open(reform_file, 'r') as rfile: + # Layer on rounding from IRS through Policy.LAST_KNOWN_YEAR + reform_file = os.path.join(tests_path, '..', 'reforms', 'rounding.json') + with open(reform_file, 'r', encoding='utf-8') as rfile: rtext = rfile.read() rtr_pol.implement_reform(Policy.read_json_reform(rtext)) assert not rtr_pol.parameter_warnings @@ -142,9 +143,9 @@ def test_round_trip_reforms(fyear, tests_path): assert clp_mdata.keys() == rtr_mdata.keys() fail_dump = False if fail_dump: - rtr_fails = open('fails_rtr', 'w') - clp_fails = open('fails_clp', 'w') - fail_params = list() + rtr_fails = open('fails_rtr', 'w', encoding='utf-8') + clp_fails = open('fails_clp', 'w', encoding='utf-8') + fail_params = [] msg = '\nRound-trip-reform and current-law-policy param values differ for:' for pname in clp_mdata.keys(): rtr_val = rtr_mdata[pname] @@ -364,7 +365,7 @@ def test_ext_reform(tests_path): end.set_year(2026) ext = Policy() reform_file = os.path.join(tests_path, '..', 'reforms', 'ext.json') - with open(reform_file, 'r') as rfile: + with open(reform_file, 'r', encoding='utf-8') as rfile: rtext = rfile.read() ext.implement_reform(Policy.read_json_reform(rtext)) assert not ext.parameter_warnings @@ -382,4 +383,4 @@ def test_ext_reform(tests_path): iitax_ext = calc_ext.array('iitax') rdiff = iitax_ext - iitax_end weighted_sum_rdiff = (rdiff * calc_end.array('s006')).sum() * 1.0e-9 - assert np.allclose([weighted_sum_rdiff], [-224.45], rtol=0.0, atol=0.01) + assert np.allclose([weighted_sum_rdiff], [-224.42], rtol=0.0, atol=0.01) diff --git a/update_pcl.py b/update_pcl.py new file mode 100644 index 000000000..f948618df --- /dev/null +++ b/update_pcl.py @@ -0,0 +1,303 @@ +""" +This script uses known values of inflation-indexed policy parameters after +2022 to write an updated version of the taxcalc/policy_current_law.json file. + +USAGE: (taxcalc-dev) Tax-Calculator% python update_pcl.py + +THEN: look at differences between the newly written pcl.json file and + the old existing taxcalc/policy_current_law.json file +""" + +import os +import sys +import json + + +LIST_MARS_ZERO = [ + {'year': 2023, 'MARS': 'single', 'value': 0.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 0.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 0.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 0.0}, + {'year': 2023, 'MARS': 'widow', 'value': 0.0}, +] +LIST_MARS_INF = [ + {'year': 2023, 'MARS': 'single', 'value': 9e99}, + {'year': 2023, 'MARS': 'mjoint', 'value': 9e99}, + {'year': 2023, 'MARS': 'mseparate', 'value': 9e99}, + {'year': 2023, 'MARS': 'headhh', 'value': 9e99}, + {'year': 2023, 'MARS': 'widow', 'value': 9e99}, +] +LIST_SCALAR_ZERO = [ + {'year': 2023, 'value': 0.0}, +] +NEW_KNOWN_ITEMS = { + # PAYROLL TAX PARAMETER SOURCES: + # - SSA Office of the Chief Actuary: Contribution and Benefit Base + # https://www.ssa.gov/OACT/COLA/cbb.html + 'SS_Earnings_c': [ + {'year': 2023, 'value': 160200.0}, + # {'year': 2024, 'value': 168600.0}, + ], + # INCOME TAX PARAMETER SOURCES: + # - IRS Rev. Proc. 2022-38 containing 2023 policy parameter values is at: + # https://www.irs.gov/pub/irs-drop/rp-22-38.pdf + # - IRS Rev. Proc. 2023-34 containing 2024 policy parameter values is at: + # https://www.irs.gov/pub/irs-drop/rp-23-34.pdf + 'II_brk1': [ + {'year': 2023, 'MARS': 'single', 'value': 11000.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 22000.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 11000.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 15700.0}, + {'year': 2023, 'MARS': 'widow', 'value': 22000.0}, + ], + 'II_brk2': [ + {'year': 2023, 'MARS': 'single', 'value': 44725.}, + {'year': 2023, 'MARS': 'mjoint', 'value': 89450.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 44725.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 59850.0}, + {'year': 2023, 'MARS': 'widow', 'value': 89450.0}, + ], + 'II_brk3': [ + {'year': 2023, 'MARS': 'single', 'value': 95375.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 190750.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 95375.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 95350.0}, + {'year': 2023, 'MARS': 'widow', 'value': 190750.0}, + ], + 'II_brk4': [ + {'year': 2023, 'MARS': 'single', 'value': 182100.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 364200.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 182100.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 182100.0}, + {'year': 2023, 'MARS': 'widow', 'value': 364200.0}, + ], + 'II_brk5': [ + {'year': 2023, 'MARS': 'single', 'value': 231250.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 462500.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 231250.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 231250.0}, + {'year': 2023, 'MARS': 'widow', 'value': 462500.0}, + ], + 'II_brk6': [ + {'year': 2023, 'MARS': 'single', 'value': 578125.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 693750.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 578125.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 578100.0}, + {'year': 2023, 'MARS': 'widow', 'value': 693750.0}, + ], + 'II_brk7': [ + {'year': 2023, 'MARS': 'single', 'value': 9e99}, + {'year': 2023, 'MARS': 'mjoint', 'value': 9e99}, + {'year': 2023, 'MARS': 'mseparate', 'value': 9e99}, + {'year': 2023, 'MARS': 'headhh', 'value': 9e99}, + {'year': 2023, 'MARS': 'widow', 'value': 9e99}, + ], + 'CG_brk1': [ + {'year': 2023, 'MARS': 'single', 'value': 44625.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 89250.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 44625.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 59750.0}, + {'year': 2023, 'MARS': 'widow', 'value': 89250.0}, + ], + 'CG_brk2': [ + {'year': 2023, 'MARS': 'single', 'value': 492300.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 553850.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 276900.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 523050.0}, + {'year': 2023, 'MARS': 'widow', 'value': 553850.0}, + ], + 'CG_brk3': [ + {'year': 2023, 'MARS': 'single', 'value': 9e99}, + {'year': 2023, 'MARS': 'mjoint', 'value': 9e99}, + {'year': 2023, 'MARS': 'mseparate', 'value': 9e99}, + {'year': 2023, 'MARS': 'headhh', 'value': 9e99}, + {'year': 2023, 'MARS': 'widow', 'value': 9e99}, + ], + 'EITC_c': [ + {'year': 2023, 'EIC': '0kids', 'value': 600.0}, + {'year': 2023, 'EIC': '1kid', 'value': 3995.0}, + {'year': 2023, 'EIC': '2kids', 'value': 6604.0}, + {'year': 2023, 'EIC': '3+kids', 'value': 7430.0}, + ], + 'EITC_ps': [ + {'year': 2023, 'EIC': '0kids', 'value': 9800.0}, + {'year': 2023, 'EIC': '1kid', 'value': 21560.0}, + {'year': 2023, 'EIC': '2kids', 'value': 21560.0}, + {'year': 2023, 'EIC': '3+kids', 'value': 21560.0}, + ], + 'EITC_ps_MarriedJ': [ + {'year': 2023, 'EIC': '0kids', 'value': 6570.0}, + {'year': 2023, 'EIC': '1kid', 'value': 6560.0}, + {'year': 2023, 'EIC': '2kids', 'value': 6560.0}, + {'year': 2023, 'EIC': '3+kids', 'value': 6560.0}, + ], + 'EITC_InvestIncome_c': [ + {'year': 2023, 'value': 11000.0}, + ], + 'AMT_brk1': [ + {'year': 2023, 'value': 220700.0}, + ], + 'AMT_em': [ + {'year': 2023, 'MARS': 'single', 'value': 81300.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 126500.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 63250.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 81300.0}, + {'year': 2023, 'MARS': 'widow', 'value': 126500.0}, + ], + 'AMT_em_ps': [ + {'year': 2023, 'MARS': 'single', 'value': 578150.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 1156300.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 578150.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 578150.0}, + {'year': 2023, 'MARS': 'widow', 'value': 1156300.0}, + ], + 'AMT_em_pe': [ + {"year": 2023, "value": 831150.0}, + ], + 'AMT_child_em': [ + {'year': 2023, 'value': 8800.0}, + ], + 'STD': [ + {'year': 2023, 'MARS': 'single', 'value': 13850.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 27700.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 13850.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 20800.0}, + {'year': 2023, 'MARS': 'widow', 'value': 27700.0}, + ], + 'STD_Dep': [ + {'year': 2023, 'value': 1250.0}, + ], + 'STD_Aged': [ + {'year': 2023, 'MARS': 'single', 'value': 1800.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 1500.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 1500.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 1800.0}, + {'year': 2023, 'MARS': 'widow', 'value': 1800.0}, + ], + 'PT_qbid_taxinc_thd': [ + {'year': 2023, 'MARS': 'single', 'value': 182100.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 364200.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 182100.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 182100.0}, + {'year': 2023, 'MARS': 'widow', 'value': 182100.0}, + ], + 'ALD_BusinessLosses_c': [ + {'year': 2023, 'MARS': 'single', 'value': 289000.0}, + {'year': 2023, 'MARS': 'mjoint', 'value': 578000.0}, + {'year': 2023, 'MARS': 'mseparate', 'value': 289000.0}, + {'year': 2023, 'MARS': 'headhh', 'value': 289000.0}, + {'year': 2023, 'MARS': 'widow', 'value': 578000.0}, + ], + # ITEMS NOT PART OF CURRENT-LAW POLICY IN 2022-2025 PERIOD: + 'ALD_Dependents_Child_c': LIST_SCALAR_ZERO, + 'ALD_Dependents_Elder_c': LIST_SCALAR_ZERO, + 'II_em': LIST_SCALAR_ZERO, + 'II_em_ps': LIST_MARS_INF, + 'II_credit': LIST_MARS_ZERO, + 'II_credit_ps': LIST_MARS_ZERO, + 'II_credit_nr': LIST_MARS_ZERO, + 'II_credit_nr_ps': LIST_MARS_ZERO, + 'ID_Medical_c': LIST_MARS_INF, + 'ID_StateLocalTax_c': LIST_MARS_INF, + 'ID_RealEstate_c': LIST_MARS_INF, + 'ID_InterestPaid_c': LIST_MARS_INF, + 'ID_Charity_c': LIST_MARS_INF, + 'ID_Casualty_c': LIST_MARS_INF, + 'ID_Miscellaneous_c': LIST_MARS_INF, + 'ID_ps': LIST_MARS_INF, + 'ID_BenefitSurtax_em': LIST_MARS_ZERO, + 'ID_c': LIST_MARS_INF, + 'CG_ec': LIST_SCALAR_ZERO, + 'PT_qbid_ps': LIST_MARS_INF, + 'RPTC_c': LIST_SCALAR_ZERO, + 'CTC_new_ps': LIST_MARS_ZERO, + 'FST_AGI_thd_lo': LIST_MARS_INF, + 'FST_AGI_thd_hi': LIST_MARS_INF, + 'AGI_surtax_thd': LIST_MARS_INF, + 'UBI_u18': LIST_SCALAR_ZERO, + 'UBI_1820': LIST_SCALAR_ZERO, + 'UBI_21': LIST_SCALAR_ZERO, +} +for num in range(1, 7 + 1): + NEW_KNOWN_ITEMS[f'PT_brk{num}'] = NEW_KNOWN_ITEMS[f'II_brk{num}'] +for num in range(1, 3 + 1): + NEW_KNOWN_ITEMS[f'AMT_CG_brk{num}'] = NEW_KNOWN_ITEMS[f'CG_brk{num}'] + + +CHECK_FOR_MISSING = False + + +def check_for_missing(pdict): + """ + Prints to sdtout indexed parameters with missing values in or before 2022. + """ + first_year = 2013 + last_known_year = 2022 + for pname, pinfo in pdict.items(): + if pname == 'schema': + continue + if not pinfo['indexed']: + continue + years_used = [] + plist = pinfo['value'] + for item in plist: + year = item['year'] + if year <= last_known_year: + if year not in years_used: + years_used.append(year) + for year in range(first_year, last_known_year + 1): + if year not in years_used: + print(f'MISSING INDEXED VALUE FOR {pname} IN {year}') + + +def main(): + """ + High-level script logic. + """ + # read existing policy_current_law.json into a Python dictionary + fname = os.path.join('taxcalc', 'policy_current_law.json') + with open(fname, 'r', encoding='utf-8') as jfile: + pdict = json.load(jfile) + + # optionally check for missing indexed parameters in years <= 2022 + if CHECK_FOR_MISSING: + check_for_missing(pdict) + return 1 + + # add parameter values to dictionary + for pname, pinfo in pdict.items(): + if pname == 'schema': + continue + if not pinfo['indexed']: + continue + if pname not in NEW_KNOWN_ITEMS: + print(f'NO NEW_KNOWN_ITEMS FOR {pname}') + continue + plist = pdict[pname]['value'] + # ... see if adding values before existing plist items for 2026 + bindex = None + for itm in plist: + if itm['year'] == 2026: + bindex = plist.index(itm) + break + # ... add new items to plist for this pname + for item in NEW_KNOWN_ITEMS[pname]: + if item in plist: + continue + if bindex: + plist.insert(bindex, item) + bindex += 1 + else: + plist.append(item) + + # write updated dictionary to pcl.json file + with open('pcl.json', 'w', encoding='utf-8') as jfile: + jfile.write(json.dumps(pdict, indent=4) + '\n') + + # return no-error exit code + return 0 +# end main function code + + +if __name__ == '__main__': + sys.exit(main())