Install
$ agentstack add skill-policyengine-policyengine-claude-policyengine-period-patterns-skill ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
PolicyEngine Period Patterns
Essential patterns for handling different definition periods (YEAR, MONTH) in PolicyEngine.
Quick Reference
| From | To | Method | Example | |------|-----|--------|---------| | MONTH formula | YEAR variable | period.this_year | age = person("age", period.this_year) | | YEAR formula | MONTH variable | period.first_month | person("monthly_rent", period.first_month) | | Any | Year integer | period.start.year | year = period.start.year | | Any | Month integer | period.start.month | month = period.start.month | | Annual → Monthly | Divide by 12 | / MONTHS_IN_YEAR | monthly = annual / 12 | | Monthly → Annual | Multiply by 12 | * MONTHS_IN_YEAR | annual = monthly * 12 |
1. Definition Periods in PolicyEngine US
Available Periods
- YEAR: Annual values (most common - 2,883 variables)
- MONTH: Monthly values (395 variables)
- ETERNITY: Never changes (1 variable - structural relationships)
Note: QUARTER is NOT used in PolicyEngine US
Examples
from policyengine_us.model_api import *
class annual_income(Variable):
definition_period = YEAR # Annual amount
class monthly_benefit(Variable):
definition_period = MONTH # Monthly amount
class is_head(Variable):
definition_period = ETERNITY # Never changes
2. The Golden Rule
When accessing a variable with a different definition period than your formula, you must specify the target period explicitly.
# ✅ CORRECT - MONTH formula accessing YEAR variable
def formula(person, period, parameters):
age = person("age", period.this_year) # Gets actual age
# ❌ WRONG - Would get age/12
def formula(person, period, parameters):
age = person("age", period) # BAD: gives age divided by 12!
3. Common Patterns
Pattern 1: MONTH Formula Accessing YEAR Variable
Use Case: Monthly benefits need annual demographic data
class monthly_benefit_eligible(Variable):
value_type = bool
entity = Person
definition_period = MONTH # Monthly eligibility
def formula(person, period, parameters):
# Age is YEAR-defined, use period.this_year
age = person("age", period.this_year) # ✅ Gets full age
# is_pregnant is MONTH-defined, just use period
is_pregnant = person("is_pregnant", period) # ✅ Same period
return (age = 18) & (age = 10:
instant_str = f"{year}-10-01"
else:
instant_str = f"{year - 1}-10-01"
# Access parameters at specific date
p_fpg = parameters(instant_str).gov.hhs.fpg
return p_fpg.first_person / MONTHS_IN_YEAR
5. Parameter Access
Standard Access
def formula(entity, period, parameters):
# Parameters use current period
p = parameters(period).gov.program.benefit
return p.amount
Specific Date Access
def formula(entity, period, parameters):
# Access parameters at specific instant
p = parameters("2024-10-01").gov.hhs.fpg
return p.amount
Important: Never use parameters(period.this_year) - parameters always use the formula's period
6. Testing with Different Periods
Critical Testing Rules
For MONTH period tests (period: 2025-01):
- Input YEAR variables as annual amounts
- Output YEAR variables show monthly values (÷12)
Test Examples
Example 1: Basic MONTH Test
- name: Monthly income test
period: 2025-01 # MONTH period
input:
people:
person1:
employment_income: 12_000 # Input: Annual
output:
employment_income: 1_000 # Output: Monthly (12_000/12)
Example 2: Mixed Variables
- name: Eligibility with age and income
period: 2024-01 # MONTH period
input:
age: 30 # Age doesn't convert
employment_income: 24_000 # Annual input
output:
age: 30 # Age stays same
employment_income: 2_000 # Monthly output
monthly_eligible: true
Example 3: YEAR Period Test
- name: Annual calculation
period: 2024 # YEAR period
input:
employment_income: 18_000 # Annual
output:
employment_income: 18_000 # Annual output
annual_tax: 2_000
Testing Best Practices
- Always specify period explicitly
- Input YEAR variables as annual amounts
- Expect monthly output for YEAR variables in MONTH tests
- Use underscore separators:
12_000not12000 - Add calculation comments in integration tests
7. Common Mistakes and Solutions
❌ Mistake 1: Not Using period.this_year
# WRONG - From MONTH formula
def formula(person, period, parameters):
age = person("age", period) # Gets age/12!
# CORRECT
def formula(person, period, parameters):
age = person("age", period.this_year) # Gets actual age
❌ Mistake 2: Redundant period.thisyear / MONTHSIN_YEAR for Flow Variables
# WRONG - Double-converting; period already auto-divides by 12
fpg = spm_unit("spm_unit_fpg", period.this_year) / MONTHS_IN_YEAR
# CORRECT - Core auto-converts annual → monthly when you use period
fpg = spm_unit("spm_unit_fpg", period)
This applies to all YEAR-defined flow variables (income, FPG, dollar amounts). Using period from a MONTH formula auto-divides by 12. Using period.this_year / MONTHS_IN_YEAR is equivalent but redundant — just use period.
❌ Mistake 3: Mixing annual and monthly
# WRONG - Comparing different units
monthly_income = person("monthly_income", period)
annual_limit = parameters(period).gov.limit
if monthly_income < annual_limit: # BAD comparison
# CORRECT - Convert to same units
monthly_income = person("monthly_income", period)
annual_limit = parameters(period).gov.limit
monthly_limit = annual_limit / MONTHS_IN_YEAR
if monthly_income < monthly_limit: # Good comparison
❌ Mistake 4: Wrong test expectations
# WRONG - Expecting annual in MONTH test
period: 2024-01
input:
employment_income: 12_000
output:
employment_income: 12_000 # Wrong!
# CORRECT
period: 2024-01
input:
employment_income: 12_000 # Annual input
output:
employment_income: 1_000 # Monthly output
8. Real-World Example
class tanf_income_eligible(Variable):
value_type = bool
entity = SPMUnit
definition_period = MONTH # Monthly eligibility
def formula(spm_unit, period, parameters):
# YEAR variables need period.this_year
household_size = spm_unit("spm_unit_size", period.this_year)
state = spm_unit.household("state_code", period.this_year)
# MONTH variables use period
gross_income = spm_unit("tanf_gross_income", period)
# Parameters use period
p = parameters(period).gov.states[state].tanf
# Convert annual limit to monthly
annual_limit = p.income_limit[household_size]
monthly_limit = annual_limit / MONTHS_IN_YEAR
return gross_income <= monthly_limit
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: PolicyEngine
- Source: PolicyEngine/policyengine-claude
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.