From 38e928e35077bb0479c7fa808c7b45c4dbb80a26 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 7 Feb 2026 08:15:32 -0500 Subject: [PATCH 1/9] Add liquid asset variables for SSI modeling Adds three input variables imputed from SIPP in policyengine-us-data: - bank_account_assets: checking, savings, money market - stock_assets: stocks and mutual funds - bond_assets: bonds and government securities Updates ssi_countable_resources to calculate from these asset categories, enabling realistic asset-based eligibility testing for SSI. Co-Authored-By: Claude Opus 4.5 --- changelog_entry.yaml | 4 +++ .../resources/ssi_countable_resources.py | 27 +++++++++++++++++++ .../household/assets/bank_account_assets.py | 14 ++++++++++ .../variables/household/assets/bond_assets.py | 14 ++++++++++ .../household/assets/stock_assets.py | 13 +++++++++ 5 files changed, 72 insertions(+) create mode 100644 policyengine_us/variables/household/assets/bank_account_assets.py create mode 100644 policyengine_us/variables/household/assets/bond_assets.py create mode 100644 policyengine_us/variables/household/assets/stock_assets.py diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..a5f1b016b60 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,4 @@ +- bump: minor + changes: + added: + - Add liquid asset input variables (bank_account_assets, stock_assets, bond_assets) and update ssi_countable_resources formula diff --git a/policyengine_us/variables/gov/ssa/ssi/eligibility/resources/ssi_countable_resources.py b/policyengine_us/variables/gov/ssa/ssi/eligibility/resources/ssi_countable_resources.py index ad4498b61a1..19225603eb6 100644 --- a/policyengine_us/variables/gov/ssa/ssi/eligibility/resources/ssi_countable_resources.py +++ b/policyengine_us/variables/gov/ssa/ssi/eligibility/resources/ssi_countable_resources.py @@ -5,5 +5,32 @@ class ssi_countable_resources(Variable): value_type = float entity = Person label = "SSI countable resources" + documentation = ( + "Countable resources for SSI eligibility. Includes liquid assets " + "(bank accounts, stocks, bonds) but excludes home, one vehicle, " + "household goods, and retirement accounts per SSI rules." + ) unit = USD definition_period = YEAR + reference = ( + "https://www.ssa.gov/ssi/spotlights/spot-resources.htm", + "https://www.law.cornell.edu/uscode/text/42/1382b", + ) + + def formula(person, period, parameters): + # SSI counts liquid assets but excludes: + # - Home and land + # - One vehicle (with exceptions) + # - Household goods and personal effects + # - Burial plots and up to $1,500 in burial funds + # - Life insurance with face value <= $1,500 + # - Retirement accounts (excluded under ABLE Act for some) + # + # Current imputation includes: + # - Bank accounts (checking, savings, money market) + # - Stocks and mutual funds + # - Bonds and government securities + bank = person("bank_account_assets", period) + stocks = person("stock_assets", period) + bonds = person("bond_assets", period) + return bank + stocks + bonds diff --git a/policyengine_us/variables/household/assets/bank_account_assets.py b/policyengine_us/variables/household/assets/bank_account_assets.py new file mode 100644 index 00000000000..6feed0c0082 --- /dev/null +++ b/policyengine_us/variables/household/assets/bank_account_assets.py @@ -0,0 +1,14 @@ +from policyengine_us.model_api import * + + +class bank_account_assets(Variable): + value_type = float + entity = Person + label = "Bank account assets" + documentation = ( + "Value of checking, savings, and money market accounts. " + "Imputed from SIPP TVAL_BANK." + ) + unit = USD + definition_period = YEAR + uprating = "gov.bls.cpi.cpi_u" diff --git a/policyengine_us/variables/household/assets/bond_assets.py b/policyengine_us/variables/household/assets/bond_assets.py new file mode 100644 index 00000000000..b9909f9a1df --- /dev/null +++ b/policyengine_us/variables/household/assets/bond_assets.py @@ -0,0 +1,14 @@ +from policyengine_us.model_api import * + + +class bond_assets(Variable): + value_type = float + entity = Person + label = "Bond assets" + documentation = ( + "Value of bonds and government securities. " + "Imputed from SIPP TVAL_BOND." + ) + unit = USD + definition_period = YEAR + uprating = "gov.bls.cpi.cpi_u" diff --git a/policyengine_us/variables/household/assets/stock_assets.py b/policyengine_us/variables/household/assets/stock_assets.py new file mode 100644 index 00000000000..bd40f3e15bf --- /dev/null +++ b/policyengine_us/variables/household/assets/stock_assets.py @@ -0,0 +1,13 @@ +from policyengine_us.model_api import * + + +class stock_assets(Variable): + value_type = float + entity = Person + label = "Stock assets" + documentation = ( + "Value of stocks and mutual funds. " "Imputed from SIPP TVAL_STMF." + ) + unit = USD + definition_period = YEAR + uprating = "gov.bls.cpi.cpi_u" From d7653b809ab2248555ca2826e7cb2dce81cb6e91 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 7 Feb 2026 08:22:34 -0500 Subject: [PATCH 2/9] Use adds pattern for ssi_countable_resources Replace formula with adds attribute referencing parameter file that lists the asset sources. This separates policy logic (which assets count) from variable implementation. Co-Authored-By: Claude Opus 4.5 --- changelog_entry.yaml | 2 +- .../ssi/eligibility/resources/countable.yaml | 16 ++++++++++++++++ .../resources/ssi_countable_resources.py | 18 +----------------- 3 files changed, 18 insertions(+), 18 deletions(-) create mode 100644 policyengine_us/parameters/gov/ssa/ssi/eligibility/resources/countable.yaml diff --git a/changelog_entry.yaml b/changelog_entry.yaml index a5f1b016b60..b18ef770f27 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -1,4 +1,4 @@ - bump: minor changes: added: - - Add liquid asset input variables (bank_account_assets, stock_assets, bond_assets) and update ssi_countable_resources formula + - Add liquid asset input variables (bank_account_assets, stock_assets, bond_assets) and ssi_countable_resources using adds pattern diff --git a/policyengine_us/parameters/gov/ssa/ssi/eligibility/resources/countable.yaml b/policyengine_us/parameters/gov/ssa/ssi/eligibility/resources/countable.yaml new file mode 100644 index 00000000000..ba2d0b2cd7d --- /dev/null +++ b/policyengine_us/parameters/gov/ssa/ssi/eligibility/resources/countable.yaml @@ -0,0 +1,16 @@ +description: >- + The US counts these asset types as countable resources for SSI eligibility. + Excludes home, one vehicle, household goods, burial plots, and retirement accounts. +values: + 1975-01-01: + # Liquid assets counted as resources + - bank_account_assets # Checking, savings, money market + - stock_assets # Stocks and mutual funds + - bond_assets # Bonds and government securities +metadata: + label: SSI countable resource sources + reference: + - title: SSA - Spotlight on Resources + href: https://www.ssa.gov/ssi/spotlights/spot-resources.htm + - title: 42 U.S.C. 1382b - Resources + href: https://www.law.cornell.edu/uscode/text/42/1382b diff --git a/policyengine_us/variables/gov/ssa/ssi/eligibility/resources/ssi_countable_resources.py b/policyengine_us/variables/gov/ssa/ssi/eligibility/resources/ssi_countable_resources.py index 19225603eb6..c1b0bbb6c86 100644 --- a/policyengine_us/variables/gov/ssa/ssi/eligibility/resources/ssi_countable_resources.py +++ b/policyengine_us/variables/gov/ssa/ssi/eligibility/resources/ssi_countable_resources.py @@ -17,20 +17,4 @@ class ssi_countable_resources(Variable): "https://www.law.cornell.edu/uscode/text/42/1382b", ) - def formula(person, period, parameters): - # SSI counts liquid assets but excludes: - # - Home and land - # - One vehicle (with exceptions) - # - Household goods and personal effects - # - Burial plots and up to $1,500 in burial funds - # - Life insurance with face value <= $1,500 - # - Retirement accounts (excluded under ABLE Act for some) - # - # Current imputation includes: - # - Bank accounts (checking, savings, money market) - # - Stocks and mutual funds - # - Bonds and government securities - bank = person("bank_account_assets", period) - stocks = person("stock_assets", period) - bonds = person("bond_assets", period) - return bank + stocks + bonds + adds = "gov.ssa.ssi.eligibility.resources.countable" From 02ded2b5beffa330647bb13ac76b7fcef7a86388 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 7 Feb 2026 08:42:04 -0500 Subject: [PATCH 3/9] Fix references to use POMS sections that explicitly list countable resources The USC only lists exclusions, not what counts. POMS SI 01140.xxx explicitly defines bank accounts, stocks, and bonds as countable. Co-Authored-By: Claude Opus 4.5 --- .../gov/ssa/ssi/eligibility/resources/countable.yaml | 12 ++++++++---- .../eligibility/resources/ssi_countable_resources.py | 3 +-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/policyengine_us/parameters/gov/ssa/ssi/eligibility/resources/countable.yaml b/policyengine_us/parameters/gov/ssa/ssi/eligibility/resources/countable.yaml index ba2d0b2cd7d..0183ec8cb12 100644 --- a/policyengine_us/parameters/gov/ssa/ssi/eligibility/resources/countable.yaml +++ b/policyengine_us/parameters/gov/ssa/ssi/eligibility/resources/countable.yaml @@ -10,7 +10,11 @@ values: metadata: label: SSI countable resource sources reference: - - title: SSA - Spotlight on Resources - href: https://www.ssa.gov/ssi/spotlights/spot-resources.htm - - title: 42 U.S.C. 1382b - Resources - href: https://www.law.cornell.edu/uscode/text/42/1382b + - title: SSA POMS SI 01140.200 - Checking and Savings Accounts + href: https://secure.ssa.gov/poms.nsf/lnx/0501140200 + - title: SSA POMS SI 01140.220 - Stocks + href: https://secure.ssa.gov/poms.nsf/lnx/0501140220 + - title: SSA POMS SI 01140.240 - U.S. Savings Bonds + href: https://secure.ssa.gov/poms.nsf/lnx/0501140240 + - title: SSA POMS SI 01140.250 - Municipal, Corporate and Government Bonds + href: https://secure.ssa.gov/poms.nsf/lnx/0501140250 diff --git a/policyengine_us/variables/gov/ssa/ssi/eligibility/resources/ssi_countable_resources.py b/policyengine_us/variables/gov/ssa/ssi/eligibility/resources/ssi_countable_resources.py index c1b0bbb6c86..3d6043b017e 100644 --- a/policyengine_us/variables/gov/ssa/ssi/eligibility/resources/ssi_countable_resources.py +++ b/policyengine_us/variables/gov/ssa/ssi/eligibility/resources/ssi_countable_resources.py @@ -13,8 +13,7 @@ class ssi_countable_resources(Variable): unit = USD definition_period = YEAR reference = ( - "https://www.ssa.gov/ssi/spotlights/spot-resources.htm", - "https://www.law.cornell.edu/uscode/text/42/1382b", + "https://secure.ssa.gov/poms.nsf/lnx/0501140000", # POMS SI 01140.000 - Types of Countable Resources ) adds = "gov.ssa.ssi.eligibility.resources.countable" From e7340cfa6cf3d9b16496e272288d4b19a5623368 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 7 Feb 2026 08:49:04 -0500 Subject: [PATCH 4/9] Add spm_unit_cash_assets aggregation from person-level assets spm_unit_cash_assets now sums bank_account_assets, stock_assets, and bond_assets across the SPM unit. This flows through to IL AABD and MA EAEDC which use spm_unit_cash_assets. Co-Authored-By: Claude Opus 4.5 --- changelog_entry.yaml | 2 +- .../variables/household/assets/spm_unit_cash_assets.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/changelog_entry.yaml b/changelog_entry.yaml index b18ef770f27..7fdad2e3738 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -1,4 +1,4 @@ - bump: minor changes: added: - - Add liquid asset input variables (bank_account_assets, stock_assets, bond_assets) and ssi_countable_resources using adds pattern + - Add liquid asset input variables (bank_account_assets, stock_assets, bond_assets), ssi_countable_resources, and spm_unit_cash_assets aggregation diff --git a/policyengine_us/variables/household/assets/spm_unit_cash_assets.py b/policyengine_us/variables/household/assets/spm_unit_cash_assets.py index 954a3a86217..fc143cd39e2 100644 --- a/policyengine_us/variables/household/assets/spm_unit_cash_assets.py +++ b/policyengine_us/variables/household/assets/spm_unit_cash_assets.py @@ -7,3 +7,5 @@ class spm_unit_cash_assets(Variable): label = "SPM unit cash assets" definition_period = YEAR unit = USD + + adds = ["bank_account_assets", "stock_assets", "bond_assets"] From 0d12db2ecf3e80384a5132a6a7d592442c519326 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 7 Feb 2026 08:53:33 -0500 Subject: [PATCH 5/9] Use actual imputed assets for SSI resource test Remove microsimulation bypass that used random pass rate. Now that liquid assets are imputed from SIPP, the resource test can use real calculated values. - Remove pass_rate.yaml parameter (no longer needed) - Update README to reflect new methodology - meets_ssi_resource_test now always uses ssi_countable_resources Co-Authored-By: Claude Opus 4.5 --- changelog_entry.yaml | 2 ++ .../gov/ssa/ssi/eligibility/resources/README.md | 12 +++++++++--- .../gov/ssa/ssi/eligibility/resources/pass_rate.yaml | 3 --- .../eligibility/resources/meets_ssi_resource_test.py | 2 +- 4 files changed, 12 insertions(+), 7 deletions(-) delete mode 100644 policyengine_us/parameters/gov/ssa/ssi/eligibility/resources/pass_rate.yaml diff --git a/changelog_entry.yaml b/changelog_entry.yaml index 7fdad2e3738..347b5a06a0d 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -2,3 +2,5 @@ changes: added: - Add liquid asset input variables (bank_account_assets, stock_assets, bond_assets), ssi_countable_resources, and spm_unit_cash_assets aggregation + changed: + - SSI resource test now uses actual imputed assets instead of random pass rate diff --git a/policyengine_us/parameters/gov/ssa/ssi/eligibility/resources/README.md b/policyengine_us/parameters/gov/ssa/ssi/eligibility/resources/README.md index f45448fdd0e..4035ff7cebc 100644 --- a/policyengine_us/parameters/gov/ssa/ssi/eligibility/resources/README.md +++ b/policyengine_us/parameters/gov/ssa/ssi/eligibility/resources/README.md @@ -1,10 +1,16 @@ # Resources -[SSA reported $5.293 billion in SSI expenditures in February 2023](https://www.ssa.gov/policy/docs/quickfacts/stat_snapshot/#table3). -Adjust `pass_rate.yaml` to match this for SSI in 2023 ($5.293 billion * 12 = $63.5 billion). +SSI countable resources are now calculated from imputed liquid assets +(bank accounts, stocks, bonds) rather than using a random pass rate. + +The assets are imputed from SIPP in policyengine-us-data and flow through +to the SSI resource test via `ssi_countable_resources`. -Check with this code: +Check SSI expenditures with: ```python from policyengine_us import Microsimulation Microsimulation().calc("ssi", map_to="person", period=2023).sum() / 1e9 ``` + +[SSA reported $5.293 billion in SSI expenditures in February 2023](https://www.ssa.gov/policy/docs/quickfacts/stat_snapshot/#table3). +Annual target: $5.293 billion * 12 = $63.5 billion. diff --git a/policyengine_us/parameters/gov/ssa/ssi/eligibility/resources/pass_rate.yaml b/policyengine_us/parameters/gov/ssa/ssi/eligibility/resources/pass_rate.yaml deleted file mode 100644 index cab81f450c9..00000000000 --- a/policyengine_us/parameters/gov/ssa/ssi/eligibility/resources/pass_rate.yaml +++ /dev/null @@ -1,3 +0,0 @@ -description: Proportion of SSI-aged-blind-disabled recipients who meet the asset test. -values: - 0000-01-01: 0.4 diff --git a/policyengine_us/variables/gov/ssa/ssi/eligibility/resources/meets_ssi_resource_test.py b/policyengine_us/variables/gov/ssa/ssi/eligibility/resources/meets_ssi_resource_test.py index 06839203514..590103a2268 100644 --- a/policyengine_us/variables/gov/ssa/ssi/eligibility/resources/meets_ssi_resource_test.py +++ b/policyengine_us/variables/gov/ssa/ssi/eligibility/resources/meets_ssi_resource_test.py @@ -5,8 +5,8 @@ class meets_ssi_resource_test(Variable): value_type = bool entity = Person label = "Meets SSI resource test" - unit = USD definition_period = YEAR + reference = "https://secure.ssa.gov/poms.nsf/lnx/0501110000" def formula(person, period, parameters): p = parameters(period).gov.ssa.ssi From 41bb470ff7f6b7c51ddc9623cc706edcb6efe100 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 7 Feb 2026 08:59:21 -0500 Subject: [PATCH 6/9] Add SSI takeup variable and apply in benefit calculation - Add takes_up_ssi_if_eligible with default_value=True - Apply takeup multiplier in ssi.py for microsimulation - Follows new pattern from PR #7326 (no random() in country package) Co-Authored-By: Claude Opus 4.5 --- changelog_entry.yaml | 2 ++ policyengine_us/variables/gov/ssa/ssi/ssi.py | 5 ++++- .../variables/gov/ssa/ssi/takes_up_ssi_if_eligible.py | 9 +++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 policyengine_us/variables/gov/ssa/ssi/takes_up_ssi_if_eligible.py diff --git a/changelog_entry.yaml b/changelog_entry.yaml index 347b5a06a0d..2cf3a8f0ae0 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -2,5 +2,7 @@ changes: added: - Add liquid asset input variables (bank_account_assets, stock_assets, bond_assets), ssi_countable_resources, and spm_unit_cash_assets aggregation + - Add takes_up_ssi_if_eligible variable for SSI takeup modeling changed: - SSI resource test now uses actual imputed assets instead of random pass rate + - SSI benefit now applies takeup in microsimulation diff --git a/policyengine_us/variables/gov/ssa/ssi/ssi.py b/policyengine_us/variables/gov/ssa/ssi/ssi.py index 47d6d6b74c9..922b94a7271 100644 --- a/policyengine_us/variables/gov/ssa/ssi/ssi.py +++ b/policyengine_us/variables/gov/ssa/ssi/ssi.py @@ -30,8 +30,11 @@ def formula(person, period, parameters): individual_max = p.individual * MONTHS_IN_YEAR capped_benefit = min_(benefit, individual_max) - return where( + final_benefit = where( deeming_applies, capped_benefit, benefit, ) + + takes_up = person("takes_up_ssi_if_eligible", period) + return final_benefit * takes_up diff --git a/policyengine_us/variables/gov/ssa/ssi/takes_up_ssi_if_eligible.py b/policyengine_us/variables/gov/ssa/ssi/takes_up_ssi_if_eligible.py new file mode 100644 index 00000000000..cd8d6d376df --- /dev/null +++ b/policyengine_us/variables/gov/ssa/ssi/takes_up_ssi_if_eligible.py @@ -0,0 +1,9 @@ +from policyengine_us.model_api import * + + +class takes_up_ssi_if_eligible(Variable): + value_type = bool + entity = Person + label = "Takes up SSI if eligible" + definition_period = YEAR + default_value = True From 44b07be4f3185c3cf968b817db8bd3c20871ba1d Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 7 Feb 2026 09:12:41 -0500 Subject: [PATCH 7/9] Trigger CI From 15e5f496e6a7c309f7a0cd1fcf97534647ac53a0 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 7 Feb 2026 09:33:09 -0500 Subject: [PATCH 8/9] Trigger CI From 4f8d5160e373c57cf8a62f86bfe32ef85a783fd0 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 7 Feb 2026 09:38:34 -0500 Subject: [PATCH 9/9] Add POMS references to asset variables Co-Authored-By: Claude Opus 4.5 --- .../variables/household/assets/bank_account_assets.py | 1 + policyengine_us/variables/household/assets/bond_assets.py | 4 ++++ policyengine_us/variables/household/assets/stock_assets.py | 1 + 3 files changed, 6 insertions(+) diff --git a/policyengine_us/variables/household/assets/bank_account_assets.py b/policyengine_us/variables/household/assets/bank_account_assets.py index 6feed0c0082..1dbfdbc151e 100644 --- a/policyengine_us/variables/household/assets/bank_account_assets.py +++ b/policyengine_us/variables/household/assets/bank_account_assets.py @@ -12,3 +12,4 @@ class bank_account_assets(Variable): unit = USD definition_period = YEAR uprating = "gov.bls.cpi.cpi_u" + reference = "https://secure.ssa.gov/poms.nsf/lnx/0501140200" diff --git a/policyengine_us/variables/household/assets/bond_assets.py b/policyengine_us/variables/household/assets/bond_assets.py index b9909f9a1df..6497eabf6d6 100644 --- a/policyengine_us/variables/household/assets/bond_assets.py +++ b/policyengine_us/variables/household/assets/bond_assets.py @@ -12,3 +12,7 @@ class bond_assets(Variable): unit = USD definition_period = YEAR uprating = "gov.bls.cpi.cpi_u" + reference = ( + "https://secure.ssa.gov/poms.nsf/lnx/0501140240", + "https://secure.ssa.gov/poms.nsf/lnx/0501140250", + ) diff --git a/policyengine_us/variables/household/assets/stock_assets.py b/policyengine_us/variables/household/assets/stock_assets.py index bd40f3e15bf..9343c3679c1 100644 --- a/policyengine_us/variables/household/assets/stock_assets.py +++ b/policyengine_us/variables/household/assets/stock_assets.py @@ -11,3 +11,4 @@ class stock_assets(Variable): unit = USD definition_period = YEAR uprating = "gov.bls.cpi.cpi_u" + reference = "https://secure.ssa.gov/poms.nsf/lnx/0501140220"