Coding a formula

Basic Example

The following piece of code creates a variable named flat_tax_on_salary, representing an imaginary tax of 25% on salaries, paid monthly by individuals (not households).

class flat_tax_on_salary(Variable):
    value_type = float
    entity = Person
    definition_period = MONTH
    label = u"Individualized and monthly paid tax on salaries"

    def formula(person, period):
        salary = person('salary', period)
        return salary * 0.25

Let’s explain in detail the different parts of the code:

The variable name

class flat_tax_on_salary(Variable): declares a new variable named flat_tax_on_salary. You can check out our recommended naming conventions.

The variable attributes

All variables have a set of attributes.

  • The value_type defines the type of the formula output. Possible types are the basic Python types. Note however that OpenFisca uses NumPy to run calculations vectorially, so the actual type of data may be slightly different from the built-in Python ones. Available types are:

    • bool: boolean

    • date: date

    • Enum: discrete value (from an enumerable). See details in the next section

    • float: float (Note that to reduce memory usage, float are stored on 32 bits using NumPy’s float32)

    • int: integer

    • str: string

  • An entity defines who or what group the variable concerns, e.g. individuals, households, and families.

  • The definition_period defines the period on which the variable is calculated. It can be MONTH (e.g. salary), YEAR (e.g. income taxes), or ETERNITY (e.g. date of birth).

  • The label is a human-friendly way to describe the variable.

  • The reference is a list of relevant legislative references for a variable (usually URLs the text of the law or another trustworthy source).

The formula

  • def formula(person, period): declares the formula that will be used to calculate the flat_tax_on_salary for a given person at a given period. Because definition_period = MONTH the period is constrained to be a month.

  • salary = person('salary', period) calculates the salary of the person, for the given month. This will, of course, work only if salary is another variable in the tax and benefit system.

  • return salary * 0.25 returns the result for the given period.

  • Dated Formulas have a start and/or an end date.

Testing a formula

To make sure that the formula you have just written works the way you expect, you have to test it. Tests about the legislation are written in a YAML syntax. The flat_tax_on_salary formula can for instance be tested with the following test file:

- name: "Flax tax on salary - No income"
  period: 2017-01
  input:
    salary: 0
  output:
    flat_tax_on_salary: 0

- name: "Flax tax on salary - With income"
  period: 2017-01
  input:
    salary: 2000
  output:
    flat_tax_on_salary: 500

You can check the YAML tests documentation to learn more about how to write YAML tests, and how to run them.

Example with legislation parameters

To access a common legislation parameter, a third parameter can be added to the function signature. The previous formulas could thus be rewritten as:

class flat_tax_on_salary(Variable):
    value_type = float
    entity = Person
    label = u"Individualized and monthly paid tax on salaries"
    definition_period = MONTH

    def formula(person, period, parameters):
        salary = person('salary', period)

        return salary * parameters(period).taxes.salary.rate

The parameters is a function that can be called for a given period that returns the whole legislation parameters (in a hierarchical tree structure). You can access the specific parameter you are interested in by navigating the tree structure with the . notation.