Skip to content

Commit

Permalink
Merge pull request #880 from PolicyEngine/fix/879-private-school-vat
Browse files Browse the repository at this point in the history
Implement private school VAT
  • Loading branch information
nikhilwoodruff authored Jun 28, 2024
2 parents f75f829 + 34d0408 commit 539fb51
Show file tree
Hide file tree
Showing 12 changed files with 231 additions and 4 deletions.
4 changes: 4 additions & 0 deletions changelog_entry.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- bump: patch
changes:
added:
- Private school VAT calculation
40 changes: 36 additions & 4 deletions policyengine_uk/data/datasets/frs/enhanced_frs.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from ..utils import STORAGE_FOLDER
from .frs import FRS_2019_20
from .calibration.calibrated_frs import CalibratedSPIEnhancedPooledFRS_2019_21
from .stacked_frs import StackedFRS
import yaml
import copy

Expand Down Expand Up @@ -137,10 +138,41 @@ def generate(self):
self.save_dataset(data)


EnhancedFRS = ImputationExtendedFRS.from_dataset(
ImputedCalibratedFRS = ImputationExtendedFRS.from_dataset(
CalibratedSPIEnhancedPooledFRS_2019_21,
"enhanced_frs",
"Enhanced FRS",
"imputed_calibrated_frs",
"Imputed-Calibrated FRS",
new_num_years=7,
new_url="release://policyengine/non-public-microdata/uk-2024-march-efo/enhanced_frs.h5",
)


class EnhancedFRS(Dataset):
name = "enhanced_frs"
label = "Enhanced FRS"
file_path = STORAGE_FOLDER / "enhanced_frs.h5"
data_format = Dataset.TIME_PERIOD_ARRAYS
num_years = 7
time_period = 2021
count_copies = 4
url = "release://policyengine/non-public-microdata/uk-2024-march-efo/enhanced_frs.h5"

def generate(self):
from policyengine_uk.tools.stack_datasets import stack_datasets

data = ImputedCalibratedFRS().load_dataset()

copies = []
for _ in range(self.count_copies):
copies.append(copy.deepcopy(data))

for time_period in data["household_weight"]:
original_weights = data["household_weight"][time_period].copy()
for dataset in [data] + copies:
dataset["household_weight"][time_period] = original_weights / (
self.count_copies + 1
)

for dataset in copies:
data = stack_datasets(data, dataset)

self.save_dataset(data)
Binary file modified policyengine_uk/data/gov/enhanced_frs_brmas.csv.gz
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
description: Total number of private school students
value:
2015-01-01: 583_029
2016-01-01: 583_268
2017-01-01: 581_873
2018-01-01: 580_480
2019-01-01: 576_857
2020-01-01: 569_366
2021-01-01: 581_427
2022-01-01: 591_954
2023-01-01: 593_486
metadata:
unit: person
label: total number of private school students
reference:
- title: School characteristics for Academy, Independent, Independent school, LA Maintained, Non-maintained special school and 5 other filters in England between 2015/16 and 2023/24
href: https://explore-education-statistics.service.gov.uk/data-tables/fast-track/27e148e3-2581-4bc3-b0bc-08dc6f35f09f
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
description: VAT rate applied to private schools.
values:
2000-01-01: 0
metadata:
unit: /1
label: private school VAT rate
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
description: Rate at which households enroll children in private schools, by percentile.
0:
2000-01-01: 0
5:
2000-01-01: 0.025
10:
2000-01-01: 0.0125
15:
2000-01-01: 0.01
20:
2000-01-01: 0.005
25:
2000-01-01: 0.008
30:
2000-01-01: 0.01
35:
2000-01-01: 0.015
40:
2000-01-01: 0.01
45:
2000-01-01: 0.0175
50:
2000-01-01: 0.025
55:
2000-01-01: 0.0175
60:
2000-01-01: 0.0175
65:
2000-01-01: 0.025
70:
2000-01-01: 0.03
75:
2000-01-01: 0.025
80:
2000-01-01: 0.05
85:
2000-01-01: 0.06
90:
2000-01-01: 0.0875
95:
2000-01-01: 0.13
100:
2000-01-01: 0.47
metadata:
unit: /1
label: percentage of students in private school, by household net income percentile
reference:
- title: Income, housing wealth, and private school access in Britain
href: https://www.tandfonline.com/doi/full/10.1080/09645292.2021.1874878
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
description: Mean annual private school fee
values:
2022-01-01: 15_200
metadata:
unit: currency-GBP
label: mean annual private school fee
reference:
- title: Tax, private school fees and state school spending
href: https://ifs.org.uk/publications/tax-private-school-fees-and-state-school-spending
uprating: calibration.uprating.CPI
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
description: Effective percentage of private school tuition subject to VAT
# Per IFS article
# (https://ifs.org.uk/publications/tax-private-school-fees-and-state-school-spending),
# about 25% of private school costs would be
# effectively VAT-free
values:
0000-01-01: 0.75
metadata:
unit: /1
label: private school tuition VAT basis
reference:
- title: Tax, private school fees and state school spending
href: https://ifs.org.uk/publications/tax-private-school-fees-and-state-school-spending
1 change: 1 addition & 0 deletions policyengine_uk/reforms/policyengine/budget_change.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ class household_tax(Variable):
"capital_gains_tax",
"corporate_incident_tax_revenue_change",
"consumer_incident_tax_revenue_change",
"private_school_vat",
]

