-
Notifications
You must be signed in to change notification settings - Fork 204
Description
Summary
irs_gross_income.py clips all income sources to $0 with max_(0, ...), which means negative partnership_s_corp_income (S-Corp and partnership losses) never reduces gross income or AGI. There is no separate mechanism to deduct these losses, so they are silently dropped.
The code
irs_gross_income.py (line 19):
for source in sources:
# Add positive values only - losses are deducted later.
total += not_dependent * max_(0, add(person, period, [source]))The comment says "losses are deducted later," but loss_ald.py only deducts:
self_employment_incomelosseslimited_capital_loss(capital losses, capped at $3,000)
loss_ald.py:
def formula(tax_unit, period, parameters):
filing_status = tax_unit("filing_status", period)
max_loss = parameters(period).gov.irs.ald.loss.max[filing_status]
person = tax_unit.members
indiv_se_loss = max_(0, -person("self_employment_income", period))
self_employment_loss = tax_unit.sum(indiv_se_loss)
limited_capital_loss = tax_unit("limited_capital_loss", period)
return min_(max_loss, self_employment_loss + limited_capital_loss)There is no deduction path for partnership_s_corp_income losses. They are excluded from gross income by the max_(0, ...) and never recovered.
What the IRS rules say
S-Corp losses pass through to shareholders under 26 USC §1366(a) and flow through Schedule E Part II → Schedule 1 line 5 → Form 1040, directly reducing AGI. Allowable losses are subject to four sequential limitations:
- Basis limitation — §1366(d): losses limited to stock + debt basis
- At-risk limitation — §465: losses limited to amount at risk
- Passive activity limitation — §469: passive losses can only offset passive income (but materially participating shareholders' losses are nonpassive and fully deductible)
- Excess business loss limitation — §461(l): for 2021, $262K single / $524K MFJ cap (losses beyond this become NOL carryforwards)
After these limitations, the remaining loss reduces AGI. Since PolicyEngine doesn't have inputs for basis, at-risk amounts, or passive/active classification, a reasonable assumption (used by TAXSIM) is that the reported value is already net of all limitations.
TAXSIM's approach (for reference)
TAXSIM includes negative scorp directly in Schedule E and total income with no clipping:
! taxsim.f line 31040-31041
schede = data(74)+data(75)+data(76)+data(77)+data(78)+data(79) + data(213)
! line 31054-31056: ti includes schede
ti = capgn + data(11) + divall + ... + schede + (d17-data(213)) + ...
! line 31122
agi = ti - adjustWith the comment at lines 31136-31137:
c Passive loss limitations apply only to rental losses
c Non-rental losses are considered allowable if reported by the SOI
Empirical impact
In a comparison of 1,000 CPS households (2021), all 73 records with negative S-Corp income show PE AGI higher than TAXSIM AGI by approximately |scorp|:
| Metric | Value |
|---|---|
| Records affected | 73 of 1,000 (all negative scorp) |
| AGI diff / |scorp| ratio | 1.00 for most records |
| Mean absolute AGI difference | $2.8M |
| Mean absolute fiitax difference | $147K |
Examples:
| taxsimid | scorp | PE AGI - TAXSIM AGI |
|---|---|---|
| 75300 | -$51,506,712 | +$51,506,712 |
| 112263 | -$25,864,222 | +$25,864,222 |
| 79995 | -$6,989,538 | +$6,989,538 |
| 78933 | -$122 | +$122 |
Suggested fix
Add partnership_s_corp_income losses to loss_ald.py, subject to the existing §461(l) excess business loss cap:
indiv_ps_loss = max_(0, -person("partnership_s_corp_income", period))
partnership_s_corp_loss = tax_unit.sum(indiv_ps_loss)
return min_(max_loss, self_employment_loss + limited_capital_loss + partnership_s_corp_loss)This assumes the input value is already net of basis, at-risk, and passive activity limitations (matching TAXSIM's assumption and consistent with how self_employment_income losses are already handled).
Alternatively, the max_(0, ...) in irs_gross_income.py could be removed for this source, but the loss_ald approach maintains consistency with how SE losses are handled and preserves the §461(l) cap.