This generates a complete two-dimensional budget constraints for some unit (person, benefit-unit, household, etc.) for some tax-benefit system. That is, a list points describing the combinations of net income that the unit would get for different values of gross income (or hours worked, wages, etc.).
See: Duncan, Alan, and Graham Stark. "A Recursive Algorithm to Generate Piecewise Linear Budget Contraints" IFS Working Paper 2000/01 May 2, 2000] https://doi.org/10.1920/wp.ifs.2000.0011.
Here is a live example of this algorithm in action.
Define a function that returns the net income for some gross value - this could be (e.g.) hours worked, wage, or gross income, and some set of data (details of a person, tax paramters, etc):
function getnet( data::Dict, gross :: Real ) :: Real
The call to
makebc then generates the budget constraint using
getnet. If successful this returns a BudgetConstraint array, which is a collection of
x,y points describing all the points where the budget constraint has a change of slope, where
x is the gross value and
y the net.
The routine is controlled by a
BCSettings struct; there is a
DEFAULT_SETTINGS constant version of this which I suggest you don't change, apart from perhaps the upper and lower x-bounds of the graph.
The tolerances here generally work quite well.
settings for the calclation. Calculate over
A budget constraint is then just an ordered list of points.
This takes a budget constraint and produces a named tuple of METRs and Tax Credits for each one. (really just 1 minus the slope and the intercept at that point). Useful for annotating graphs and tables.
Attempt to remove near duplicate points and ensure all points ordered in ascending gross income.
A reverse lookup. E.g given some net income
y what would the corresponding gross
x have to have been?
Make a budget constraint using function
getnet to extract net incomes and
settings (see above on this struct).
data should hold whatever your
getnet function needs (parameters, a househols, etc.)
getnet should be a function of the form
net=f(data, gross). See the testcase for an example.
Covert a list of points into x an y vectors. Some plotters may need this.
a line between 2 points; used internally
A point; in our case y is net income (or something) and x gross.
- the tolerance isn't used consistently (see
- I may be misunderstanding abstract types in the declarations;
- possibly use some definition of point, line, etc. from some standard package.