Creating a country package#

Most use cases won’t interact with this package directly, but will instead use a country package, which is a Python package that contains a country’s policy logic and parameters. The country package is responsible for defining the variables that are available in the simulation, and for defining the logic that calculates the values of those variables. The country package also defines the parameters that are used in the logic, and the default values of those parameters. Each country package has the same API:

from policyengine_core.country_template import (
    CountryTaxBenefitSystem,  # Holds all policy-related data.
    Simulation,  # General purpose: enables users to simulate policy on new data.
    Microsimulation,  # Specific purpose: enables users to simulate policy on large datasets.
    COUNTRY_DIR,  # Path to the country directory.
    DATASETS,  # List of datasets available for this country (to use with `Microsimulation`).
)

Building the repo#

To create a new country package, copy the policyengine_core.country_template module code into a new repo. Replace all code specific to the example country as needed. You’ll want to check the following:

  • variables/: contains an arbitrarily-organised set of Python files, each defining a new Variable.

  • parameters/: contains the parameter tree, organised by folder structure.

  • tests/: contains policy logic and other tests.

  • data/: contains definitions for Datasets usable with the country package.

  • situation_examples/: contains JSON examples of situations that can be used to quickly demonstrate the country package.

  • reforms/: contains implementations of reforms that can be applied to the country package.

  • entities.py: contains definitions for the entities use in the country package.

  • __init__.py: contains the CountryTaxBenefitSystem, Simulation and Microsimulation classes.

Creating the country interfaces#

The country package should define each of the main interfaces in the code block above, inheriting from Core classes and adding metadata. Here’s how the example country package does it:

import os
from typing import Dict, Type
from policyengine_core.data.dataset import Dataset
from policyengine_core.populations.population import Population
from policyengine_core.taxbenefitsystems import TaxBenefitSystem
from policyengine_core.country_template import entities
from policyengine_core.country_template.situation_examples import couple
from policyengine_core.simulations import Simulation as CoreSimulation
from policyengine_core.simulations import (
    Microsimulation as CoreMicrosimulation,
)
from policyengine_core.country_template.data.datasets.country_template_dataset import (
    CountryTemplateDataset,
)
from pathlib import Path
import logging
from policyengine_core.country_template.constants import COUNTRY_DIR

DATASETS = [CountryTemplateDataset]  # Important: must be instantiated


class CountryTaxBenefitSystem(TaxBenefitSystem):
    entities = entities.entities
    variables_dir = COUNTRY_DIR / "variables"
    parameters_dir = COUNTRY_DIR / "parameters"
    auto_carry_over_input_variables = False


class Simulation(CoreSimulation):
    default_tax_benefit_system = CountryTaxBenefitSystem


class Microsimulation(CoreMicrosimulation):
    default_tax_benefit_system = CountryTaxBenefitSystem
    default_dataset = CountryTemplateDataset