diff --git a/UPGRADING.md b/UPGRADING.md new file mode 100644 index 000000000..1ea15b84a --- /dev/null +++ b/UPGRADING.md @@ -0,0 +1,94 @@ +Upgrading to Tax-Calculator 2.0 +=============================== + +Tax-Calculator version 2.0 (and higher) is incompatible with earlier +versions. The tax logic is unchanged, but 2.0 introduces a simplified +and standardized way of specifying tax reforms (or economic assumption +changes). This note explains what you have to do in order to use +Tax-Calculator version 2.0 and higher. + +What you need to do is change the way you specify tax policy reforms. +Obviously, you need to do this only for reforms you want to analyze +using Tax-Calculator 2.0 and higher. + +The details of what to do depend on whether you are in the habit of +specifying reforms in JSON files (as demonstrated in the [user +guide](https://PSLmodels.github.io/Tax-Calculator/index.html) and +[cookbook](https://PSLmodels.github.io/Tax-Calculator/cookbook.html)) +or whether you take a low-level approach and specify reforms as Python +dictionaries directly in your Python scripts (as done in hundreds of +Tax-Calculator tests). + +In both cases you need to do the following: + +1. Remove the leading underscore character from each parameter name. + +2. Remove the brackets around the value of scalar parameters (i.e., + those that do not vary by filing-unit type, number of EITC eligible + children, or type of itemized deduction, and therefore, are just a + single value in any year). + +3. Remove **one** of the double set of brackets around the values of + vector parameters(i.e., those that are not scalar parameters). + This will leave vector parameter values enclosed in just one pair + of brackets. + +4. Only if you are changing whether a parameter is (wage or price) + indexed for inflation, you need to change the trailing `_cpi` + characters to be `-indexed` (making sure to use a dash and not an + underscore). + +5. Only if you are changing CPI offset policy, you need to change the + old parameter name `_cpi_offset` to `CPI_offset`. + +That is all that needs to be done to convert JSON reform (or +assumption) files so that they work with Tax-Calculator 2.0 and +higher. (If you have many JSON reform files that you want to convert, +the first three steps may be able to be automated using the +`Tax-Calculator/new_json.py` script, but be sure to read the short +script before using it. If your JSON reform files are not formatted +in the way extected by the `new_json.py` script, then make the changes +in the above steps by hand editing each JSON file.) + +If you have specified reforms (or changes in economic assumption +parameters) directly in your Python scripts using dictionaries, then +there is another set of changes you need to make to each of those +dictionaries. In older versions of Tax-Calcualtor, each reform +dictionary was structured using a `year : param : value` format. +Here is an example of the old format after making the changes +listed above: + +``` +reform = { + 2020: { + 'SS_Earnings_c': 200000, + 2021: { + 'SS_Earnings_c': 300000, + 'SS_Earnings_c-indexed': False + }, + 2022: { + 'STD': [14000, 28000, 14000, 21000, 28000] + } +} +``` + +Notice that the primary keys in the above dictionary are years and the +secondary keys are parameter names. Beginning with Tax-Calculator +2.0, that order is reversed making the new `param : year : value` +format consistent with the format of the JSON reform files. + +So, the above dictionary needs to be converted (by hand editing) to +the following: + +``` +reform = { + 'SS_Earnings_c': {2020: 200000, + 2021: 300000}, + 'SS_Earnings_c-indexed': {2021: False}, + 'STD': {2022: [14000, 28000, 14000, 21000, 28000]} +} +``` + +If you have any problems or questions converting your reforms for +use with Tax-Calculator 2.0, please raise an issue +[here](https://github.com/PSLmodels/Tax-Calculator/issues). diff --git a/docs/cookbook/recipe00.res b/docs/cookbook/recipe00.res index de4164608..840296908 100644 --- a/docs/cookbook/recipe00.res +++ b/docs/cookbook/recipe00.res @@ -1,46 +1,44 @@ -You loaded data for 2014. -Tax-Calculator startup automatically extrapolated your data to 2014. -You loaded data for 2014. -Tax-Calculator startup automatically extrapolated your data to 2014. REFORM DOCUMENTATION Baseline Growth-Difference Assumption Values by Year: -none: using default baseline growth assumptions +none: using default growth assumptions +Response Growth-Difference Assumption Values by Year: +none: using default growth assumptions Policy Reform Parameter Values by Year: 2020: - _II_em : 1000 + II_em : 1000.0 name: Personal and dependent exemption amount desc: Subtracted from AGI in the calculation of taxable income, per taxpayer and dependent. baseline_value: 0.0 - _II_rt5 : 0.36 + II_rt5 : 0.36 name: Personal income (regular/non-AMT/non-pass-through) tax rate 5 desc: The third highest tax rate, applied to the portion of taxable income below tax bracket 5 and above tax bracket 4. baseline_value: 0.32 - _II_rt6 : 0.39 + II_rt6 : 0.39 name: Personal income (regular/non-AMT/non-pass-through) tax rate 6 desc: The second higher tax rate, applied to the portion of taxable income below tax bracket 6 and above tax bracket 5. baseline_value: 0.35 - _II_rt7 : 0.41 + II_rt7 : 0.41 name: Personal income (regular/non-AMT/non-pass-through) tax rate 7 desc: The tax rate applied to the portion of taxable income below tax bracket 7 and above tax bracket 6. baseline_value: 0.37 - _PT_rt5 : 0.36 + PT_rt5 : 0.36 name: Pass-through income tax rate 5 desc: The third highest tax rate, applied to the portion of income from sole proprietorships, partnerships and S-corporations below tax bracket 5 and above tax bracket 4. baseline_value: 0.32 - _PT_rt6 : 0.39 + PT_rt6 : 0.39 name: Pass-through income tax rate 6 desc: The second higher tax rate, applied to the portion of income from sole proprietorships, partnerships and S-corporations below tax bracket 6 and above tax bracket 5. baseline_value: 0.35 - _PT_rt7 : 0.41 + PT_rt7 : 0.41 name: Pass-through income tax rate 7 desc: The highest tax rate, applied to the portion of income from sole proprietorships, partnerships and S-corporations below tax bracket 7 diff --git a/docs/cookbook/recipe03.res b/docs/cookbook/recipe03.res index 6cfbcb937..c09fa2a97 100644 --- a/docs/cookbook/recipe03.res +++ b/docs/cookbook/recipe03.res @@ -1,5 +1,3 @@ -You loaded data for 2014. -Tax-Calculator startup automatically extrapolated your data to 2014. Filing Units Receiving EITC and Average Positive EITC by AGI Category AGI Category Num(#M) Avg($K) [-9e+99, 1) 0.047 1.244 diff --git a/docs/cookbook/reformA.json b/docs/cookbook/reformA.json index 15ee142aa..93dddc7c8 100644 --- a/docs/cookbook/reformA.json +++ b/docs/cookbook/reformA.json @@ -2,16 +2,16 @@ // from (0.32, 0.35, 0.37) to (0.36, 0.39, 0.41) beginning in 2020. { "policy": { - // raise personal exemption amount and index in subsequent years - "_II_em": {"2020": [1000]}, - // raise tax rates in the top three brackets - // ... raise non-AMT rates on non-pass-through income - "_II_rt5": {"2020": [0.36]}, - "_II_rt6": {"2020": [0.39]}, - "_II_rt7": {"2020": [0.41]}, - // ... raise non-AMT rates on pass-through income - "_PT_rt5": {"2020": [0.36]}, - "_PT_rt6": {"2020": [0.39]}, - "_PT_rt7": {"2020": [0.41]} + // raise personal exemption amount and index in subsequent years + "II_em": {"2020": 1000}, + // raise tax rates in the top three brackets + // ... raise non-AMT rates on non-pass-through income + "II_rt5": {"2020": 0.36}, + "II_rt6": {"2020": 0.39}, + "II_rt7": {"2020": 0.41}, + // ... raise non-AMT rates on pass-through income + "PT_rt5": {"2020": 0.36}, + "PT_rt6": {"2020": 0.39}, + "PT_rt7": {"2020": 0.41} } } diff --git a/docs/cookbook/reformB.json b/docs/cookbook/reformB.json index 028df3da5..199e17d8e 100644 --- a/docs/cookbook/reformB.json +++ b/docs/cookbook/reformB.json @@ -1,7 +1,7 @@ // Raise personal exemption and lower standard deduction beginning in 2020. { "policy": { - "_II_em": {"2020": [2000]}, - "_STD": {"2020": [[6000, 12000, 6000, 9000, 12000]]} + "II_em": {"2020": 2000}, + "STD": {"2020": [6000, 12000, 6000, 9000, 12000]} } } diff --git a/docs/index.htmx b/docs/index.htmx index 57c270005..86b883355 100644 --- a/docs/index.htmx +++ b/docs/index.htmx @@ -640,7 +640,7 @@ the ref3.json file, the content of which is: // after which it continues to be indexed to price inflation. { "policy": { - "_II_em": {"2022": [8000]} + "II_em": {"2022": 8000} } }
diff --git a/docs/make_index.py b/docs/make_index.py index a3ea386ba..f2fa557b6 100644 --- a/docs/make_index.py +++ b/docs/make_index.py @@ -90,25 +90,25 @@ def policy_param_text(pname, param): else: txt += 'False' txt += '{} — {}'.format(sec1, param['section_2']) + txt = '
{} — {}'.format(sec1, + param.get('section_2', '')) else: txt = '
{} — {}'.format('Assumption Parameter',
ptype.capitalize())
@@ -224,13 +225,13 @@ def assumption_param_text(pname, ptype, param):
else:
txt += '
Long Name: {}'.format(param['long_name'])
txt += '
Description: {}'.format(param['description'])
- if len(param['notes']) > 0:
+ if len(param.get('notes', '')) > 0:
txt += '
Notes: {}'.format(param['notes'])
txt += '
Default Value:'
- if len(param['col_label']) > 0:
- cols = ', '.join(param['col_label'])
+ if len(param.get('vi_vals', [])) > 0:
+ cols = ', '.join(param['vi_vals'])
txt += '
for: [{}]'.format(cols)
- for cyr, val in zip(param['row_label'], param['value']):
+ for cyr, val in zip(param['value_yrs'], param['value']):
txt += '
{}: {}'.format(cyr, val)
txt += '
Valid Range:'
minval = param['valid_values']['min']
diff --git a/docs/ref3.json b/docs/ref3.json
index 9023e2f6a..a6404cdc0 100644
--- a/docs/ref3.json
+++ b/docs/ref3.json
@@ -2,6 +2,6 @@
// after which it continues to be indexed to price inflation.
{
"policy": {
- "_II_em": {"2022": [8000]}
+ "II_em": {"2022": 8000}
}
}
diff --git a/new_json.py b/new_json.py
index 7c3f7aa4e..8c88942fe 100644
--- a/new_json.py
+++ b/new_json.py
@@ -1,6 +1,6 @@
"""
Command-line tool that converts Tax-Calculator JSON reform/assumption file
-from the old (1.x) format to the new (2.0) format.
+from the old (1.x) format to the new (2.0+) format.
------------------------------------------------------------------------
WARNING: This program make certain assumptions about how the JSON file
is formatted, so it will not work correctly on a JSON file
diff --git a/taxcalc/tests/test_policy.py b/taxcalc/tests/test_policy.py
index 8365996dc..8c0a8e0ca 100644
--- a/taxcalc/tests/test_policy.py
+++ b/taxcalc/tests/test_policy.py
@@ -66,7 +66,7 @@ def test_policy_json_content_consistency():
# check entries in vi_vals list
vivals = data['vi_vals']
if vivals:
- assert set(vivals) == set(expected_vi_vals[data['vi_name']])
+ assert vivals == expected_vi_vals[data['vi_name']]
# pylint: disable=protected-access,no-member