Openfisca handles the fact that the legislation changes over time.
Many legislation parameters are regularly re-evaluated while the variables using them stay the same.
Example: thetaxes
parameter can change without altering the code of theflat_tax_on_salary
variable that uses that parameter.
In that case, add the new parameter values and their start dates in the appropriate parameter files.
taxes:
salary:
rate:
description: Rate for the flat tax on salaries
values:
2016-01-01:
value: 0.25
reference: https://www.legislation-source.com/2016
2015-01-01:
value: 0.20
reference: https://www.legislation-source.com/2015
taxes:
salary:
rate:
description: Rate for the flat tax on salaries
values:
2017-01-01:
value: 0.3
reference: https://www.legislation-source.com/2017
2016-01-01:
value: 0.25
reference: https://www.legislation-source.com/2016
2015-01-01:
value: 0.2
reference: https://www.legislation-source.com/2015
After this change, in a formula:
parameters('2016-04').taxes.salary.rate
is 0.25
parameters('2017-01').taxes.salary.rate
is 0.3
parameters('2022-01').taxes.salary.rate
is 0.3
Some fiscal or benefit mechanism significantly evolve over time and call for a change in the formula that computes them. In this case, a simple parameter adjustement is not enough.
For instance, let’s assume that from the 1st of Jan. 2017, the flat_tax_on_salary
is not applied anymore on the first 1000
earned by a person.
We implement this rule by adding a new formula to our variable, and dating it:
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_2017(person, period, parameters):
salary = person('salary', period)
salary_above_1000 = min_(salary - 1000, 0)
return salary_above_1000 * parameters(period).taxes.salary.rate
def formula(person, period, parameters):
salary = person('salary', period)
return salary * parameters(period).taxes.salary.rate
If the flat_tax_on_salary
is calculated for a person before the 31st of Dec. 2016 (included), formula
is used. If it is called after the 1st of Jan 2017 (included), formula_2017
is used.
Formula naming rules:
formula
.formula_2017_01_01
is active from the 1st of Jan. 2017.formula_2017
is equivalent to formula_2017_01_01
.0001-01-01
, as Python does not handle B.C. dates).formula
is active on 2010
.end
date is reached, as we’ll see further down in the Variable end section).formula
is active until 2016-12-31
(included). On the day after, 2017-01-01
, formula_2017
becomes active, and formula
becomes inactive.In our previous example, we assumed that flat_tax_on_salary
had always had a formula, since the dawn of time. This is a reasonable hypothesis if we are only interested in running computations for recent years.
But most fiscal and benefit mechanisms have been introduced at some point. Let’s for instance assume that our flat_tax_on_salary
only appeared in our legislation on the 1st of June 2005.
This is easily implemented by dating the two formulas:
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_2017(person, period, parameters):
salary = person('salary', period)
salary_above_1000 = min_(salary - 1000, 0)
return salary_above_1000 * parameters(period).taxes.salary.rate
def formula_2005_06(person, period, parameters):
salary = person('salary', period)
return salary * parameters(period).taxes.salary.rate
Only a few characters changed in comparison with the last example: the suffix _2005_06
has been added to the second formula name.
Note that if flat_tax_on_salary
is calculated before 2005-05-31
(included), none of the two formulas is used, as they are both inactive at this time. Instead, the variable default value is returned.
As the legislation evolves, some fiscal or benefit mechanisms disapear.
Let’s for instance assume that a progressive_income_tax
used to exist before the flat_tax_on_salary
was introduced. This progressive tax then disapeared on the 1st of June 2005.
This is implemented with an end
attribute that define the last day a variable can be calculated:
class progressive_income_tax(Variable):
value_type = float
entity = Person
label = u"Former tax replaced by the flat tax on the 1st of June 2005"
definition_period = MONTH
end = '2005-05-31'
def formula(person, period, legislation):
# Apply a marginal scale to the person's income
...
If progressive_income_tax
is called before 2005-05-31
(included), formula
will be used.
However, if progressive_income_tax
is calculated after 2005-06-01
(included), formula
is not used, as it is not active anymore at this time. Instead, the variable default value is returned.
Note that:
end
day is inclusive: it is the last day a variable and its formulas are active (and not the first day it is not active anymore).end
value is a string of format YYYY-MM-DD
where YYYY
, MM
and DD
are respectively a year, month and day.