AgentStack
SKILL verified MIT Self-run

Policyengine Period Patterns

skill-policyengine-policyengine-claude-policyengine-period-patterns-skill · by PolicyEngine

PolicyEngine period handling - converting between YEAR, MONTH definition periods and testing patterns

No reviews yet
0 installs
5 views
0.0% view→install

Install

$ agentstack add skill-policyengine-policyengine-claude-policyengine-period-patterns-skill

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No 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.

Are you the author of Policyengine Period Patterns? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

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

  1. Always specify period explicitly
  2. Input YEAR variables as annual amounts
  3. Expect monthly output for YEAR variables in MONTH tests
  4. Use underscore separators: 12_000 not 12000
  5. 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.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.