Skip to content

Commit

Permalink
Merge pull request #2497 from Peter-Metz/qbid
Browse files Browse the repository at this point in the history
[WIP] Add switch for QBI deduction wage/capital limitations
  • Loading branch information
MattHJensen authored Nov 30, 2020
2 parents d3c7037 + 5c869cd commit da900b1
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 3 deletions.
13 changes: 10 additions & 3 deletions taxcalc/calcfunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -791,8 +791,8 @@ def TaxInc(c00100, standard, c04470, c04600, MARS, e00900, e26270,
e02100, e27200, e00650, c01000,
PT_SSTB_income, PT_binc_w2_wages, PT_ubia_property,
PT_qbid_rt, PT_qbid_taxinc_thd, PT_qbid_taxinc_gap,
PT_qbid_w2_wages_rt,
PT_qbid_alt_w2_wages_rt, PT_qbid_alt_property_rt,
PT_qbid_w2_wages_rt, PT_qbid_alt_w2_wages_rt,
PT_qbid_alt_property_rt, PT_qbid_limit_switch,
c04800, qbided):
"""
Calculates taxable income, c04800, and
Expand All @@ -813,7 +813,9 @@ def TaxInc(c00100, standard, c04470, c04600, MARS, e00900, e26270,
upper_thd = lower_thd + pre_qbid_taxinc_gap
if PT_SSTB_income == 1 and pre_qbid_taxinc >= upper_thd:
qbided = 0.
else:
# if PT_qbid_limit_switch is True, apply wage/capital
# limitations.
elif PT_qbid_limit_switch:
wage_cap = PT_binc_w2_wages * PT_qbid_w2_wages_rt
alt_cap = (PT_binc_w2_wages * PT_qbid_alt_w2_wages_rt +
PT_ubia_property * PT_qbid_alt_property_rt)
Expand All @@ -834,6 +836,11 @@ def TaxInc(c00100, standard, c04470, c04600, MARS, e00900, e26270,
prt = (pre_qbid_taxinc - lower_thd) / pre_qbid_taxinc_gap
adj = prt * (qbid_adjusted - cap_adjusted)
qbided = qbid_adjusted - adj
# if PT_qbid_limit_switch is False, assume all taxpayers
# have sufficient wage expenses and capital income to avoid
# QBID limitations.
else:
qbided = qbid_before_limits
# apply taxinc cap (assuning cap rate is equal to PT_qbid_rt)
net_cg = e00650 + c01000 # per line 34 in 2018 Pub 535 Worksheet 12-A
taxinc_cap = PT_qbid_rt * max(0., pre_qbid_taxinc - net_cg)
Expand Down
26 changes: 26 additions & 0 deletions taxcalc/policy_current_law.json
Original file line number Diff line number Diff line change
Expand Up @@ -12358,6 +12358,32 @@
"cps": false
}
},
"PT_qbid_limit_switch": {
"title": "QBID wage and capital limitations switch.",
"description": "A value of True imposes wage/capital limitations. Note that neither the PUF nor CPS have data on wage expenses or capital income, and therefore all taxpayers are fully subject to the QBID limitations. A value of False assumes sufficient wage and capital income to avoid QBID limitations.",
"notes": "",
"section_1": "Personal Income",
"section_2": "Pass-Through",
"indexable": false,
"indexed": false,
"type": "bool",
"value": [
{
"year": 2013,
"value": true
}
],
"validators": {
"range": {
"min": false,
"max": true
}
},
"compatible_data": {
"puf": false,
"cps": false
}
},
"AMT_em": {
"title": "AMT exemption amount",
"description": "The amount of AMT taxable income exempted from AMT.",
Expand Down
36 changes: 36 additions & 0 deletions taxcalc/tests/test_calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,42 @@ def test_qbid_calculation():
assert np.allclose(tc_df.qbided, tpc_df.qbid)


def test_qbid_limit_switch():
"""
Test Calculator's switch to implement wage/capital limitations
on QBI deduction.
"""
cy = 2019
ref = {"PT_qbid_limit_switch": {2019: False}}

# filing unit has $500,000 in wages and $100,000 in QBI. Since
# the household is above the taxable income limitation threshold,
# with full wage/capital limitations, it does not receive a QBI
# deduction. With sufficent wage/capital to avoid the limitation,
# the filing unit receives a deduction of:
# $100,000 * 20% = $20,000.
VARS = 'RECID,MARS,e00200s,e00200p,e00200,e26270,e02000\n'
FUNIT = '1,2,250000,250000,500000,100000,100000'

funit_df = pd.read_csv(StringIO(VARS + FUNIT))
recs = Records(data=funit_df, start_year=cy,
gfactors=None, weights=None)

calc_base = Calculator(policy=Policy(), records=recs)
calc_base.calc_all()

qbid_base = calc_base.array('qbided')
assert np.equal(qbid_base, 0)

pol_ref = Policy()
pol_ref.implement_reform(ref)
calc_ref = Calculator(policy=pol_ref, records=recs)
calc_ref.calc_all()

qbid_ref = calc_ref.array('qbided')
assert np.equal(qbid_ref, 20000)


def test_calc_all_benefits_amounts(cps_subsample):
'''
Testing how benefits are handled in the calc_all method
Expand Down

0 comments on commit da900b1

Please sign in to comment.