@retiregolden/engine 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +79 -0
- package/dist/allocation/assetClasses.d.ts +94 -0
- package/dist/allocation/assetClasses.js +215 -0
- package/dist/decisions/annuitization.d.ts +72 -0
- package/dist/decisions/annuitization.js +184 -0
- package/dist/decisions/decisionFixtures.d.ts +48 -0
- package/dist/decisions/decisionFixtures.js +253 -0
- package/dist/decisions/evaluateCandidate.d.ts +61 -0
- package/dist/decisions/evaluateCandidate.js +193 -0
- package/dist/decisions/generators.d.ts +110 -0
- package/dist/decisions/generators.js +667 -0
- package/dist/decisions/index.d.ts +17 -0
- package/dist/decisions/index.js +17 -0
- package/dist/decisions/insightsAdapter.d.ts +27 -0
- package/dist/decisions/insightsAdapter.js +51 -0
- package/dist/decisions/objectives.d.ts +96 -0
- package/dist/decisions/objectives.js +319 -0
- package/dist/decisions/pensionElection.d.ts +112 -0
- package/dist/decisions/pensionElection.js +239 -0
- package/dist/decisions/search.d.ts +51 -0
- package/dist/decisions/search.js +110 -0
- package/dist/decisions/spendingSolver.d.ts +70 -0
- package/dist/decisions/spendingSolver.js +180 -0
- package/dist/decisions/spiaQuotes.d.ts +21 -0
- package/dist/decisions/spiaQuotes.js +43 -0
- package/dist/decisions/stochastic.d.ts +11 -0
- package/dist/decisions/stochastic.js +66 -0
- package/dist/decisions/swrComparator.d.ts +54 -0
- package/dist/decisions/swrComparator.js +89 -0
- package/dist/decisions/tournament.d.ts +53 -0
- package/dist/decisions/tournament.js +104 -0
- package/dist/decisions/types.d.ts +125 -0
- package/dist/decisions/types.js +12 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +12 -0
- package/dist/insights/detectors/annuitizationHeadroom.d.ts +11 -0
- package/dist/insights/detectors/annuitizationHeadroom.js +77 -0
- package/dist/insights/detectors/assetLocation.d.ts +9 -0
- package/dist/insights/detectors/assetLocation.js +86 -0
- package/dist/insights/detectors/hecmBufferCandidate.d.ts +12 -0
- package/dist/insights/detectors/hecmBufferCandidate.js +76 -0
- package/dist/insights/detectors/incomeFloorFunded.d.ts +8 -0
- package/dist/insights/detectors/incomeFloorFunded.js +52 -0
- package/dist/insights/detectors/irmaaTierEdge.d.ts +2 -0
- package/dist/insights/detectors/irmaaTierEdge.js +102 -0
- package/dist/insights/detectors/pensionElectionPending.d.ts +11 -0
- package/dist/insights/detectors/pensionElectionPending.js +62 -0
- package/dist/insights/detectors/qcdEfficiency.d.ts +2 -0
- package/dist/insights/detectors/qcdEfficiency.js +62 -0
- package/dist/insights/detectors/rothBridgeHeadroom.d.ts +2 -0
- package/dist/insights/detectors/rothBridgeHeadroom.js +77 -0
- package/dist/insights/detectors/spendingGuardrails.d.ts +2 -0
- package/dist/insights/detectors/spendingGuardrails.js +77 -0
- package/dist/insights/detectors/spendingHeadroom.d.ts +12 -0
- package/dist/insights/detectors/spendingHeadroom.js +92 -0
- package/dist/insights/detectors/ssBridgeGap.d.ts +9 -0
- package/dist/insights/detectors/ssBridgeGap.js +92 -0
- package/dist/insights/detectors/stateRelocation.d.ts +12 -0
- package/dist/insights/detectors/stateRelocation.js +99 -0
- package/dist/insights/detectors/widowsPenalty.d.ts +12 -0
- package/dist/insights/detectors/widowsPenalty.js +145 -0
- package/dist/insights/registry.d.ts +4 -0
- package/dist/insights/registry.js +62 -0
- package/dist/insights/runInsights.d.ts +6 -0
- package/dist/insights/runInsights.js +15 -0
- package/dist/insights/types.d.ts +70 -0
- package/dist/insights/types.js +1 -0
- package/dist/ladder/bridge.d.ts +72 -0
- package/dist/ladder/bridge.js +59 -0
- package/dist/ladder/fedInvest.d.ts +55 -0
- package/dist/ladder/fedInvest.js +77 -0
- package/dist/ladder/fundedRatio.d.ts +41 -0
- package/dist/ladder/fundedRatio.js +46 -0
- package/dist/ladder/ladderMath.d.ts +88 -0
- package/dist/ladder/ladderMath.js +140 -0
- package/dist/longevity/ssaPeriod2022.d.ts +10 -0
- package/dist/longevity/ssaPeriod2022.js +51 -0
- package/dist/longevity/types.d.ts +39 -0
- package/dist/longevity/types.js +1 -0
- package/dist/model/migrations.d.ts +20 -0
- package/dist/model/migrations.js +67 -0
- package/dist/model/plan.d.ts +3108 -0
- package/dist/model/plan.js +1514 -0
- package/dist/montecarlo/frontiers.d.ts +22 -0
- package/dist/montecarlo/frontiers.js +61 -0
- package/dist/montecarlo/historicalReturns.d.ts +27 -0
- package/dist/montecarlo/historicalReturns.js +124 -0
- package/dist/montecarlo/historicalSuites.d.ts +45 -0
- package/dist/montecarlo/historicalSuites.js +102 -0
- package/dist/montecarlo/ltcShock.d.ts +42 -0
- package/dist/montecarlo/ltcShock.js +62 -0
- package/dist/montecarlo/marketModels.d.ts +248 -0
- package/dist/montecarlo/marketModels.js +672 -0
- package/dist/montecarlo/mortality.d.ts +31 -0
- package/dist/montecarlo/mortality.js +61 -0
- package/dist/montecarlo/riskBasedGuardrails.d.ts +93 -0
- package/dist/montecarlo/riskBasedGuardrails.js +200 -0
- package/dist/montecarlo/rng.d.ts +18 -0
- package/dist/montecarlo/rng.js +44 -0
- package/dist/montecarlo/run.d.ts +210 -0
- package/dist/montecarlo/run.js +353 -0
- package/dist/montecarlo/sharedPaths.d.ts +43 -0
- package/dist/montecarlo/sharedPaths.js +28 -0
- package/dist/montecarlo/survival.d.ts +49 -0
- package/dist/montecarlo/survival.js +126 -0
- package/dist/params/data/realYieldCurve2026.d.ts +17 -0
- package/dist/params/data/realYieldCurve2026.js +26 -0
- package/dist/params/data/year2026.d.ts +14 -0
- package/dist/params/data/year2026.js +199 -0
- package/dist/params/index.d.ts +63 -0
- package/dist/params/index.js +134 -0
- package/dist/params/provenance.d.ts +29 -0
- package/dist/params/provenance.js +123 -0
- package/dist/params/state/data/year2026.d.ts +18 -0
- package/dist/params/state/data/year2026.js +581 -0
- package/dist/params/state/index.d.ts +13 -0
- package/dist/params/state/index.js +26 -0
- package/dist/params/state/types.d.ts +73 -0
- package/dist/params/state/types.js +10 -0
- package/dist/params/types.d.ts +201 -0
- package/dist/params/types.js +7 -0
- package/dist/projection/annuityForms.d.ts +62 -0
- package/dist/projection/annuityForms.js +87 -0
- package/dist/projection/compare.d.ts +96 -0
- package/dist/projection/compare.js +216 -0
- package/dist/projection/flatTax.d.ts +7 -0
- package/dist/projection/flatTax.js +14 -0
- package/dist/projection/optimizePlan.d.ts +328 -0
- package/dist/projection/optimizePlan.js +1039 -0
- package/dist/projection/relocation.d.ts +149 -0
- package/dist/projection/relocation.js +317 -0
- package/dist/projection/simulate.d.ts +61 -0
- package/dist/projection/simulate.js +2754 -0
- package/dist/projection/types.d.ts +381 -0
- package/dist/projection/types.js +9 -0
- package/dist/rmd/jointLifeTable.d.ts +8 -0
- package/dist/rmd/jointLifeTable.js +663 -0
- package/dist/rmd/rmd.d.ts +29 -0
- package/dist/rmd/rmd.js +34 -0
- package/dist/scenarios/scenarios.d.ts +70 -0
- package/dist/scenarios/scenarios.js +130 -0
- package/dist/socialSecurity/benefitFactor.d.ts +13 -0
- package/dist/socialSecurity/benefitFactor.js +40 -0
- package/dist/socialSecurity/claimFactor.d.ts +33 -0
- package/dist/socialSecurity/claimFactor.js +58 -0
- package/dist/socialSecurity/disability.d.ts +36 -0
- package/dist/socialSecurity/disability.js +42 -0
- package/dist/socialSecurity/familyMaximum.d.ts +38 -0
- package/dist/socialSecurity/familyMaximum.js +48 -0
- package/dist/socialSecurity/maritalBenefits.d.ts +57 -0
- package/dist/socialSecurity/maritalBenefits.js +87 -0
- package/dist/socialSecurity/nra.d.ts +30 -0
- package/dist/socialSecurity/nra.js +83 -0
- package/dist/socialSecurity/piaFromEarnings.d.ts +100 -0
- package/dist/socialSecurity/piaFromEarnings.js +202 -0
- package/dist/socialSecurity/ssaWageData.d.ts +68 -0
- package/dist/socialSecurity/ssaWageData.js +306 -0
- package/dist/socialSecurity/survivorBenefit.d.ts +61 -0
- package/dist/socialSecurity/survivorBenefit.js +61 -0
- package/dist/spending/abw.d.ts +57 -0
- package/dist/spending/abw.js +80 -0
- package/dist/spending/flexibleGoals.d.ts +62 -0
- package/dist/spending/flexibleGoals.js +136 -0
- package/dist/spending/guardrails.d.ts +78 -0
- package/dist/spending/guardrails.js +100 -0
- package/dist/spending/layers.d.ts +81 -0
- package/dist/spending/layers.js +67 -0
- package/dist/spending/shapePresets.d.ts +42 -0
- package/dist/spending/shapePresets.js +77 -0
- package/dist/strategies/accountEligibility.d.ts +81 -0
- package/dist/strategies/accountEligibility.js +98 -0
- package/dist/strategies/inheritedIra.d.ts +45 -0
- package/dist/strategies/inheritedIra.js +43 -0
- package/dist/strategies/iraBasis.d.ts +48 -0
- package/dist/strategies/iraBasis.js +46 -0
- package/dist/strategies/optimizer.d.ts +307 -0
- package/dist/strategies/optimizer.js +551 -0
- package/dist/strategies/rothBasis.d.ts +67 -0
- package/dist/strategies/rothBasis.js +83 -0
- package/dist/strategies/rothConversion.d.ts +55 -0
- package/dist/strategies/rothConversion.js +83 -0
- package/dist/strategies/sepp.d.ts +38 -0
- package/dist/strategies/sepp.js +53 -0
- package/dist/tax/aca.d.ts +40 -0
- package/dist/tax/aca.js +82 -0
- package/dist/tax/federalTax.d.ts +110 -0
- package/dist/tax/federalTax.js +249 -0
- package/dist/tax/medicare.d.ts +20 -0
- package/dist/tax/medicare.js +36 -0
- package/dist/tax/propertySale.d.ts +46 -0
- package/dist/tax/propertySale.js +35 -0
- package/dist/tax/stateTax.d.ts +66 -0
- package/dist/tax/stateTax.js +198 -0
- package/dist/testing/money.d.ts +7 -0
- package/dist/testing/money.js +17 -0
- package/dist/testing/planFixtures.d.ts +29 -0
- package/dist/testing/planFixtures.js +141 -0
- package/package.json +75 -0
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State income tax pack — all 50 states + DC ("big levers", V5 PR B).
|
|
3
|
+
*
|
|
4
|
+
* Transcribed from the cited per-state research docs in
|
|
5
|
+
* DOCS/domain/state-tax-research/ (see each <CODE>.md for sources and the
|
|
6
|
+
* simplifications each state's mapping makes). Values are latest-published
|
|
7
|
+
* (≈2025) individual-income-tax figures; like the federal pack, nominal
|
|
8
|
+
* brackets are carried forward for future years (bracket creep modeled).
|
|
9
|
+
*
|
|
10
|
+
* State taxable income in the engine starts from gross ordinary income (plus
|
|
11
|
+
* gains, plus the federally taxable SS amount where the state taxes SS), minus
|
|
12
|
+
* the retirement exclusion and the standard deduction below. For states that
|
|
13
|
+
* tax *federal taxable income* and have no separate deduction (e.g. CO), the
|
|
14
|
+
* standard deduction is set to the federal-equivalent so the gross→taxable
|
|
15
|
+
* conversion matches; noted inline.
|
|
16
|
+
*/
|
|
17
|
+
const PUBLIC_PENSION_OVERRIDES = {
|
|
18
|
+
AL: { kind: 'full' },
|
|
19
|
+
AR: { kind: 'full' },
|
|
20
|
+
HI: { kind: 'full' },
|
|
21
|
+
IN: { kind: 'full' },
|
|
22
|
+
KS: { kind: 'full' },
|
|
23
|
+
LA: { kind: 'full' },
|
|
24
|
+
MA: { kind: 'full' },
|
|
25
|
+
NE: { kind: 'full' },
|
|
26
|
+
NY: { kind: 'full' },
|
|
27
|
+
OH: { kind: 'full' },
|
|
28
|
+
SC: { kind: 'full' },
|
|
29
|
+
};
|
|
30
|
+
function splitRetirementBuckets(raw) {
|
|
31
|
+
const states = {};
|
|
32
|
+
for (const [code, { retirement, ...params }] of Object.entries(raw.states)) {
|
|
33
|
+
states[code] = {
|
|
34
|
+
...params,
|
|
35
|
+
retirementPrivate: retirement,
|
|
36
|
+
retirementPublic: PUBLIC_PENSION_OVERRIDES[code] ?? retirement,
|
|
37
|
+
// Without a separate public-pension law, the copied rule is one cap on
|
|
38
|
+
// all retirement income — the engine must not grant it per bucket.
|
|
39
|
+
retirementRuleShared: PUBLIC_PENSION_OVERRIDES[code] === undefined,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return { year: raw.year, states };
|
|
43
|
+
}
|
|
44
|
+
const rawStateYear2026 = {
|
|
45
|
+
year: 2026,
|
|
46
|
+
states: {
|
|
47
|
+
AL: {
|
|
48
|
+
code: 'AL', name: 'Alabama', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
49
|
+
standardDeduction: { single: 3000, marriedFilingJointly: 8500 },
|
|
50
|
+
brackets: {
|
|
51
|
+
single: [{ lowerBound: 0, ratePct: 2 }, { lowerBound: 500, ratePct: 4 }, { lowerBound: 3000, ratePct: 5 }],
|
|
52
|
+
marriedFilingJointly: [{ lowerBound: 0, ratePct: 2 }, { lowerBound: 1000, ratePct: 4 }, { lowerBound: 6000, ratePct: 5 }],
|
|
53
|
+
},
|
|
54
|
+
retirement: { kind: 'capped', capPerPerson: 6000, minAge: 65 },
|
|
55
|
+
},
|
|
56
|
+
AK: {
|
|
57
|
+
code: 'AK', name: 'Alaska', hasIncomeTax: false, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
58
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
59
|
+
brackets: { single: [], marriedFilingJointly: [] }, retirement: { kind: 'none' },
|
|
60
|
+
},
|
|
61
|
+
AZ: {
|
|
62
|
+
code: 'AZ', name: 'Arizona', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
63
|
+
standardDeduction: { single: 15000, marriedFilingJointly: 30000 },
|
|
64
|
+
brackets: { single: [{ lowerBound: 0, ratePct: 2.5 }], marriedFilingJointly: [{ lowerBound: 0, ratePct: 2.5 }] },
|
|
65
|
+
retirement: { kind: 'none' },
|
|
66
|
+
},
|
|
67
|
+
AR: {
|
|
68
|
+
code: 'AR', name: 'Arkansas', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
69
|
+
standardDeduction: { single: 2410, marriedFilingJointly: 4820 },
|
|
70
|
+
brackets: {
|
|
71
|
+
single: [{ lowerBound: 0, ratePct: 2 }, { lowerBound: 4500, ratePct: 3.9 }],
|
|
72
|
+
marriedFilingJointly: [{ lowerBound: 0, ratePct: 2 }, { lowerBound: 4500, ratePct: 3.9 }],
|
|
73
|
+
},
|
|
74
|
+
retirement: { kind: 'capped', capPerPerson: 6000 },
|
|
75
|
+
},
|
|
76
|
+
CA: {
|
|
77
|
+
code: 'CA', name: 'California', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
78
|
+
capitalGainsNotes: 'Long-term capital gains are taxed at ordinary California rates; no preferential state rate modeled.',
|
|
79
|
+
capitalGainsSources: [
|
|
80
|
+
'DOCS/domain/state-tax-research/CA.md',
|
|
81
|
+
'https://www.ftb.ca.gov/forms/2025/2025-540-tax-rate-schedules.pdf',
|
|
82
|
+
],
|
|
83
|
+
standardDeduction: { single: 5540, marriedFilingJointly: 11080 },
|
|
84
|
+
brackets: {
|
|
85
|
+
single: [
|
|
86
|
+
{ lowerBound: 0, ratePct: 1 }, { lowerBound: 11079, ratePct: 2 }, { lowerBound: 26264, ratePct: 4 },
|
|
87
|
+
{ lowerBound: 41452, ratePct: 6 }, { lowerBound: 57542, ratePct: 8 }, { lowerBound: 72724, ratePct: 9.3 },
|
|
88
|
+
{ lowerBound: 371479, ratePct: 10.3 }, { lowerBound: 445771, ratePct: 11.3 }, { lowerBound: 742953, ratePct: 12.3 },
|
|
89
|
+
],
|
|
90
|
+
marriedFilingJointly: [
|
|
91
|
+
{ lowerBound: 0, ratePct: 1 }, { lowerBound: 22158, ratePct: 2 }, { lowerBound: 52528, ratePct: 4 },
|
|
92
|
+
{ lowerBound: 82904, ratePct: 6 }, { lowerBound: 115084, ratePct: 8 }, { lowerBound: 145448, ratePct: 9.3 },
|
|
93
|
+
{ lowerBound: 742958, ratePct: 10.3 }, { lowerBound: 891542, ratePct: 11.3 }, { lowerBound: 1485906, ratePct: 12.3 },
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
retirement: { kind: 'none' },
|
|
97
|
+
},
|
|
98
|
+
CO: {
|
|
99
|
+
// Flat 4.4% on federal taxable income; no separate state deduction, so the
|
|
100
|
+
// standard deduction is the federal-equivalent to convert gross→taxable.
|
|
101
|
+
code: 'CO', name: 'Colorado', hasIncomeTax: true, taxesSocialSecurity: true, capitalGainsAsOrdinary: true,
|
|
102
|
+
standardDeduction: { single: 15750, marriedFilingJointly: 31500 },
|
|
103
|
+
brackets: { single: [{ lowerBound: 0, ratePct: 4.4 }], marriedFilingJointly: [{ lowerBound: 0, ratePct: 4.4 }] },
|
|
104
|
+
retirement: { kind: 'capped', capPerPerson: 24000, minAge: 65 },
|
|
105
|
+
},
|
|
106
|
+
CT: {
|
|
107
|
+
code: 'CT', name: 'Connecticut', hasIncomeTax: true, taxesSocialSecurity: true, capitalGainsAsOrdinary: true,
|
|
108
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
109
|
+
brackets: {
|
|
110
|
+
single: [
|
|
111
|
+
{ lowerBound: 0, ratePct: 2 }, { lowerBound: 10000, ratePct: 4.5 }, { lowerBound: 50000, ratePct: 5.5 },
|
|
112
|
+
{ lowerBound: 100000, ratePct: 6 }, { lowerBound: 200000, ratePct: 6.5 }, { lowerBound: 250000, ratePct: 6.9 },
|
|
113
|
+
{ lowerBound: 500000, ratePct: 6.99 },
|
|
114
|
+
],
|
|
115
|
+
marriedFilingJointly: [
|
|
116
|
+
{ lowerBound: 0, ratePct: 2 }, { lowerBound: 20000, ratePct: 4.5 }, { lowerBound: 100000, ratePct: 5.5 },
|
|
117
|
+
{ lowerBound: 200000, ratePct: 6 }, { lowerBound: 400000, ratePct: 6.5 }, { lowerBound: 500000, ratePct: 6.9 },
|
|
118
|
+
{ lowerBound: 1000000, ratePct: 6.99 },
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
retirement: { kind: 'full' }, // pension/IRA reach full exemption by 2026
|
|
122
|
+
},
|
|
123
|
+
DE: {
|
|
124
|
+
code: 'DE', name: 'Delaware', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
125
|
+
standardDeduction: { single: 5700, marriedFilingJointly: 11400 },
|
|
126
|
+
brackets: {
|
|
127
|
+
single: [
|
|
128
|
+
{ lowerBound: 0, ratePct: 0 }, { lowerBound: 2000, ratePct: 2.2 }, { lowerBound: 5000, ratePct: 3.9 },
|
|
129
|
+
{ lowerBound: 10000, ratePct: 4.8 }, { lowerBound: 20000, ratePct: 5.2 }, { lowerBound: 25000, ratePct: 5.5 },
|
|
130
|
+
{ lowerBound: 60000, ratePct: 6.6 },
|
|
131
|
+
],
|
|
132
|
+
marriedFilingJointly: [
|
|
133
|
+
{ lowerBound: 0, ratePct: 0 }, { lowerBound: 2000, ratePct: 2.2 }, { lowerBound: 5000, ratePct: 3.9 },
|
|
134
|
+
{ lowerBound: 10000, ratePct: 4.8 }, { lowerBound: 20000, ratePct: 5.2 }, { lowerBound: 25000, ratePct: 5.5 },
|
|
135
|
+
{ lowerBound: 60000, ratePct: 6.6 },
|
|
136
|
+
],
|
|
137
|
+
},
|
|
138
|
+
retirement: { kind: 'capped', capPerPerson: 12500, minAge: 60 },
|
|
139
|
+
},
|
|
140
|
+
DC: {
|
|
141
|
+
code: 'DC', name: 'District of Columbia', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
142
|
+
standardDeduction: { single: 15000, marriedFilingJointly: 30000 },
|
|
143
|
+
brackets: {
|
|
144
|
+
single: [
|
|
145
|
+
{ lowerBound: 0, ratePct: 4 }, { lowerBound: 10000, ratePct: 6 }, { lowerBound: 40000, ratePct: 6.5 },
|
|
146
|
+
{ lowerBound: 60000, ratePct: 8.5 }, { lowerBound: 250000, ratePct: 9.25 }, { lowerBound: 500000, ratePct: 9.75 },
|
|
147
|
+
{ lowerBound: 1000000, ratePct: 10.75 },
|
|
148
|
+
],
|
|
149
|
+
marriedFilingJointly: [
|
|
150
|
+
{ lowerBound: 0, ratePct: 4 }, { lowerBound: 10000, ratePct: 6 }, { lowerBound: 40000, ratePct: 6.5 },
|
|
151
|
+
{ lowerBound: 60000, ratePct: 8.5 }, { lowerBound: 250000, ratePct: 9.25 }, { lowerBound: 500000, ratePct: 9.75 },
|
|
152
|
+
{ lowerBound: 1000000, ratePct: 10.75 },
|
|
153
|
+
],
|
|
154
|
+
},
|
|
155
|
+
retirement: { kind: 'none' },
|
|
156
|
+
},
|
|
157
|
+
FL: {
|
|
158
|
+
code: 'FL', name: 'Florida', hasIncomeTax: false, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
159
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
160
|
+
brackets: { single: [], marriedFilingJointly: [] }, retirement: { kind: 'none' },
|
|
161
|
+
},
|
|
162
|
+
GA: {
|
|
163
|
+
code: 'GA', name: 'Georgia', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
164
|
+
standardDeduction: { single: 12000, marriedFilingJointly: 24000 },
|
|
165
|
+
brackets: { single: [{ lowerBound: 0, ratePct: 5.39 }], marriedFilingJointly: [{ lowerBound: 0, ratePct: 5.39 }] },
|
|
166
|
+
retirement: { kind: 'capped', capPerPerson: 65000, minAge: 65 },
|
|
167
|
+
},
|
|
168
|
+
HI: {
|
|
169
|
+
code: 'HI', name: 'Hawaii', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
170
|
+
standardDeduction: { single: 4400, marriedFilingJointly: 8800 },
|
|
171
|
+
brackets: {
|
|
172
|
+
single: [
|
|
173
|
+
{ lowerBound: 0, ratePct: 1.4 }, { lowerBound: 9600, ratePct: 3.2 }, { lowerBound: 14400, ratePct: 5.5 },
|
|
174
|
+
{ lowerBound: 19200, ratePct: 6.4 }, { lowerBound: 24000, ratePct: 6.8 }, { lowerBound: 36000, ratePct: 7.2 },
|
|
175
|
+
{ lowerBound: 48000, ratePct: 7.6 }, { lowerBound: 125000, ratePct: 7.9 }, { lowerBound: 175000, ratePct: 8.25 },
|
|
176
|
+
{ lowerBound: 225000, ratePct: 9 }, { lowerBound: 275000, ratePct: 10 }, { lowerBound: 325000, ratePct: 11 },
|
|
177
|
+
],
|
|
178
|
+
marriedFilingJointly: [
|
|
179
|
+
{ lowerBound: 0, ratePct: 1.4 }, { lowerBound: 19200, ratePct: 3.2 }, { lowerBound: 28800, ratePct: 5.5 },
|
|
180
|
+
{ lowerBound: 38400, ratePct: 6.4 }, { lowerBound: 48000, ratePct: 6.8 }, { lowerBound: 72000, ratePct: 7.2 },
|
|
181
|
+
{ lowerBound: 96000, ratePct: 7.6 }, { lowerBound: 250000, ratePct: 7.9 }, { lowerBound: 350000, ratePct: 8.25 },
|
|
182
|
+
{ lowerBound: 450000, ratePct: 9 }, { lowerBound: 550000, ratePct: 10 }, { lowerBound: 650000, ratePct: 11 },
|
|
183
|
+
],
|
|
184
|
+
},
|
|
185
|
+
retirement: { kind: 'none' },
|
|
186
|
+
},
|
|
187
|
+
ID: {
|
|
188
|
+
code: 'ID', name: 'Idaho', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
189
|
+
standardDeduction: { single: 15000, marriedFilingJointly: 30000 },
|
|
190
|
+
brackets: {
|
|
191
|
+
single: [{ lowerBound: 0, ratePct: 0 }, { lowerBound: 4811, ratePct: 5.3 }],
|
|
192
|
+
marriedFilingJointly: [{ lowerBound: 0, ratePct: 0 }, { lowerBound: 9622, ratePct: 5.3 }],
|
|
193
|
+
},
|
|
194
|
+
retirement: { kind: 'none' },
|
|
195
|
+
},
|
|
196
|
+
IL: {
|
|
197
|
+
code: 'IL', name: 'Illinois', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
198
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
199
|
+
brackets: { single: [{ lowerBound: 0, ratePct: 4.95 }], marriedFilingJointly: [{ lowerBound: 0, ratePct: 4.95 }] },
|
|
200
|
+
retirement: { kind: 'full' },
|
|
201
|
+
},
|
|
202
|
+
IN: {
|
|
203
|
+
code: 'IN', name: 'Indiana', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
204
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
205
|
+
brackets: { single: [{ lowerBound: 0, ratePct: 3 }], marriedFilingJointly: [{ lowerBound: 0, ratePct: 3 }] },
|
|
206
|
+
retirement: { kind: 'none' },
|
|
207
|
+
},
|
|
208
|
+
IA: {
|
|
209
|
+
code: 'IA', name: 'Iowa', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
210
|
+
standardDeduction: { single: 15000, marriedFilingJointly: 30000 },
|
|
211
|
+
brackets: { single: [{ lowerBound: 0, ratePct: 3.8 }], marriedFilingJointly: [{ lowerBound: 0, ratePct: 3.8 }] },
|
|
212
|
+
retirement: { kind: 'full', minAge: 55 },
|
|
213
|
+
},
|
|
214
|
+
KS: {
|
|
215
|
+
code: 'KS', name: 'Kansas', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
216
|
+
standardDeduction: { single: 3605, marriedFilingJointly: 8240 },
|
|
217
|
+
brackets: {
|
|
218
|
+
single: [{ lowerBound: 0, ratePct: 5.2 }, { lowerBound: 23000, ratePct: 5.58 }],
|
|
219
|
+
marriedFilingJointly: [{ lowerBound: 0, ratePct: 5.2 }, { lowerBound: 46000, ratePct: 5.58 }],
|
|
220
|
+
},
|
|
221
|
+
retirement: { kind: 'none' },
|
|
222
|
+
},
|
|
223
|
+
KY: {
|
|
224
|
+
code: 'KY', name: 'Kentucky', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
225
|
+
standardDeduction: { single: 3360, marriedFilingJointly: 6720 },
|
|
226
|
+
brackets: { single: [{ lowerBound: 0, ratePct: 3.5 }], marriedFilingJointly: [{ lowerBound: 0, ratePct: 3.5 }] },
|
|
227
|
+
retirement: { kind: 'capped', capPerPerson: 31110 },
|
|
228
|
+
},
|
|
229
|
+
LA: {
|
|
230
|
+
code: 'LA', name: 'Louisiana', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
231
|
+
standardDeduction: { single: 12500, marriedFilingJointly: 25000 },
|
|
232
|
+
brackets: { single: [{ lowerBound: 0, ratePct: 3 }], marriedFilingJointly: [{ lowerBound: 0, ratePct: 3 }] },
|
|
233
|
+
retirement: { kind: 'capped', capPerPerson: 12000, minAge: 65 },
|
|
234
|
+
},
|
|
235
|
+
ME: {
|
|
236
|
+
code: 'ME', name: 'Maine', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
237
|
+
standardDeduction: { single: 15000, marriedFilingJointly: 30000 },
|
|
238
|
+
brackets: {
|
|
239
|
+
single: [{ lowerBound: 0, ratePct: 5.8 }, { lowerBound: 26800, ratePct: 6.75 }, { lowerBound: 63450, ratePct: 7.15 }],
|
|
240
|
+
marriedFilingJointly: [{ lowerBound: 0, ratePct: 5.8 }, { lowerBound: 53600, ratePct: 6.75 }, { lowerBound: 126900, ratePct: 7.15 }],
|
|
241
|
+
},
|
|
242
|
+
retirement: { kind: 'capped', capPerPerson: 48216 },
|
|
243
|
+
},
|
|
244
|
+
MD: {
|
|
245
|
+
code: 'MD', name: 'Maryland', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
246
|
+
standardDeduction: { single: 3350, marriedFilingJointly: 6700 },
|
|
247
|
+
brackets: {
|
|
248
|
+
single: [
|
|
249
|
+
{ lowerBound: 0, ratePct: 2 }, { lowerBound: 1000, ratePct: 3 }, { lowerBound: 2000, ratePct: 4 },
|
|
250
|
+
{ lowerBound: 3000, ratePct: 4.75 }, { lowerBound: 100000, ratePct: 5 }, { lowerBound: 125000, ratePct: 5.25 },
|
|
251
|
+
{ lowerBound: 150000, ratePct: 5.5 }, { lowerBound: 250000, ratePct: 5.75 }, { lowerBound: 500000, ratePct: 6.25 },
|
|
252
|
+
{ lowerBound: 1000000, ratePct: 6.5 },
|
|
253
|
+
],
|
|
254
|
+
marriedFilingJointly: [
|
|
255
|
+
{ lowerBound: 0, ratePct: 2 }, { lowerBound: 1000, ratePct: 3 }, { lowerBound: 2000, ratePct: 4 },
|
|
256
|
+
{ lowerBound: 3000, ratePct: 4.75 }, { lowerBound: 150000, ratePct: 5 }, { lowerBound: 175000, ratePct: 5.25 },
|
|
257
|
+
{ lowerBound: 225000, ratePct: 5.5 }, { lowerBound: 300000, ratePct: 5.75 }, { lowerBound: 600000, ratePct: 6.25 },
|
|
258
|
+
{ lowerBound: 1200000, ratePct: 6.5 },
|
|
259
|
+
],
|
|
260
|
+
},
|
|
261
|
+
retirement: { kind: 'capped', capPerPerson: 41200, minAge: 65 },
|
|
262
|
+
},
|
|
263
|
+
MA: {
|
|
264
|
+
code: 'MA', name: 'Massachusetts', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
265
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
266
|
+
brackets: { single: [{ lowerBound: 0, ratePct: 5 }], marriedFilingJointly: [{ lowerBound: 0, ratePct: 5 }] },
|
|
267
|
+
retirement: { kind: 'none' },
|
|
268
|
+
},
|
|
269
|
+
MI: {
|
|
270
|
+
code: 'MI', name: 'Michigan', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
271
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
272
|
+
brackets: { single: [{ lowerBound: 0, ratePct: 4.25 }], marriedFilingJointly: [{ lowerBound: 0, ratePct: 4.25 }] },
|
|
273
|
+
retirement: { kind: 'capped', capPerPerson: 49423 },
|
|
274
|
+
},
|
|
275
|
+
MN: {
|
|
276
|
+
code: 'MN', name: 'Minnesota', hasIncomeTax: true, taxesSocialSecurity: true, capitalGainsAsOrdinary: true,
|
|
277
|
+
capitalGainsNotes: 'Long-term capital gains are taxed as ordinary income; high-income NIIT-like surtax omitted.',
|
|
278
|
+
capitalGainsSources: ['DOCS/domain/state-tax-research/MN.md', 'https://www.revenue.state.mn.us/'],
|
|
279
|
+
standardDeduction: { single: 14575, marriedFilingJointly: 29150 },
|
|
280
|
+
brackets: {
|
|
281
|
+
single: [
|
|
282
|
+
{ lowerBound: 0, ratePct: 5.35 }, { lowerBound: 31690, ratePct: 6.8 }, { lowerBound: 104090, ratePct: 7.85 },
|
|
283
|
+
{ lowerBound: 193240, ratePct: 9.85 },
|
|
284
|
+
],
|
|
285
|
+
marriedFilingJointly: [
|
|
286
|
+
{ lowerBound: 0, ratePct: 5.35 }, { lowerBound: 46330, ratePct: 6.8 }, { lowerBound: 184040, ratePct: 7.85 },
|
|
287
|
+
{ lowerBound: 321450, ratePct: 9.85 },
|
|
288
|
+
],
|
|
289
|
+
},
|
|
290
|
+
retirement: { kind: 'none' },
|
|
291
|
+
},
|
|
292
|
+
MS: {
|
|
293
|
+
code: 'MS', name: 'Mississippi', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
294
|
+
standardDeduction: { single: 2300, marriedFilingJointly: 4600 },
|
|
295
|
+
brackets: {
|
|
296
|
+
single: [{ lowerBound: 0, ratePct: 0 }, { lowerBound: 10000, ratePct: 4.4 }],
|
|
297
|
+
marriedFilingJointly: [{ lowerBound: 0, ratePct: 0 }, { lowerBound: 10000, ratePct: 4.4 }],
|
|
298
|
+
},
|
|
299
|
+
retirement: { kind: 'full' },
|
|
300
|
+
},
|
|
301
|
+
MO: {
|
|
302
|
+
code: 'MO', name: 'Missouri', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
303
|
+
standardDeduction: { single: 15750, marriedFilingJointly: 31500 },
|
|
304
|
+
brackets: {
|
|
305
|
+
single: [
|
|
306
|
+
{ lowerBound: 0, ratePct: 0 }, { lowerBound: 1313, ratePct: 2 }, { lowerBound: 2626, ratePct: 2.5 },
|
|
307
|
+
{ lowerBound: 3939, ratePct: 3 }, { lowerBound: 5252, ratePct: 3.5 }, { lowerBound: 6565, ratePct: 4 },
|
|
308
|
+
{ lowerBound: 7878, ratePct: 4.5 }, { lowerBound: 9191, ratePct: 4.7 },
|
|
309
|
+
],
|
|
310
|
+
marriedFilingJointly: [
|
|
311
|
+
{ lowerBound: 0, ratePct: 0 }, { lowerBound: 1313, ratePct: 2 }, { lowerBound: 2626, ratePct: 2.5 },
|
|
312
|
+
{ lowerBound: 3939, ratePct: 3 }, { lowerBound: 5252, ratePct: 3.5 }, { lowerBound: 6565, ratePct: 4 },
|
|
313
|
+
{ lowerBound: 7878, ratePct: 4.5 }, { lowerBound: 9191, ratePct: 4.7 },
|
|
314
|
+
],
|
|
315
|
+
},
|
|
316
|
+
retirement: { kind: 'capped', capPerPerson: 6000 },
|
|
317
|
+
},
|
|
318
|
+
MT: {
|
|
319
|
+
code: 'MT', name: 'Montana', hasIncomeTax: true, taxesSocialSecurity: true, capitalGainsAsOrdinary: true,
|
|
320
|
+
standardDeduction: { single: 15750, marriedFilingJointly: 31500 },
|
|
321
|
+
brackets: {
|
|
322
|
+
single: [{ lowerBound: 0, ratePct: 4.7 }, { lowerBound: 20500, ratePct: 5.9 }],
|
|
323
|
+
marriedFilingJointly: [{ lowerBound: 0, ratePct: 4.7 }, { lowerBound: 41000, ratePct: 5.9 }],
|
|
324
|
+
},
|
|
325
|
+
retirement: { kind: 'none' },
|
|
326
|
+
},
|
|
327
|
+
NE: {
|
|
328
|
+
code: 'NE', name: 'Nebraska', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
329
|
+
standardDeduction: { single: 8600, marriedFilingJointly: 17200 },
|
|
330
|
+
brackets: {
|
|
331
|
+
single: [
|
|
332
|
+
{ lowerBound: 0, ratePct: 2.46 }, { lowerBound: 4030, ratePct: 3.51 }, { lowerBound: 24120, ratePct: 5.01 },
|
|
333
|
+
{ lowerBound: 38870, ratePct: 5.2 },
|
|
334
|
+
],
|
|
335
|
+
marriedFilingJointly: [
|
|
336
|
+
{ lowerBound: 0, ratePct: 2.46 }, { lowerBound: 8040, ratePct: 3.51 }, { lowerBound: 48250, ratePct: 5.01 },
|
|
337
|
+
{ lowerBound: 77730, ratePct: 5.2 },
|
|
338
|
+
],
|
|
339
|
+
},
|
|
340
|
+
retirement: { kind: 'none' },
|
|
341
|
+
},
|
|
342
|
+
NV: {
|
|
343
|
+
code: 'NV', name: 'Nevada', hasIncomeTax: false, taxesSocialSecurity: false, capitalGainsAsOrdinary: false,
|
|
344
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
345
|
+
brackets: { single: [], marriedFilingJointly: [] }, retirement: { kind: 'none' },
|
|
346
|
+
},
|
|
347
|
+
NH: {
|
|
348
|
+
// Wages/retirement never taxed; interest & dividends tax repealed from 2025.
|
|
349
|
+
code: 'NH', name: 'New Hampshire', hasIncomeTax: false, taxesSocialSecurity: false, capitalGainsAsOrdinary: false,
|
|
350
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
351
|
+
brackets: { single: [], marriedFilingJointly: [] }, retirement: { kind: 'none' },
|
|
352
|
+
},
|
|
353
|
+
NJ: {
|
|
354
|
+
code: 'NJ', name: 'New Jersey', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
355
|
+
capitalGainsNotes: 'Capital gains are included in New Jersey gross income and taxed at ordinary NJ rates.',
|
|
356
|
+
capitalGainsSources: ['DOCS/domain/state-tax-research/NJ.md', 'https://www.nj.gov/treasury/taxation/'],
|
|
357
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
358
|
+
brackets: {
|
|
359
|
+
single: [
|
|
360
|
+
{ lowerBound: 0, ratePct: 1.4 }, { lowerBound: 20000, ratePct: 1.75 }, { lowerBound: 35000, ratePct: 3.5 },
|
|
361
|
+
{ lowerBound: 40000, ratePct: 5.525 }, { lowerBound: 75000, ratePct: 6.37 }, { lowerBound: 500000, ratePct: 8.97 },
|
|
362
|
+
{ lowerBound: 1000000, ratePct: 10.75 },
|
|
363
|
+
],
|
|
364
|
+
marriedFilingJointly: [
|
|
365
|
+
{ lowerBound: 0, ratePct: 1.4 }, { lowerBound: 20000, ratePct: 1.75 }, { lowerBound: 50000, ratePct: 2.45 },
|
|
366
|
+
{ lowerBound: 70000, ratePct: 3.5 }, { lowerBound: 80000, ratePct: 5.525 }, { lowerBound: 150000, ratePct: 6.37 },
|
|
367
|
+
{ lowerBound: 500000, ratePct: 8.97 }, { lowerBound: 1000000, ratePct: 10.75 },
|
|
368
|
+
],
|
|
369
|
+
},
|
|
370
|
+
retirement: { kind: 'capped', capPerPerson: 50000, minAge: 62 },
|
|
371
|
+
},
|
|
372
|
+
NM: {
|
|
373
|
+
code: 'NM', name: 'New Mexico', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
374
|
+
standardDeduction: { single: 15750, marriedFilingJointly: 31500 },
|
|
375
|
+
brackets: {
|
|
376
|
+
single: [
|
|
377
|
+
{ lowerBound: 0, ratePct: 1.5 }, { lowerBound: 5500, ratePct: 3.2 }, { lowerBound: 16500, ratePct: 4.3 },
|
|
378
|
+
{ lowerBound: 33500, ratePct: 4.7 }, { lowerBound: 66500, ratePct: 4.9 }, { lowerBound: 210000, ratePct: 5.9 },
|
|
379
|
+
],
|
|
380
|
+
marriedFilingJointly: [
|
|
381
|
+
{ lowerBound: 0, ratePct: 1.5 }, { lowerBound: 8000, ratePct: 3.2 }, { lowerBound: 25000, ratePct: 4.3 },
|
|
382
|
+
{ lowerBound: 50000, ratePct: 4.7 }, { lowerBound: 100000, ratePct: 4.9 }, { lowerBound: 315000, ratePct: 5.9 },
|
|
383
|
+
],
|
|
384
|
+
},
|
|
385
|
+
retirement: { kind: 'none' },
|
|
386
|
+
},
|
|
387
|
+
NY: {
|
|
388
|
+
code: 'NY', name: 'New York', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
389
|
+
standardDeduction: { single: 8000, marriedFilingJointly: 16050 },
|
|
390
|
+
brackets: {
|
|
391
|
+
single: [
|
|
392
|
+
{ lowerBound: 0, ratePct: 4 }, { lowerBound: 8500, ratePct: 4.5 }, { lowerBound: 11700, ratePct: 5.25 },
|
|
393
|
+
{ lowerBound: 13900, ratePct: 5.5 }, { lowerBound: 80650, ratePct: 6 }, { lowerBound: 215400, ratePct: 6.85 },
|
|
394
|
+
{ lowerBound: 1077550, ratePct: 9.65 },
|
|
395
|
+
],
|
|
396
|
+
marriedFilingJointly: [
|
|
397
|
+
{ lowerBound: 0, ratePct: 4 }, { lowerBound: 17150, ratePct: 4.5 }, { lowerBound: 23600, ratePct: 5.25 },
|
|
398
|
+
{ lowerBound: 27900, ratePct: 5.5 }, { lowerBound: 161550, ratePct: 6 }, { lowerBound: 323200, ratePct: 6.85 },
|
|
399
|
+
{ lowerBound: 2155350, ratePct: 9.65 },
|
|
400
|
+
],
|
|
401
|
+
},
|
|
402
|
+
retirement: { kind: 'capped', capPerPerson: 20000, minAge: 59 },
|
|
403
|
+
},
|
|
404
|
+
NC: {
|
|
405
|
+
code: 'NC', name: 'North Carolina', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
406
|
+
standardDeduction: { single: 12750, marriedFilingJointly: 25500 },
|
|
407
|
+
brackets: { single: [{ lowerBound: 0, ratePct: 4.25 }], marriedFilingJointly: [{ lowerBound: 0, ratePct: 4.25 }] },
|
|
408
|
+
retirement: { kind: 'none' },
|
|
409
|
+
},
|
|
410
|
+
ND: {
|
|
411
|
+
// Brackets defined on federal taxable income; std deduction ≈ federal base.
|
|
412
|
+
code: 'ND', name: 'North Dakota', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
413
|
+
standardDeduction: { single: 15000, marriedFilingJointly: 30000 },
|
|
414
|
+
brackets: {
|
|
415
|
+
single: [{ lowerBound: 0, ratePct: 0 }, { lowerBound: 48475, ratePct: 1.95 }, { lowerBound: 244825, ratePct: 2.5 }],
|
|
416
|
+
marriedFilingJointly: [{ lowerBound: 0, ratePct: 0 }, { lowerBound: 80975, ratePct: 1.95 }, { lowerBound: 298075, ratePct: 2.5 }],
|
|
417
|
+
},
|
|
418
|
+
retirement: { kind: 'none' },
|
|
419
|
+
},
|
|
420
|
+
OH: {
|
|
421
|
+
code: 'OH', name: 'Ohio', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
422
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
423
|
+
brackets: {
|
|
424
|
+
single: [{ lowerBound: 0, ratePct: 0 }, { lowerBound: 26050, ratePct: 2.75 }, { lowerBound: 100000, ratePct: 3.5 }],
|
|
425
|
+
marriedFilingJointly: [{ lowerBound: 0, ratePct: 0 }, { lowerBound: 26050, ratePct: 2.75 }, { lowerBound: 100000, ratePct: 3.5 }],
|
|
426
|
+
},
|
|
427
|
+
retirement: { kind: 'none' },
|
|
428
|
+
},
|
|
429
|
+
OK: {
|
|
430
|
+
code: 'OK', name: 'Oklahoma', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
431
|
+
standardDeduction: { single: 6350, marriedFilingJointly: 12700 },
|
|
432
|
+
brackets: {
|
|
433
|
+
single: [
|
|
434
|
+
{ lowerBound: 0, ratePct: 0.25 }, { lowerBound: 1000, ratePct: 0.75 }, { lowerBound: 2500, ratePct: 1.75 },
|
|
435
|
+
{ lowerBound: 3750, ratePct: 2.75 }, { lowerBound: 4900, ratePct: 3.75 }, { lowerBound: 7200, ratePct: 4.75 },
|
|
436
|
+
],
|
|
437
|
+
marriedFilingJointly: [
|
|
438
|
+
{ lowerBound: 0, ratePct: 0.25 }, { lowerBound: 2000, ratePct: 0.75 }, { lowerBound: 5000, ratePct: 1.75 },
|
|
439
|
+
{ lowerBound: 7500, ratePct: 2.75 }, { lowerBound: 9800, ratePct: 3.75 }, { lowerBound: 14400, ratePct: 4.75 },
|
|
440
|
+
],
|
|
441
|
+
},
|
|
442
|
+
retirement: { kind: 'capped', capPerPerson: 10000 },
|
|
443
|
+
},
|
|
444
|
+
OR: {
|
|
445
|
+
code: 'OR', name: 'Oregon', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
446
|
+
standardDeduction: { single: 2835, marriedFilingJointly: 5670 },
|
|
447
|
+
brackets: {
|
|
448
|
+
single: [
|
|
449
|
+
{ lowerBound: 0, ratePct: 4.75 }, { lowerBound: 4050, ratePct: 6.75 }, { lowerBound: 10200, ratePct: 8.75 },
|
|
450
|
+
{ lowerBound: 125000, ratePct: 9.9 },
|
|
451
|
+
],
|
|
452
|
+
marriedFilingJointly: [
|
|
453
|
+
{ lowerBound: 0, ratePct: 4.75 }, { lowerBound: 8100, ratePct: 6.75 }, { lowerBound: 20400, ratePct: 8.75 },
|
|
454
|
+
{ lowerBound: 250000, ratePct: 9.9 },
|
|
455
|
+
],
|
|
456
|
+
},
|
|
457
|
+
retirement: { kind: 'none' },
|
|
458
|
+
},
|
|
459
|
+
PA: {
|
|
460
|
+
code: 'PA', name: 'Pennsylvania', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
461
|
+
capitalLossCarryforwardConformity: 'currentYearOnly',
|
|
462
|
+
capitalGainsNotes: 'Net gains are taxable at the flat PA rate; federal prior-year capital-loss carryforwards are not modeled as PA offsets.',
|
|
463
|
+
capitalGainsSources: ['DOCS/domain/state-tax-research/PA.md', 'https://www.revenue.pa.gov/'],
|
|
464
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
465
|
+
brackets: { single: [{ lowerBound: 0, ratePct: 3.07 }], marriedFilingJointly: [{ lowerBound: 0, ratePct: 3.07 }] },
|
|
466
|
+
retirement: { kind: 'full', minAge: 60 },
|
|
467
|
+
},
|
|
468
|
+
RI: {
|
|
469
|
+
code: 'RI', name: 'Rhode Island', hasIncomeTax: true, taxesSocialSecurity: true, capitalGainsAsOrdinary: true,
|
|
470
|
+
standardDeduction: { single: 10900, marriedFilingJointly: 21800 },
|
|
471
|
+
brackets: {
|
|
472
|
+
single: [{ lowerBound: 0, ratePct: 3.75 }, { lowerBound: 79900, ratePct: 4.75 }, { lowerBound: 181650, ratePct: 5.99 }],
|
|
473
|
+
marriedFilingJointly: [{ lowerBound: 0, ratePct: 3.75 }, { lowerBound: 79900, ratePct: 4.75 }, { lowerBound: 181650, ratePct: 5.99 }],
|
|
474
|
+
},
|
|
475
|
+
retirement: { kind: 'capped', capPerPerson: 20000, minAge: 67 },
|
|
476
|
+
},
|
|
477
|
+
SC: {
|
|
478
|
+
code: 'SC', name: 'South Carolina', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
479
|
+
standardDeduction: { single: 15000, marriedFilingJointly: 30000 },
|
|
480
|
+
brackets: {
|
|
481
|
+
single: [{ lowerBound: 0, ratePct: 0 }, { lowerBound: 3560, ratePct: 3 }, { lowerBound: 17830, ratePct: 6 }],
|
|
482
|
+
marriedFilingJointly: [{ lowerBound: 0, ratePct: 0 }, { lowerBound: 3560, ratePct: 3 }, { lowerBound: 17830, ratePct: 6 }],
|
|
483
|
+
},
|
|
484
|
+
retirement: { kind: 'capped', capPerPerson: 10000, minAge: 65 },
|
|
485
|
+
},
|
|
486
|
+
SD: {
|
|
487
|
+
code: 'SD', name: 'South Dakota', hasIncomeTax: false, taxesSocialSecurity: false, capitalGainsAsOrdinary: false,
|
|
488
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
489
|
+
brackets: { single: [], marriedFilingJointly: [] }, retirement: { kind: 'none' },
|
|
490
|
+
},
|
|
491
|
+
TN: {
|
|
492
|
+
code: 'TN', name: 'Tennessee', hasIncomeTax: false, taxesSocialSecurity: false, capitalGainsAsOrdinary: false,
|
|
493
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
494
|
+
brackets: { single: [], marriedFilingJointly: [] }, retirement: { kind: 'none' },
|
|
495
|
+
},
|
|
496
|
+
TX: {
|
|
497
|
+
code: 'TX', name: 'Texas', hasIncomeTax: false, taxesSocialSecurity: false, capitalGainsAsOrdinary: false,
|
|
498
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
499
|
+
brackets: { single: [], marriedFilingJointly: [] }, retirement: { kind: 'none' },
|
|
500
|
+
},
|
|
501
|
+
UT: {
|
|
502
|
+
code: 'UT', name: 'Utah', hasIncomeTax: true, taxesSocialSecurity: true, capitalGainsAsOrdinary: true,
|
|
503
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
504
|
+
brackets: { single: [{ lowerBound: 0, ratePct: 4.5 }], marriedFilingJointly: [{ lowerBound: 0, ratePct: 4.5 }] },
|
|
505
|
+
retirement: { kind: 'none' },
|
|
506
|
+
},
|
|
507
|
+
VT: {
|
|
508
|
+
code: 'VT', name: 'Vermont', hasIncomeTax: true, taxesSocialSecurity: true, capitalGainsAsOrdinary: true,
|
|
509
|
+
standardDeduction: { single: 7400, marriedFilingJointly: 14850 },
|
|
510
|
+
brackets: {
|
|
511
|
+
single: [
|
|
512
|
+
{ lowerBound: 0, ratePct: 3.35 }, { lowerBound: 47900, ratePct: 6.6 }, { lowerBound: 116000, ratePct: 7.6 },
|
|
513
|
+
{ lowerBound: 242000, ratePct: 8.75 },
|
|
514
|
+
],
|
|
515
|
+
marriedFilingJointly: [
|
|
516
|
+
{ lowerBound: 0, ratePct: 3.35 }, { lowerBound: 79950, ratePct: 6.6 }, { lowerBound: 193300, ratePct: 7.6 },
|
|
517
|
+
{ lowerBound: 294600, ratePct: 8.75 },
|
|
518
|
+
],
|
|
519
|
+
},
|
|
520
|
+
retirement: { kind: 'none' },
|
|
521
|
+
},
|
|
522
|
+
VA: {
|
|
523
|
+
code: 'VA', name: 'Virginia', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
524
|
+
standardDeduction: { single: 8750, marriedFilingJointly: 17500 },
|
|
525
|
+
brackets: {
|
|
526
|
+
single: [
|
|
527
|
+
{ lowerBound: 0, ratePct: 2 }, { lowerBound: 3000, ratePct: 3 }, { lowerBound: 5000, ratePct: 5 },
|
|
528
|
+
{ lowerBound: 17000, ratePct: 5.75 },
|
|
529
|
+
],
|
|
530
|
+
marriedFilingJointly: [
|
|
531
|
+
{ lowerBound: 0, ratePct: 2 }, { lowerBound: 3000, ratePct: 3 }, { lowerBound: 5000, ratePct: 5 },
|
|
532
|
+
{ lowerBound: 17000, ratePct: 5.75 },
|
|
533
|
+
],
|
|
534
|
+
},
|
|
535
|
+
retirement: { kind: 'capped', capPerPerson: 12000, minAge: 65 },
|
|
536
|
+
},
|
|
537
|
+
WA: {
|
|
538
|
+
// No broad income tax; a 7% tax on large long-term gains is out of scope.
|
|
539
|
+
code: 'WA', name: 'Washington', hasIncomeTax: false, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
540
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
541
|
+
brackets: { single: [], marriedFilingJointly: [] }, retirement: { kind: 'none' },
|
|
542
|
+
},
|
|
543
|
+
WV: {
|
|
544
|
+
// Social Security fully exempt from 2026 (phase-out complete).
|
|
545
|
+
code: 'WV', name: 'West Virginia', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
546
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
547
|
+
brackets: {
|
|
548
|
+
single: [
|
|
549
|
+
{ lowerBound: 0, ratePct: 2.22 }, { lowerBound: 10000, ratePct: 2.96 }, { lowerBound: 25000, ratePct: 3.33 },
|
|
550
|
+
{ lowerBound: 40000, ratePct: 4.44 }, { lowerBound: 60000, ratePct: 4.82 },
|
|
551
|
+
],
|
|
552
|
+
marriedFilingJointly: [
|
|
553
|
+
{ lowerBound: 0, ratePct: 2.22 }, { lowerBound: 10000, ratePct: 2.96 }, { lowerBound: 25000, ratePct: 3.33 },
|
|
554
|
+
{ lowerBound: 40000, ratePct: 4.44 }, { lowerBound: 60000, ratePct: 4.82 },
|
|
555
|
+
],
|
|
556
|
+
},
|
|
557
|
+
retirement: { kind: 'capped', capPerPerson: 8000, minAge: 65 },
|
|
558
|
+
},
|
|
559
|
+
WI: {
|
|
560
|
+
code: 'WI', name: 'Wisconsin', hasIncomeTax: true, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
561
|
+
standardDeduction: { single: 13560, marriedFilingJointly: 25110 },
|
|
562
|
+
brackets: {
|
|
563
|
+
single: [
|
|
564
|
+
{ lowerBound: 0, ratePct: 3.5 }, { lowerBound: 14680, ratePct: 4.4 }, { lowerBound: 50480, ratePct: 5.3 },
|
|
565
|
+
{ lowerBound: 323290, ratePct: 7.65 },
|
|
566
|
+
],
|
|
567
|
+
marriedFilingJointly: [
|
|
568
|
+
{ lowerBound: 0, ratePct: 3.5 }, { lowerBound: 19580, ratePct: 4.4 }, { lowerBound: 67300, ratePct: 5.3 },
|
|
569
|
+
{ lowerBound: 431060, ratePct: 7.65 },
|
|
570
|
+
],
|
|
571
|
+
},
|
|
572
|
+
retirement: { kind: 'capped', capPerPerson: 24000, minAge: 67 },
|
|
573
|
+
},
|
|
574
|
+
WY: {
|
|
575
|
+
code: 'WY', name: 'Wyoming', hasIncomeTax: false, taxesSocialSecurity: false, capitalGainsAsOrdinary: true,
|
|
576
|
+
standardDeduction: { single: 0, marriedFilingJointly: 0 },
|
|
577
|
+
brackets: { single: [], marriedFilingJointly: [] }, retirement: { kind: 'none' },
|
|
578
|
+
},
|
|
579
|
+
},
|
|
580
|
+
};
|
|
581
|
+
export const stateYear2026 = splitRetirementBuckets(rawStateYear2026);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed access to per-state tax packs. Mirrors the federal `packForYear`
|
|
3
|
+
* pattern: future years use the latest published pack (nominal brackets, so
|
|
4
|
+
* bracket creep is modeled). States with no entry return undefined — the
|
|
5
|
+
* caller falls back to the flat effective-rate override.
|
|
6
|
+
*/
|
|
7
|
+
import type { StateTaxParams } from './types.js';
|
|
8
|
+
export declare const LATEST_STATE_PACK_YEAR: number;
|
|
9
|
+
/** Tax parameters for a state in a year, or undefined if that state isn't modeled yet. */
|
|
10
|
+
export declare function stateParamsFor(code: string, year: number): StateTaxParams | undefined;
|
|
11
|
+
/** Two-letter codes with a modeled pack in the latest year (for UI hints). */
|
|
12
|
+
export declare function modeledStateCodes(): string[];
|
|
13
|
+
export type { StateTaxParams, StateTaxBracket, StateRetirementExclusion, StateTaxPack } from './types.js';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed access to per-state tax packs. Mirrors the federal `packForYear`
|
|
3
|
+
* pattern: future years use the latest published pack (nominal brackets, so
|
|
4
|
+
* bracket creep is modeled). States with no entry return undefined — the
|
|
5
|
+
* caller falls back to the flat effective-rate override.
|
|
6
|
+
*/
|
|
7
|
+
import { stateYear2026 } from './data/year2026.js';
|
|
8
|
+
const packs = [stateYear2026];
|
|
9
|
+
// Keep sorted ascending by year as packs are added each fall.
|
|
10
|
+
export const LATEST_STATE_PACK_YEAR = packs[packs.length - 1].year;
|
|
11
|
+
function statesPackForYear(year) {
|
|
12
|
+
const exact = packs.find((p) => p.year === year);
|
|
13
|
+
if (exact)
|
|
14
|
+
return exact;
|
|
15
|
+
if (year > LATEST_STATE_PACK_YEAR)
|
|
16
|
+
return packs[packs.length - 1];
|
|
17
|
+
return packs[0];
|
|
18
|
+
}
|
|
19
|
+
/** Tax parameters for a state in a year, or undefined if that state isn't modeled yet. */
|
|
20
|
+
export function stateParamsFor(code, year) {
|
|
21
|
+
return statesPackForYear(year).states[code.toUpperCase()];
|
|
22
|
+
}
|
|
23
|
+
/** Two-letter codes with a modeled pack in the latest year (for UI hints). */
|
|
24
|
+
export function modeledStateCodes() {
|
|
25
|
+
return Object.keys(packs[packs.length - 1].states).sort();
|
|
26
|
+
}
|