|
| 1 | +""" |
| 2 | +Tests for the income-scaled match tolerance in the comparator. |
| 3 | +
|
| 4 | +The flat $15 absolute tolerance flags negligible differences on |
| 5 | +extreme-magnitude records (e.g. large S-corp income/losses), where PE and |
| 6 | +TAXSIM agree to a tiny fraction of income. `relative_tolerance` lets a record |
| 7 | +match within max($15, relative_tolerance * |AGI|). Default 0.0 preserves the |
| 8 | +absolute-only behavior. |
| 9 | +""" |
| 10 | + |
| 11 | +import pandas as pd |
| 12 | + |
| 13 | +from policyengine_taxsim.comparison.comparator import ( |
| 14 | + TaxComparator, |
| 15 | + ComparisonConfig, |
| 16 | +) |
| 17 | + |
| 18 | + |
| 19 | +def _frames(taxsimid, agi, fiitax_t, fiitax_p): |
| 20 | + tx = pd.DataFrame( |
| 21 | + {"taxsimid": taxsimid, "v10": agi, "fiitax": fiitax_t, "siitax": 0.0} |
| 22 | + ) |
| 23 | + pe = pd.DataFrame( |
| 24 | + {"taxsimid": taxsimid, "v10": agi, "fiitax": fiitax_p, "siitax": 0.0} |
| 25 | + ) |
| 26 | + return tx, pe |
| 27 | + |
| 28 | + |
| 29 | +def test_default_absolute_tolerance_flags_large_dollar_diff(): |
| 30 | + """With default (absolute-only) tolerance, a $500 diff is a mismatch.""" |
| 31 | + tx, pe = _frames([1], [10_000_000], [1_000_000], [1_000_500]) |
| 32 | + r = TaxComparator(tx, pe, ComparisonConfig()).compare() |
| 33 | + assert r.federal_match_percentage == 0.0 |
| 34 | + |
| 35 | + |
| 36 | +def test_income_scaled_tolerance_absorbs_negligible_diff(): |
| 37 | + """A $500 diff on $10M AGI is 0.005% — within a 0.1% income-scaled |
| 38 | + tolerance, so it matches; a genuinely large diff still fails.""" |
| 39 | + # negligible: $500 on $10M |
| 40 | + tx, pe = _frames([1], [10_000_000], [1_000_000], [1_000_500]) |
| 41 | + r = TaxComparator(tx, pe, ComparisonConfig(relative_tolerance=0.001)).compare() |
| 42 | + assert r.federal_match_percentage == 100.0 |
| 43 | + |
| 44 | + # material: $50k diff on $10M (0.5%) exceeds the 0.1% floor -> mismatch |
| 45 | + tx2, pe2 = _frames([1], [10_000_000], [1_000_000], [1_050_000]) |
| 46 | + r2 = TaxComparator(tx2, pe2, ComparisonConfig(relative_tolerance=0.001)).compare() |
| 47 | + assert r2.federal_match_percentage == 0.0 |
| 48 | + |
| 49 | + |
| 50 | +def test_absolute_floor_preserved_for_small_income(): |
| 51 | + """The $15 absolute floor still applies for low-AGI records (the scaled |
| 52 | + tolerance never lowers it below $15).""" |
| 53 | + # $20 diff on $1,000 AGI: 0.1% of AGI = $1, so floor stays $15 -> mismatch |
| 54 | + tx, pe = _frames([1], [1_000], [100], [120]) |
| 55 | + r = TaxComparator(tx, pe, ComparisonConfig(relative_tolerance=0.001)).compare() |
| 56 | + assert r.federal_match_percentage == 0.0 |
0 commit comments