diff --git a/changelog.d/525.added.md b/changelog.d/525.added.md new file mode 100644 index 000000000..0f8d820b7 --- /dev/null +++ b/changelog.d/525.added.md @@ -0,0 +1 @@ +Added CPP retirement pension calculation with eligibility, contribution history, and benefit parameters. diff --git a/policyengine_canada/parameters/gov/cra/benefits/cpp/retirement/average_monthly.yaml b/policyengine_canada/parameters/gov/cra/benefits/cpp/retirement/average_monthly.yaml new file mode 100644 index 000000000..2c692feb3 --- /dev/null +++ b/policyengine_canada/parameters/gov/cra/benefits/cpp/retirement/average_monthly.yaml @@ -0,0 +1,16 @@ +description: The Canada Pension Plan applies this average monthly amount for retirement pension benefits at age 65. +values: + 2020-01-01: 710.41 + 2021-01-01: 702.77 + 2022-01-01: 727.61 + 2023-01-01: 758.32 + 2024-01-01: 816.52 + 2025-01-01: 803.76 +metadata: + unit: currency-CAD + period: month + label: CPP average monthly retirement pension + note: "Historical averages (2020-2024) sourced from canada.ca at time of implementation. Canada.ca only displays current values; historical data may require archived sources to verify." + reference: + - title: Canada Pension Plan — Monthly retirement pension amounts + href: https://www.canada.ca/en/services/benefits/publicpensions/cpp/cpp-benefit/amount.html diff --git a/policyengine_canada/parameters/gov/cra/benefits/cpp/retirement/eligibility_age.yaml b/policyengine_canada/parameters/gov/cra/benefits/cpp/retirement/eligibility_age.yaml new file mode 100644 index 000000000..c1e712503 --- /dev/null +++ b/policyengine_canada/parameters/gov/cra/benefits/cpp/retirement/eligibility_age.yaml @@ -0,0 +1,10 @@ +description: The Canada Pension Plan requires this minimum age for retirement pension eligibility. +values: + 2020-01-01: 60 +metadata: + unit: year + period: year + label: CPP retirement pension eligibility age + reference: + - title: Canada Pension Plan — Retirement pension eligibility requirements + href: https://www.canada.ca/en/services/benefits/publicpensions/cpp/cpp-benefit/eligibility.html diff --git a/policyengine_canada/parameters/gov/cra/benefits/cpp/retirement/max_contributory_years.yaml b/policyengine_canada/parameters/gov/cra/benefits/cpp/retirement/max_contributory_years.yaml new file mode 100644 index 000000000..4b8e31417 --- /dev/null +++ b/policyengine_canada/parameters/gov/cra/benefits/cpp/retirement/max_contributory_years.yaml @@ -0,0 +1,11 @@ +description: The Canada Pension Plan sets this as the maximum number of contributory years used to calculate the retirement pension. +values: + 1966-01-01: 40 +metadata: + unit: year + period: year + label: CPP maximum contributory years + note: "CPP Act s. 49 allows contributions from age 18 to 65 (~47 years), but dropout provisions (child-rearing, disability, low-earning years) typically reduce the effective contributory period. The 'best 39 years' rule (post-2024 CPP enhancement) makes 40 a reasonable simplified maximum." + reference: + - title: Canada Pension Plan Act, R.S.C. 1985, c. C-8, s. 49 — Contributory period + href: https://laws-lois.justice.gc.ca/eng/acts/c-8/page-11.html diff --git a/policyengine_canada/parameters/gov/cra/benefits/cpp/retirement/maximum_monthly.yaml b/policyengine_canada/parameters/gov/cra/benefits/cpp/retirement/maximum_monthly.yaml new file mode 100644 index 000000000..86ac5da76 --- /dev/null +++ b/policyengine_canada/parameters/gov/cra/benefits/cpp/retirement/maximum_monthly.yaml @@ -0,0 +1,16 @@ +description: The Canada Pension Plan sets this maximum monthly amount for retirement pension benefits at age 65. +values: + 2020-01-01: 1_175.83 + 2021-01-01: 1_203.75 + 2022-01-01: 1_253.59 + 2023-01-01: 1_306.57 + 2024-01-01: 1_364.60 + 2025-01-01: 1_433.00 +metadata: + unit: currency-CAD + period: month + label: CPP maximum monthly retirement pension + note: "Historical maximums (2020-2024) sourced from canada.ca at time of implementation. Canada.ca only displays current values; historical data may require archived sources to verify." + reference: + - title: Canada Pension Plan — Maximum monthly retirement pension amount + href: https://www.canada.ca/en/services/benefits/publicpensions/cpp/cpp-benefit/amount.html diff --git a/policyengine_canada/tests/gov/cra/benefits/cpp/cpp_retirement_pension.yaml b/policyengine_canada/tests/gov/cra/benefits/cpp/cpp_retirement_pension.yaml new file mode 100644 index 000000000..3b249531d --- /dev/null +++ b/policyengine_canada/tests/gov/cra/benefits/cpp/cpp_retirement_pension.yaml @@ -0,0 +1,55 @@ +- name: CPP retirement pension with full contributions + period: 2024 + input: + age: 65 + cpp_years_of_contribution: 40 + output: + # Full contributions (40 years) = average monthly benefit + # $816.52 * 12 = $9,798.24 + cpp_retirement_pension: 9_798.24 + +- name: CPP retirement pension with partial contributions + period: 2024 + input: + age: 65 + cpp_years_of_contribution: 20 + output: + # 20/40 years = 50% of average benefit + # $816.52 * 0.5 * 12 = $4,899.12 + cpp_retirement_pension: 4_899.12 + +- name: No pension below age 60 + period: 2024 + input: + age: 55 + cpp_years_of_contribution: 30 + output: + cpp_retirement_pension: 0 + +- name: No pension without contributions + period: 2024 + input: + age: 65 + cpp_years_of_contribution: 0 + output: + cpp_retirement_pension: 0 + +- name: CPP retirement pension for 2025 + period: 2025 + input: + age: 70 + cpp_years_of_contribution: 45 + output: + # Capped at 40 years = full average benefit + # $803.76 * 12 = $9,645.12 + cpp_retirement_pension: 9_645.12 + +- name: Minimum contribution scenario + period: 2024 + input: + age: 60 + cpp_years_of_contribution: 1 + output: + # 1/40 years = 2.5% of average benefit + # $816.52 * 0.025 * 12 = $244.956 + cpp_retirement_pension: 244.956 diff --git a/policyengine_canada/variables/gov/benefits.py b/policyengine_canada/variables/gov/benefits.py index 052eae5ed..9a0fd00fa 100644 --- a/policyengine_canada/variables/gov/benefits.py +++ b/policyengine_canada/variables/gov/benefits.py @@ -11,6 +11,7 @@ class benefits(Variable): "child_benefit", "child_disability_benefit", "canada_workers_benefit", + "cpp_retirement_pension", "dental_benefit", "oas_net", # Ontario programs. diff --git a/policyengine_canada/variables/gov/cra/benefits/cpp/cpp_retirement_eligible.py b/policyengine_canada/variables/gov/cra/benefits/cpp/cpp_retirement_eligible.py new file mode 100644 index 000000000..a848c8a9c --- /dev/null +++ b/policyengine_canada/variables/gov/cra/benefits/cpp/cpp_retirement_eligible.py @@ -0,0 +1,23 @@ +from policyengine_canada.model_api import * + + +class cpp_retirement_eligible(Variable): + value_type = bool + entity = Person + label = "Eligible for CPP retirement pension" + definition_period = YEAR + documentation = "Whether person is eligible for CPP retirement pension" + reference = "https://www.canada.ca/en/services/benefits/publicpensions/cpp/cpp-benefit/eligibility.html" + + def formula(person, period, parameters): + p = parameters(period).gov.cra.benefits.cpp.retirement + + # Check age requirement (60+) + age = person("age", period) + meets_age = age >= p.eligibility_age + + # Check contribution requirement (simplified - at least 1 year) + years_contributed = person("cpp_years_of_contribution", period) + has_contributions = years_contributed > 0 + + return meets_age & has_contributions diff --git a/policyengine_canada/variables/gov/cra/benefits/cpp/cpp_retirement_pension.py b/policyengine_canada/variables/gov/cra/benefits/cpp/cpp_retirement_pension.py new file mode 100644 index 000000000..9e7fd7111 --- /dev/null +++ b/policyengine_canada/variables/gov/cra/benefits/cpp/cpp_retirement_pension.py @@ -0,0 +1,29 @@ +from policyengine_canada.model_api import * + + +class cpp_retirement_pension(Variable): + value_type = float + entity = Person + label = "CPP retirement pension" + definition_period = YEAR + unit = CAD + documentation = "Annual CPP retirement pension amount" + reference = "https://www.canada.ca/en/services/benefits/publicpensions/cpp/cpp-benefit/amount.html" + + def formula(person, period, parameters): + p = parameters(period).gov.cra.benefits.cpp.retirement + eligible = person("cpp_retirement_eligible", period) + years_contributed = person("cpp_years_of_contribution", period) + + # Contribution factor: ratio of years contributed to maximum contributory period + max_years = p.max_contributory_years + contribution_factor = min_(years_contributed / max_years, 1) + + # Scale average monthly by contribution factor, cap at maximum monthly + monthly_amount = min_( + p.average_monthly * contribution_factor, + p.maximum_monthly, + ) + annual_amount = monthly_amount * 12 + + return where(eligible, annual_amount, 0) diff --git a/policyengine_canada/variables/gov/cra/benefits/cpp/cpp_years_of_contribution.py b/policyengine_canada/variables/gov/cra/benefits/cpp/cpp_years_of_contribution.py new file mode 100644 index 000000000..dacd59318 --- /dev/null +++ b/policyengine_canada/variables/gov/cra/benefits/cpp/cpp_years_of_contribution.py @@ -0,0 +1,11 @@ +from policyengine_canada.model_api import * + + +class cpp_years_of_contribution(Variable): + value_type = float + entity = Person + label = "Years of CPP contributions" + definition_period = YEAR + unit = "year" + documentation = "Number of years person has contributed to CPP" + reference = "https://www.canada.ca/en/services/benefits/publicpensions/cpp/cpp-benefit/amount.html"