Should the emulator assume sufficient W-2 wages for the QBI deduction, as TAXSIM does?
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 35/100
Research direction
Read the stdin drop-in command and the --assume-w2-wages handling in the policyengine and compare subcommands; the issue names no file or test. First determine how stdin options are parsed and how QBI results are compared with TAXSIM. Done means an explicit decision on whether the default should change, with the stdin flag behavior and tests matching that decision.
Written by the indexing model from the issue text.
Description
The stdin drop-in command (policyengine-taxsim < input.csv) gives a QBI deduction of 0 to a single filer with $400,000 of pbusinc in 2024. The bundled taxsimtest binary gives 77,080. --assume-w2-wages closes most of the gap, but only the policyengine and compare subcommands accept it.
Reproduce
policyengine-taxsim 3.0.1 (3e2a7589), policyengine-us 2.30.1, bundled taxsimtest-osx.exe:
taxsimid,year,state,mstat,page,psemp,pbusinc,idtl
1,2024,0,1,40,0,400000,2
2,2024,0,1,40,400000,0,2
| Row | Engine | fica | v10 (AGI) | qbid | fiitax |
|---|---|---|---|---|---|
1 pbusinc |
TAXSIM binary | 0 | 400,000.00 | 77,080.00 | 85,886.75 |
1 pbusinc |
emulator, default | 33,143.60 | 384,190.47 | 0 | 99,731.42 |
1 pbusinc |
emulator, --assume-w2-wages |
33,143.60 | 384,190.47 | 73,918.10 | 73,860.10 |
2 psemp |
TAXSIM binary | 33,143.60 | 384,190.50 | 73,918.10 | 73,860.09 |
2 psemp |
emulator, default | 33,143.60 | 384,190.47 | 0 | 99,731.42 |
2 psemp |
emulator, --assume-w2-wages |
33,143.60 | 384,190.47 | 73,918.10 | 73,860.10 |
With the flag, row 2 matches TAXSIM to the cent. The remaining 3,162 gap on row 1 comes from the binary's missing SECA on pbusinc (#1254), not from the wage limit.
Why the default gives 0
PolicyEngine-US applies the statutory W-2 wage limit. TAXSIM input has no W-2 wage column, so the emulator supplies none. 26 U.S.C. § 199A(b)(2), "Determination of deductible amount for each trade or business" (LII, fetched 2026-10-07):
The amount determined under this paragraph with respect to any qualified trade or business is the lesser of— (A) 20 percent of the taxpayer's qualified business income with respect to the qualified trade or business, or (B) the greater of— (i) 50 percent of the W–2 wages with respect to the qualified trade or business, or (ii) the sum of 25 percent of the W–2 wages with respect to the qualified trade or business, plus 2.5 percent of the unadjusted basis immediately after acquisition of all qualified property.
§ 199A(b)(3)(A) drops (B) only at or below the threshold amount:
In the case of any taxpayer whose taxable income for the taxable year does not exceed the threshold amount, paragraph (2) shall be applied without regard to subparagraph (B).
Rev. Proc. 2023-34, § 3.27 "Qualified Business Income" (page 15):
For taxable years beginning in 2024, the threshold amounts under § 199A(e)(2) and phase-in range amounts under § 199A(b)(3)(B) and § 199A(d)(3)(A) are: [...] All Other Returns $191,950 $241,950
Taxable income before the deduction is 369,590, above 241,950. With no W-2 wages and no qualified property, (B) is 0, so the deduction is 0.
What TAXSIM does
The taxsimtest input documentation ("Date last modified: 28 February 2026", fetched 2026-10-07), item 26:
- pbusinc and sbusinc Primary and secondary Taxpayer's active income eligible for the QBI deduction without phaseout and assuming sufficient wages paid or capital to be eligible for the full deduction. Subject to NIIT, SECA and Medicare additional Earnings Tax.
The full QBI deduction block of the published source (law87.for lines 796–811, feenberg/taxsim @ 359c71f) has no wage or capital term. The deduction is 20% of the QBI pools less half of SE tax, capped at ptlim:
c 2018+ pass-through income qualifies for 20% deduction
c income after fica and phaseout for sstb + scorp only
if(lawyr.ge.2018) then
ptqbi =max(0.d0,d(211))+max(0.d0,d(214))
& +max(0.d0,d(224))+max(0d0,d(17))
ptsst =max(0.d0,d(212))+max(0.d0,d(215))
ptfica =sen
ptinc =d(213)+ptqbi+ptsst-ptfica/2
ptstrt =phin(lawyr,max(1,int(d(7))))
if(sepret.eq.2.and.lawyr.eq.2019) ptstrt=160725.d0
ptexcs =max(0d0,taxinc-ptstrt)
perc =min(1.d0,max(0.d0,ptexcs/50000.d0))
ptlim =max(0.d0,.2d0*(taxinc-(capgn+d(12))))
ptded =.2d0*(ptsst*(1.d0-perc)+ptqbi+d(213)-.5*sen)
ptded =max(0.d0,min(ptded,ptlim))
taxinc=max(0d0,taxinc-ptded)
Questions
- #1405 adds
--assume-w2-wagesto the stdin command and keeps it off by default. Is an opt-in flag enough? - Should the emulator assume sufficient W-2 wages by default, because TAXSIM documents this for
pbusincand its code has no wage limit for any QBI? That would change the default output for every QBI record above the threshold (psemp,pbusinc,scorp), so it needs an explicit, announced decision.
Side note: the same page describes psemp as "not eligible as Qualified Business Income (QBI)", but the binary gives row 2 a QBI deduction of 73,918.10. That is a separate question for TAXSIM and does not change this issue.
- Dominant language
- Python
- Stars
- 18
- Forks
- 10
- Avg merge
- 2d 9h
- Merged PRs (30d)
- 15
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from PolicyEngine/policyengine-taxsim
-
2024
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
PolicyEngine/policyengine-taxsim#1372 · 2 comments ·
Maintainers usually reply within 1 day
-
Backlog
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
PolicyEngine/policyengine-taxsim#165 · 1 comment · 1 reaction ·
Maintainers usually reply within 1 day
-
Refresh pip before Modal image package installsPossibly taken @anth-volk claimed this today. Open
Difficulty 4/5 1-2 days Newbie friendliness 22/100
PolicyEngine/policyengine-taxsim#1501 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 28/100
PolicyEngine/policyengine-taxsim#1500 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 22/100
PolicyEngine/policyengine-taxsim#1499 ·
Maintainers usually reply within 1 day
All issues in PolicyEngine/policyengine-taxsim
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
huggingface/smolagents#3106 ·
Maintainers usually reply within 2 days
-
area:scripts area:tests bug priority:later
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Ikalus1988/MisakaNet#4358 ·
Maintainers usually reply within 1 day
-
Discovered ports from service discovery are never propagated to modules in Module.load()Possibly taken @vishalmore90 claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
OWASP/Nettacker#1828 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
aws-samples/sample-per-model-bedrock#708 ·
Maintainers usually reply within 1 day
-
maintenance
Difficulty 2/5 1-3 hours Newbie friendliness 62/100