diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb..8515e2ff7 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,7 @@ +- bump: minor + changes: + added: + - Firm dataset support with 3 new entities (firm, sector, business_group) + - 16 firm variables for business microdata analysis + - UKFirmSingleYearDataset class for firm data handling + - FIRM_2023_24 dataset constant for firm_2023_24.h5 integration \ No newline at end of file diff --git a/policyengine_uk/__init__.py b/policyengine_uk/__init__.py index 727ce05c5..2b1d6fd51 100644 --- a/policyengine_uk/__init__.py +++ b/policyengine_uk/__init__.py @@ -6,6 +6,7 @@ CountryTaxBenefitSystem, Microsimulation, Simulation, + FirmSimulation, COUNTRY_DIR, parameters, variables, diff --git a/policyengine_uk/data/__init__.py b/policyengine_uk/data/__init__.py index 905fb1306..9ee80a30a 100644 --- a/policyengine_uk/data/__init__.py +++ b/policyengine_uk/data/__init__.py @@ -2,3 +2,6 @@ UKMultiYearDataset, UKSingleYearDataset, ) +from policyengine_uk.data.firm_dataset_schema import ( + UKFirmSingleYearDataset, +) diff --git a/policyengine_uk/data/firm_dataset_schema.py b/policyengine_uk/data/firm_dataset_schema.py new file mode 100644 index 000000000..e3684707f --- /dev/null +++ b/policyengine_uk/data/firm_dataset_schema.py @@ -0,0 +1,138 @@ +import pandas as pd +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from policyengine_uk import Microsimulation + +from pathlib import Path +import h5py + + +class UKFirmSingleYearDataset: + firm: pd.DataFrame + sector: pd.DataFrame + business_group: pd.DataFrame + + @staticmethod + def validate_file_path(file_path: str, raise_exception: bool = True): + if not file_path.endswith(".h5"): + if raise_exception: + raise ValueError( + "File path must end with '.h5' for UKFirmDataset." + ) + return False + if not Path(file_path).exists(): + if raise_exception: + raise FileNotFoundError(f"File not found: {file_path}") + return False + + # Check if the file contains time_period, firm, sector, and business_group datasets + with h5py.File(file_path, "r") as f: + required_datasets = [ + "time_period", + "firm", + "sector", + "business_group", + ] + for dataset in required_datasets: + if dataset not in f: + if raise_exception: + raise ValueError( + f"Dataset '{dataset}' not found in the file: {file_path}" + ) + else: + return False + + return True + + def __init__( + self, + file_path: str = None, + firm: pd.DataFrame = None, + sector: pd.DataFrame = None, + business_group: pd.DataFrame = None, + fiscal_year: int = 2025, + ): + file_path = str(file_path) if file_path else None + if file_path is not None: + self.validate_file_path(file_path) + with pd.HDFStore(file_path) as f: + self.firm = f["firm"] + self.sector = f["sector"] + self.business_group = f["business_group"] + self.time_period = str(f["time_period"].iloc[0]) + else: + if firm is None or sector is None or business_group is None: + raise ValueError( + "Must provide either a file path or all three DataFrames (firm, sector, business_group)." + ) + self.firm = firm + self.sector = sector + self.business_group = business_group + self.time_period = str(fiscal_year) + + self.data_format = "arrays" + self.tables = (self.firm, self.sector, self.business_group) + self.table_names = ("firm", "sector", "business_group") + + def save(self, file_path: str): + with pd.HDFStore(file_path) as f: + f.put("firm", self.firm, format="table", data_columns=True) + f.put("sector", self.sector, format="table", data_columns=True) + f.put( + "business_group", + self.business_group, + format="table", + data_columns=True, + ) + f.put("time_period", pd.Series([self.time_period]), format="table") + + def load(self): + data = {} + for df in (self.firm, self.sector, self.business_group): + for col in df.columns: + data[col] = df[col].values + + return data + + def copy(self): + return UKFirmSingleYearDataset( + firm=self.firm.copy(), + sector=self.sector.copy(), + business_group=self.business_group.copy(), + fiscal_year=self.time_period, + ) + + def validate(self): + # Check for NaNs in the tables + for df in self.tables: + for col in df.columns: + if df[col].isna().any(): + raise ValueError(f"Column '{col}' contains NaN values.") + + @staticmethod + def from_simulation( + simulation: "Microsimulation", fiscal_year: int = 2025 + ): + entity_dfs = {} + + for entity in ["firm", "sector", "business_group"]: + input_variables = [ + variable + for variable in simulation.input_variables + if simulation.tax_benefit_system.variables[variable].entity.key + == entity + ] + if len(input_variables) == 0: + entity_dfs[entity] = pd.DataFrame() + else: + entity_dfs[entity] = simulation.calculate_dataframe( + input_variables, period=fiscal_year + ) + + return UKFirmSingleYearDataset( + firm=entity_dfs["firm"], + sector=entity_dfs["sector"], + business_group=entity_dfs["business_group"], + fiscal_year=fiscal_year, + ) diff --git a/policyengine_uk/entities.py b/policyengine_uk/entities.py index d83ee53b2..3130fa68e 100644 --- a/policyengine_uk/entities.py +++ b/policyengine_uk/entities.py @@ -43,4 +43,42 @@ is_person=True, ) -entities = [Household, BenUnit, Person] +Firm = build_entity( + key="firm", + plural="firms", + label="Firm", + doc="A business entity with employees and operations.", + is_person=True, +) + +Sector = build_entity( + key="sector", + plural="sectors", + label="Sector", + doc="An economic sector containing multiple firms.", + roles=[ + { + "key": "member", + "plural": "members", + "label": "Member", + "doc": "A sector in the business classification.", + } + ], +) + +BusinessGroup = build_entity( + key="business_group", + plural="business_groups", + label="Business Group", + doc="A business group containing multiple firms.", + roles=[ + { + "key": "member", + "plural": "members", + "label": "Member", + "doc": "A business group in the firm dataset.", + } + ], +) + +entities = [Household, BenUnit, Person, Firm, Sector, BusinessGroup] diff --git a/policyengine_uk/firm_simulation.py b/policyengine_uk/firm_simulation.py new file mode 100644 index 000000000..b30a6ba83 --- /dev/null +++ b/policyengine_uk/firm_simulation.py @@ -0,0 +1,135 @@ +"""Firm-specific simulation class for business microdata analysis.""" + +from typing import Dict, Optional, Union, List +import numpy as np +import pandas as pd + +from policyengine_core.simulations.simulation import Simulation +from policyengine_uk.data.firm_dataset_schema import UKFirmSingleYearDataset +from policyengine_uk.firm_tax_benefit_system import FirmTaxBenefitSystem + + +class FirmSimulation(Simulation): + """Firm-specific simulation class for business microdata. + + This simulation handles firm, sector, and business_group entities + for business-level policy analysis. + """ + + default_input_period: int = 2025 + default_calculation_period: int = 2025 + + def __init__( + self, + dataset: Optional[Union[UKFirmSingleYearDataset, str]] = None, + reform: Optional[Dict] = None, + trace: bool = False, + ): + """Initialize a firm simulation. + + Args: + dataset: Firm dataset or path to firm dataset + reform: Optional reform to apply + trace: Whether to enable tracing + """ + # Initialize firm tax benefit system + tax_benefit_system = FirmTaxBenefitSystem() + + if reform is not None: + # Apply reform to the tax benefit system if needed + pass + + # Build populations from dataset + if isinstance(dataset, str): + dataset = UKFirmSingleYearDataset(file_path=dataset) + elif dataset is None: + raise ValueError("FirmSimulation requires a firm dataset") + elif not isinstance(dataset, UKFirmSingleYearDataset): + raise ValueError(f"Unsupported dataset type: {dataset.__class__}") + + # Create populations using the dataset + from policyengine_core.simulations.simulation_builder import ( + SimulationBuilder, + ) + + builder = SimulationBuilder() + builder.populations = tax_benefit_system.instantiate_entities() + + # Declare entities + builder.declare_person_entity("firm", dataset.firm.firm_id.values) + builder.declare_entity("sector", dataset.sector.sector_id.values) + builder.declare_entity( + "business_group", dataset.business_group.business_group_id.values + ) + + # Link firms to sectors and business groups + builder.join_with_persons( + builder.populations["sector"], + dataset.firm.firm_sector_id.values, + np.array(["member"] * len(dataset.firm)), + ) + builder.join_with_persons( + builder.populations["business_group"], + dataset.firm.firm_business_group_id.values, + np.array(["member"] * len(dataset.firm)), + ) + + # Initialize the parent Simulation with populations + super().__init__( + tax_benefit_system=tax_benefit_system, + populations=builder.populations, + ) + + # Set up tracing if requested + if trace: + self.trace = True + + # Load variable values from dataset + for table in dataset.tables: + for variable in table.columns: + if variable not in self.tax_benefit_system.variables: + continue + self.set_input( + variable, dataset.time_period, table[variable].values + ) + + self.dataset = dataset + self.input_variables = self.get_known_variables() + + def get_known_variables(self) -> List[str]: + """Get list of variables with known values. + + Returns: + List of variable names that have values set + """ + known = [] + for variable in self.tax_benefit_system.variables: + try: + if len(self.get_holder(variable).get_known_periods()) > 0: + known.append(variable) + except: + pass + return known + + def calculate_dataframe( + self, + variable_names: List[str], + period: Optional[int] = None, + ) -> pd.DataFrame: + """Calculate multiple variables and return as DataFrame. + + Args: + variable_names: List of variables to calculate + period: Time period for calculation + + Returns: + DataFrame with calculated values + """ + if period is None: + period = self.default_calculation_period + + data = {} + for variable in variable_names: + data[variable] = self.calculate(variable, period) + + return pd.DataFrame(data) diff --git a/policyengine_uk/firm_tax_benefit_system.py b/policyengine_uk/firm_tax_benefit_system.py new file mode 100644 index 000000000..2dc3024d7 --- /dev/null +++ b/policyengine_uk/firm_tax_benefit_system.py @@ -0,0 +1,60 @@ +"""Firm-specific tax benefit system for business microdata.""" + +import copy +from pathlib import Path +from typing import Any, Dict + +from policyengine_core.taxbenefitsystems import TaxBenefitSystem +from policyengine_uk.entities import Firm, Sector, BusinessGroup +from policyengine_uk.utils.parameters import backdate_parameters + +# Module constants +COUNTRY_DIR = Path(__file__).parent + + +class FirmTaxBenefitSystem(TaxBenefitSystem): + """Firm-specific tax and benefit system for business microdata. + + This system handles firm, sector, and business_group entities + for business-level analysis. + """ + + def __init__(self): + """Initialize the firm tax-benefit system with business entities.""" + self._parameters_at_instant_cache: Dict[str, Any] = {} + self.variables = {} + + # Create copies of entity classes to avoid modifying originals + firm, sector, business_group = ( + copy.copy(Firm), + copy.copy(Sector), + copy.copy(BusinessGroup), + ) + + # Set up entities + self.entities = [firm, sector, business_group] + self.person_entity = ( + firm # Firm is the "person" entity for this system + ) + self.group_entities = [sector, business_group] + self.group_entity_keys = [entity.key for entity in self.group_entities] + + # Link entities to this tax-benefit system + for entity in self.entities: + entity.set_tax_benefit_system(self) + + self.variable_module_metadata = {} + + # Add firm variables from separate directory + variables_firm_directory = COUNTRY_DIR / "variables_firm" + self.add_variables_from_directory(variables_firm_directory) + + # Add parameters (if needed for firm calculations) + parameters_directory = COUNTRY_DIR / "parameters" + if parameters_directory.exists(): + self.load_parameters(str(parameters_directory)) + backdate_parameters(self.parameters) + + def reset_parameter_caches(self): + """Reset parameter caches (compatibility method).""" + self._parameters_at_instant_cache = {} diff --git a/policyengine_uk/parameters/gov/hmrc/vat/deregistration_threshold.yaml b/policyengine_uk/parameters/gov/hmrc/vat/deregistration_threshold.yaml new file mode 100644 index 000000000..6c09fa672 --- /dev/null +++ b/policyengine_uk/parameters/gov/hmrc/vat/deregistration_threshold.yaml @@ -0,0 +1,9 @@ +description: The United Kingdom requires firms to remain registered for Value Added Tax if their taxable turnover exceeds this amount. +values: + 2017-04-01: 83_000 + 2024-04-01: 88_000 +metadata: + unit: currency-GBP + reference: + - title: HMRC VAT registration thresholds + href: https://www.gov.uk/vat-registration-thresholds \ No newline at end of file diff --git a/policyengine_uk/parameters/gov/hmrc/vat/registration_threshold.yaml b/policyengine_uk/parameters/gov/hmrc/vat/registration_threshold.yaml new file mode 100644 index 000000000..49aab5cc9 --- /dev/null +++ b/policyengine_uk/parameters/gov/hmrc/vat/registration_threshold.yaml @@ -0,0 +1,9 @@ +description: The United Kingdom requires firms to register for Value Added Tax when their taxable turnover exceeds this amount. +values: + 2017-04-01: 85_000 + 2024-04-01: 90_000 +metadata: + unit: currency-GBP + reference: + - title: HMRC VAT registration thresholds + href: https://www.gov.uk/vat-registration-thresholds \ No newline at end of file diff --git a/policyengine_uk/simulation.py b/policyengine_uk/simulation.py index e2537d54b..d1aac5316 100644 --- a/policyengine_uk/simulation.py +++ b/policyengine_uk/simulation.py @@ -108,7 +108,9 @@ def __init__( # Universal Credit reform (July 2025). Needs closer integration in the baseline, # but adding here for ease of toggling on/off via the 'active' parameter. - from policyengine_uk.scenarios import universal_credit_july_2025_reform + from policyengine_uk.scenarios import ( + universal_credit_july_2025_reform, + ) universal_credit_july_2025_reform.simulation_modifier(self) diff --git a/policyengine_uk/system.py b/policyengine_uk/system.py index 5d926165a..e43123f0b 100644 --- a/policyengine_uk/system.py +++ b/policyengine_uk/system.py @@ -1,3 +1,4 @@ from .tax_benefit_system import * from .simulation import * from .microsimulation import * +from .firm_simulation import FirmSimulation diff --git a/policyengine_uk/tax_benefit_system.py b/policyengine_uk/tax_benefit_system.py index e76cddbd9..02b8da8f3 100644 --- a/policyengine_uk/tax_benefit_system.py +++ b/policyengine_uk/tax_benefit_system.py @@ -14,7 +14,14 @@ from policyengine_core.variables import Variable # PolicyEngine UK imports -from policyengine_uk.entities import BenUnit, Household, Person +from policyengine_uk.entities import ( + BenUnit, + Household, + Person, + Firm, + Sector, + BusinessGroup, +) from policyengine_uk.parameters.gov.contrib.create_private_pension_uprating import ( add_private_pension_uprating_factor, ) @@ -38,6 +45,7 @@ # Module constants COUNTRY_DIR = Path(__file__).parent ENHANCED_FRS = "hf://policyengine/policyengine-uk-data/enhanced_frs_2023_24.h5" +FIRM_2023_24 = "hf://policyengine/policyengine-uk-data/firm_2023_24.h5" class CountryTaxBenefitSystem(TaxBenefitSystem): @@ -115,7 +123,11 @@ def __init__(self): ) # Set up entities - self.entities = [person, benunit, household] + self.entities = [ + person, + benunit, + household, + ] self.person_entity = person self.group_entities = [benunit, household] self.group_entity_keys = [entity.key for entity in self.group_entities] diff --git a/policyengine_uk/variables_firm/gov/hmrc/vat/firm_net_vat_liability.py b/policyengine_uk/variables_firm/gov/hmrc/vat/firm_net_vat_liability.py new file mode 100644 index 000000000..39a0a15d0 --- /dev/null +++ b/policyengine_uk/variables_firm/gov/hmrc/vat/firm_net_vat_liability.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * +from policyengine_uk.entities import Firm + + +class firm_net_vat_liability(Variable): + value_type = float + entity = Firm + label = "Net VAT liability" + definition_period = YEAR + unit = GBP + documentation = "Net VAT liability (output VAT minus input VAT)" + + def formula(firm, period, parameters): + output_vat = firm("firm_vat_on_sales", period) + input_vat = firm("firm_vat_on_purchases", period) + + return output_vat - input_vat diff --git a/policyengine_uk/variables_firm/gov/hmrc/vat/firm_reduced_rated_supplies.py b/policyengine_uk/variables_firm/gov/hmrc/vat/firm_reduced_rated_supplies.py new file mode 100644 index 000000000..50cbf18e5 --- /dev/null +++ b/policyengine_uk/variables_firm/gov/hmrc/vat/firm_reduced_rated_supplies.py @@ -0,0 +1,11 @@ +from policyengine_uk.model_api import * +from policyengine_uk.entities import Firm + + +class firm_reduced_rated_supplies(Variable): + value_type = float + entity = Firm + label = "Reduced-rated supplies" + definition_period = YEAR + unit = GBP + documentation = "Value of supplies subject to reduced VAT rate (5%)" diff --git a/policyengine_uk/variables_firm/gov/hmrc/vat/firm_standard_rated_supplies.py b/policyengine_uk/variables_firm/gov/hmrc/vat/firm_standard_rated_supplies.py new file mode 100644 index 000000000..c2b7eeee0 --- /dev/null +++ b/policyengine_uk/variables_firm/gov/hmrc/vat/firm_standard_rated_supplies.py @@ -0,0 +1,11 @@ +from policyengine_uk.model_api import * +from policyengine_uk.entities import Firm + + +class firm_standard_rated_supplies(Variable): + value_type = float + entity = Firm + label = "Standard-rated supplies" + definition_period = YEAR + unit = GBP + documentation = "Value of supplies subject to standard VAT rate (20%)" diff --git a/policyengine_uk/variables_firm/gov/hmrc/vat/firm_vat_liability_calculated.py b/policyengine_uk/variables_firm/gov/hmrc/vat/firm_vat_liability_calculated.py new file mode 100644 index 000000000..2e5b4c5ed --- /dev/null +++ b/policyengine_uk/variables_firm/gov/hmrc/vat/firm_vat_liability_calculated.py @@ -0,0 +1,16 @@ +from policyengine_uk.model_api import * +from policyengine_uk.entities import Firm + + +class firm_vat_liability_calculated(Variable): + value_type = float + entity = Firm + label = "Calculated VAT liability" + definition_period = YEAR + unit = GBP + documentation = "Calculated VAT liability based on supplies and parameters" + + def formula(firm, period, parameters): + # This calculates VAT based on supplies and rates + # Compare with vat_liability_k from the dataset + return firm("firm_net_vat_liability", period) diff --git a/policyengine_uk/variables_firm/gov/hmrc/vat/firm_vat_on_purchases.py b/policyengine_uk/variables_firm/gov/hmrc/vat/firm_vat_on_purchases.py new file mode 100644 index 000000000..c4e5dbc77 --- /dev/null +++ b/policyengine_uk/variables_firm/gov/hmrc/vat/firm_vat_on_purchases.py @@ -0,0 +1,11 @@ +from policyengine_uk.model_api import * +from policyengine_uk.entities import Firm + + +class firm_vat_on_purchases(Variable): + value_type = float + entity = Firm + label = "VAT on purchases" + definition_period = YEAR + unit = GBP + documentation = "Total VAT paid on firm's purchases (input VAT)" diff --git a/policyengine_uk/variables_firm/gov/hmrc/vat/firm_vat_on_sales.py b/policyengine_uk/variables_firm/gov/hmrc/vat/firm_vat_on_sales.py new file mode 100644 index 000000000..43bbc1fe6 --- /dev/null +++ b/policyengine_uk/variables_firm/gov/hmrc/vat/firm_vat_on_sales.py @@ -0,0 +1,26 @@ +from policyengine_uk.model_api import * +from policyengine_uk.entities import Firm + + +class firm_vat_on_sales(Variable): + value_type = float + entity = Firm + label = "VAT on sales" + definition_period = YEAR + unit = GBP + documentation = "Total VAT charged on firm's sales (output VAT)" + + def formula(firm, period, parameters): + # Only calculate for VAT registered firms + registered = firm("firm_vat_registered", period) + + p = parameters(period).gov.hmrc.vat + + standard_supplies = firm("firm_standard_rated_supplies", period) + reduced_supplies = firm("firm_reduced_rated_supplies", period) + + standard_vat = standard_supplies * p.standard_rate + reduced_vat = reduced_supplies * p.reduced_rate + # Zero-rated supplies have 0% VAT by definition + + return where(registered, standard_vat + reduced_vat, 0) diff --git a/policyengine_uk/variables_firm/gov/hmrc/vat/firm_vat_registered.py b/policyengine_uk/variables_firm/gov/hmrc/vat/firm_vat_registered.py new file mode 100644 index 000000000..a9c4e9d7f --- /dev/null +++ b/policyengine_uk/variables_firm/gov/hmrc/vat/firm_vat_registered.py @@ -0,0 +1,20 @@ +from policyengine_uk.model_api import * +from policyengine_uk.entities import Firm + + +class firm_vat_registered(Variable): + value_type = bool + entity = Firm + label = "VAT registered" + definition_period = YEAR + documentation = ( + "Whether the firm is registered for VAT based on turnover threshold" + ) + + def formula(firm, period, parameters): + # Use annual_turnover_k from our existing firm variables + # Convert from thousands to pounds + turnover = firm("annual_turnover_k", period) * 1000 + threshold = parameters(period).gov.hmrc.vat.registration_threshold + + return turnover > threshold diff --git a/policyengine_uk/variables_firm/gov/hmrc/vat/firm_zero_rated_supplies.py b/policyengine_uk/variables_firm/gov/hmrc/vat/firm_zero_rated_supplies.py new file mode 100644 index 000000000..f07844303 --- /dev/null +++ b/policyengine_uk/variables_firm/gov/hmrc/vat/firm_zero_rated_supplies.py @@ -0,0 +1,11 @@ +from policyengine_uk.model_api import * +from policyengine_uk.entities import Firm + + +class firm_zero_rated_supplies(Variable): + value_type = float + entity = Firm + label = "Zero-rated supplies" + definition_period = YEAR + unit = GBP + documentation = "Value of supplies subject to zero VAT rate (0%)" diff --git a/policyengine_uk/variables_firm/input/business_group.py b/policyengine_uk/variables_firm/input/business_group.py new file mode 100644 index 000000000..3da3d77ed --- /dev/null +++ b/policyengine_uk/variables_firm/input/business_group.py @@ -0,0 +1,13 @@ +from policyengine_uk.model_api import * + +label = "Business Group" +description = "Business group variables." + + +class business_group_id(Variable): + value_type = int + entity = BusinessGroup + label = "business group ID" + documentation = "Unique identifier for each business group" + definition_period = YEAR + quantity_type = STOCK diff --git a/policyengine_uk/variables_firm/input/firm.py b/policyengine_uk/variables_firm/input/firm.py new file mode 100644 index 000000000..221de3a7a --- /dev/null +++ b/policyengine_uk/variables_firm/input/firm.py @@ -0,0 +1,133 @@ +from policyengine_uk.model_api import * + +label = "Firm" +description = "Business firm variables from firm dataset." + + +class firm_id(Variable): + value_type = int + entity = Firm + label = "firm ID" + documentation = "Unique identifier for each firm" + definition_period = YEAR + quantity_type = STOCK + + +class firm_sector_id(Variable): + value_type = int + entity = Firm + label = "firm sector ID" + documentation = "Identifier linking firm to its sector" + definition_period = YEAR + quantity_type = STOCK + + +class firm_business_group_id(Variable): + value_type = int + entity = Firm + label = "firm business group ID" + documentation = "Identifier linking firm to its business group" + definition_period = YEAR + quantity_type = STOCK + + +class year(Variable): + value_type = int + entity = Firm + label = "year" + documentation = "Year of the data" + definition_period = YEAR + quantity_type = STOCK + + +class firm_weight(Variable): + value_type = float + entity = Firm + label = "firm weight" + documentation = "Statistical weight for firm in population" + definition_period = YEAR + quantity_type = STOCK + + +class sic_code(Variable): + value_type = str + entity = Firm + label = "SIC code" + documentation = "Standard Industrial Classification code" + definition_period = YEAR + quantity_type = STOCK + + +class annual_turnover_k(Variable): + value_type = float + entity = Firm + label = "annual turnover (thousands)" + documentation = "Annual turnover in thousands of pounds" + definition_period = YEAR + unit = GBP + quantity_type = FLOW + + +class annual_input_k(Variable): + value_type = float + entity = Firm + label = "annual input (thousands)" + documentation = "Annual input costs in thousands of pounds" + definition_period = YEAR + unit = GBP + quantity_type = FLOW + + +class vat_liability_k(Variable): + value_type = float + entity = Firm + label = "VAT liability (thousands)" + documentation = "VAT liability in thousands of pounds" + definition_period = YEAR + unit = GBP + quantity_type = FLOW + + +class employment(Variable): + value_type = int + entity = Firm + label = "employment" + documentation = "Number of employees" + definition_period = YEAR + quantity_type = STOCK + + +class vat_registered(Variable): + value_type = bool + entity = Firm + label = "VAT registered" + documentation = "Whether the firm is registered for VAT" + definition_period = YEAR + quantity_type = STOCK + + +class hmrc_band(Variable): + value_type = str + entity = Firm + label = "HMRC band" + documentation = "HMRC size band classification" + definition_period = YEAR + quantity_type = STOCK + + +class employment_band(Variable): + value_type = str + entity = Firm + label = "employment band" + documentation = "Employment size band classification" + definition_period = YEAR + quantity_type = STOCK + + +class sic_numeric(Variable): + value_type = int + entity = Firm + label = "SIC numeric" + documentation = "Numeric version of SIC code" + definition_period = YEAR + quantity_type = STOCK diff --git a/policyengine_uk/variables_firm/input/sector.py b/policyengine_uk/variables_firm/input/sector.py new file mode 100644 index 000000000..e33a7678a --- /dev/null +++ b/policyengine_uk/variables_firm/input/sector.py @@ -0,0 +1,13 @@ +from policyengine_uk.model_api import * + +label = "Sector" +description = "Economic sector variables." + + +class sector_id(Variable): + value_type = int + entity = Sector + label = "sector ID" + documentation = "Unique identifier for each sector" + definition_period = YEAR + quantity_type = STOCK