def formula(household, period, parameters):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
age: 35
household_gross_income: 0
is_household_head: true
household_weight: 1
output:
poverty_gap_bhc: 220 * 52
in_poverty_bhc: true
Expand Down
93 changes: 93 additions & 0 deletions policyengine_uk/variables/contrib/labour/private_school_vat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
from policyengine_uk.model_api import *
from policyengine_uk.variables.gov.hmrc.tax import household_tax


class attends_private_school(Variable):
label = "attends private school"
entity = Person
definition_period = YEAR
value_type = bool

def formula(person, period, parameters):
household = person.household
# To ensure that our model matches
# total number of students actually enrolled

ps_vat_params = parameters(period).gov.simulation.private_school_vat
private_school_attendance_rate = (
ps_vat_params.private_school_attendance_rate
)

person = household.members

is_child = person("is_child", period)

taxes = household.sum(
person("income_tax", period) + person("national_insurance", period)
)

net_income = (
household("household_market_income", period)
+ household("household_benefits", period)
- taxes
)

household_weight = household("household_weight", period)
weighted_income = MicroSeries(net_income, weights=household_weight)
percentile = (
weighted_income.percentile_rank()
.clip(0, 100)
.values.astype(numpy.int64)
)
STUDENT_POPULATION_ADJUSTMENT_FACTOR = 1.1

p_attends_private_school = (
np.array(
[
interpolate_percentile(private_school_attendance_rate, p)
for p in percentile
]
)
* STUDENT_POPULATION_ADJUSTMENT_FACTOR
* is_child
)

return random(person) < p_attends_private_school


class private_school_vat(Variable):
label = "private school VAT"
entity = Household
definition_period = YEAR
value_type = float
unit = "currency-GBP"

def formula(household, period, parameters):
num_children = add(household, period, ["attends_private_school"])

ps_vat_params = parameters(period).gov.simulation.private_school_vat
private_school_vat_basis = ps_vat_params.private_school_vat_basis
avg_yearly_private_school_cost = ps_vat_params.private_school_fees

private_school_vat_rate = parameters(
period
).gov.contrib.labour.private_school_vat

return (
num_children
* avg_yearly_private_school_cost
* private_school_vat_rate
* private_school_vat_basis
)


def interpolate_percentile(param, percentile):
if str(percentile) in param:
return param[str(percentile)]
else:
idx = percentile - (percentile % 5)
p1 = idx
p2 = idx + 5
v1 = param[str(idx)]
v2 = param[str(idx + 5)]
return v1 + (v2 - v1) * (percentile - p1) / (p2 - p1)
1 change: 1 addition & 0 deletions policyengine_uk/variables/gov/hmrc/tax.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class household_tax(Variable):
"carbon_tax",
"vat_change",
"capital_gains_tax",
"private_school_vat",
]

def formula(household, period, parameters):
Expand Down

0 comments on commit 539fb51

Please sign in to comment.