Step 20: NTA Full Generational Accounts

Overview

At this step we add the optional module NtaFullGenAccounts.mpp for the calculation of Full Generational Accounts (FGAs) as suggested by Lee et.al. (2017).

The new NtaFullGenAccounts.mpp Module

This module introduces Full Generational Accounts (FGAs) as suggested by Lee et.al. 2017 in: Full Generational Accounts: What Do We Give to the Next Generation?



////////////////////////////////////////////////////////////////////////////////////////////////////
// Parameters
////////////////////////////////////////////////////////////////////////////////////////////////////

parameters
{
    double  FgaEconomicGrowth;                                  //EN Economic growth
    double  FgaDiscountFactor;                                  //EN Discount factor
    model_generated double mgFgaUprateFactor[SIM_YEAR_RANGE];   //EN Uprate factor

    //EN Discount factor for present value at birth
    model_generated double mgFgaDeflationFactor[AGE_RANGE];

    //EN Discount factor for present value 2010
    model_generated double mgFgaDeflation2010[SIM_YEAR_RANGE];

    //EN Discount factor for present value 2040
    model_generated double mgFgaDeflation2040[SIM_YEAR_RANGE];
};

parameter_group PG_FGA                                          //EN Full Generational Accounts
{
    FgaEconomicGrowth, FgaDiscountFactor
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Actor Person
////////////////////////////////////////////////////////////////////////////////////////////////////

actor Person
{
    // Age in tables
    AGE_RANGE age_2010 = COERCE(AGE_RANGE,2010 - year_of_birth);        //EN Age
    AGE_RANGE age_2011 = COERCE(AGE_RANGE,2011 - year_of_birth);        //EN Age
    AGE_RANGE age_2040 = COERCE(AGE_RANGE,2040 - year_of_birth);        //EN Age


    real fga_YL = base_YL * mgFgaUprateFactor[RANGE_POS(SIM_YEAR_RANGE,calendar_year)];
    real fga_TF = (base_TFB + base_TFW) * mgFgaUprateFactor[RANGE_POS(SIM_YEAR_RANGE,calendar_year)];
    real fga_TGI = (base_TGSOAI + base_TGXCI + base_TGXII + base_TGEI +  base_TGHI)
        * mgFgaUprateFactor[RANGE_POS(SIM_YEAR_RANGE,calendar_year)];
    real fga_TGO = base_TGO * mgFgaUprateFactor[RANGE_POS(SIM_YEAR_RANGE,calendar_year)];
    real fga_TF_adj = (fga_TF > 0.0) ? fga_TF * lGlobals->adj_factor_TFI
        : fga_TF * lGlobals->adj_factor_TFO;
    real fga_TGI_adj = fga_TGI * lGlobals->adj_factor_TGI;
    real fga_TGO_adj = fga_TGO * lGlobals->adj_factor_TGO;

    real deflation_factor = mgFgaDeflationFactor[integer_age];

    // PV Age 0

    real fga_YL_defl = deflation_factor * fga_YL;
    real fga_YL_pv = weighted_duration(fga_YL_defl);

    real fga_TF_defl = deflation_factor * fga_TF;
    real fga_TF_pv = weighted_duration(fga_TF_defl);

    real fga_TGI_defl = deflation_factor * fga_TGI;
    real fga_TGI_pv = weighted_duration(fga_TGI_defl);

    real fga_TGO_defl = deflation_factor * fga_TGO;
    real fga_TGO_pv = weighted_duration(fga_TGO_defl);

    real fga_TF_adj_defl = deflation_factor * fga_TF_adj;
    real fga_TF_adj_pv = weighted_duration(fga_TF_adj_defl);

    real fga_TGI_adj_defl = deflation_factor * fga_TGI_adj;
    real fga_TGI_adj_pv = weighted_duration(fga_TGI_adj_defl);

    real fga_TGO_adj_defl = deflation_factor * fga_TGO_adj;
    real fga_TGO_adj_pv = weighted_duration(fga_TGO_adj_defl);

    // PV 2010 (only transfers 2010+)

    real deflation_2010 = (calendar_year >= MIN(SIM_YEAR_RANGE)) ?
        mgFgaDeflation2010[RANGE_POS(SIM_YEAR_RANGE,calendar_year)] : 0.0;

    real fga_YL_defl_2010 = deflation_2010 * fga_YL;
    real fga_YL_pv_2010 = weighted_duration(fga_YL_defl_2010);

    real fga_TF_defl_2010 = deflation_2010 * fga_TF;
    real fga_TF_pv_2010 = weighted_duration(fga_TF_defl_2010);

    real fga_TGI_defl_2010 = deflation_2010 * fga_TGI;
    real fga_TGI_pv_2010 = weighted_duration(fga_TGI_defl_2010);

    real fga_TGO_defl_2010 = deflation_2010 * fga_TGO;
    real fga_TGO_pv_2010 = weighted_duration(fga_TGO_defl_2010);

    real fga_TF_adj_defl_2010 = deflation_2010 * fga_TF_adj;
    real fga_TF_adj_pv_2010 = weighted_duration(fga_TF_adj_defl_2010);

    real fga_TGI_adj_defl_2010 = deflation_2010 * fga_TGI_adj;
    real fga_TGI_adj_pv_2010 = weighted_duration(fga_TGI_adj_defl_2010);

    real fga_TGO_adj_defl_2010 = deflation_2010 * fga_TGO_adj;
    real fga_TGO_adj_pv_2010 = weighted_duration(fga_TGO_adj_defl_2010);

     // PV 2040 (only transfers 2040+)

    real deflation_2040 = (calendar_year >= 2040) ?
        mgFgaDeflation2040[RANGE_POS(SIM_YEAR_RANGE,calendar_year)] : 0.0;

    real fga_YL_defl_2040 = deflation_2040 * fga_YL;
    real fga_YL_pv_2040 = weighted_duration(fga_YL_defl_2040);

    real fga_TF_defl_2040 = deflation_2040 * fga_TF;
    real fga_TF_pv_2040 = weighted_duration(fga_TF_defl_2040);

    real fga_TGI_defl_2040 = deflation_2040 * fga_TGI;
    real fga_TGI_pv_2040 = weighted_duration(fga_TGI_defl_2040);

    real fga_TGO_defl_2040 = deflation_2040 * fga_TGO;
    real fga_TGO_pv_2040 = weighted_duration(fga_TGO_defl_2040);

    real fga_TF_adj_defl_2040 = deflation_2040 * fga_TF_adj;
    real fga_TF_adj_pv_2040 = weighted_duration(fga_TF_adj_defl_2040);

    real fga_TGI_adj_defl_2040 = deflation_2040 * fga_TGI_adj;
    real fga_TGI_adj_pv_2040 = weighted_duration(fga_TGI_adj_defl_2040);

    real fga_TGO_adj_defl_2040 = deflation_2040 * fga_TGO_adj;
    real fga_TGO_adj_pv_2040 = weighted_duration(fga_TGO_adj_defl_2040);
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Actor Globals
////////////////////////////////////////////////////////////////////////////////////////////////////

actor Globals
{
    real adj_factor_TFI = {1.0};
    real adj_factor_TFO = {1.0};
    real adj_factor_TGI = {1.0};
    real adj_factor_TGO = {1.0};
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Actor State
////////////////////////////////////////////////////////////////////////////////////////////////////

actor State
{
    TIME time_update_fga = { 0.0 };                         //EN Time of next FGA udjustment update
    event timeUpdateFgaAdjustEvent, UpdateFgaAdjustEvent;   //EN FGA adjustment update event
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////////////////////////////////////////////////////////

TIME State::timeUpdateFgaAdjustEvent()
{
    if (time_update_fga < MIN(SIM_YEAR_RANGE)) return MIN(SIM_YEAR_RANGE) + 0.5;
    else return time_update_fga;
}

void State::UpdateFgaAdjustEvent()
{
    // Population size
    long nPersons = asAllResidents->Count();

    double dTotalTFI = 0.0;
    double dTotalTFO = 0.0;
    double dTotalTGI = 0.0;
    double dTotalTGO = 0.0;
    double dAverage;

    // Loop adding individual NTAs
    for (long nI = 0; nI < nPersons; nI++)
    {
        auto prPerson = asAllResidents->Item(nI);
        if (prPerson->fga_TF > 0.0) dTotalTFI = dTotalTFI + prPerson->fga_TF;
        else dTotalTFO = dTotalTFO - prPerson->fga_TF;
        dTotalTGI = dTotalTGI + prPerson->fga_TGI;
        dTotalTGO = dTotalTGO + prPerson->fga_TGO;
    }
    // Adjust TG
    dAverage = (dTotalTGI + dTotalTGO) / 2.0;
    lStateToGlobals->adj_factor_TGI = dAverage / dTotalTGI;
    lStateToGlobals->adj_factor_TGO = dAverage / dTotalTGO;

    // Adjust TF
    dAverage = (dTotalTFI + dTotalTFO) / 2.0;
    lStateToGlobals->adj_factor_TFI = dAverage / dTotalTFI;
    lStateToGlobals->adj_factor_TFO = dAverage / dTotalTFO;

    // Program next update event
    time_update_fga = WAIT(1.0);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Pre-Simulation
////////////////////////////////////////////////////////////////////////////////////////////////////

void PreSimulation()
{
    for (int nJ = 0; nJ < SIZE(SIM_YEAR_RANGE); nJ++)
    {
        mgFgaUprateFactor[nJ] = 1.0 * pow((1.0 + FgaEconomicGrowth), nJ);
    }

    for (int nJ = 0; nJ < SIZE(AGE_RANGE); nJ++)
    {
        mgFgaDeflationFactor[nJ] = 1.0 * pow((1.0 / (1.0 + FgaDiscountFactor)), nJ);
    }

    for (int nJ = 0; nJ < SIZE(SIM_YEAR_RANGE); nJ++)
    {
        if (MIN(SIM_YEAR_RANGE) + nJ >= 2010) mgFgaDeflation2010[nJ] = 1.0
            * pow((1.0 / (1.0 + FgaDiscountFactor)), 2010-MIN(SIM_YEAR_RANGE)+nJ);
        else mgFgaDeflation2010[nJ] = 0.0;
    }

    for (int nJ = 0; nJ < SIZE(SIM_YEAR_RANGE); nJ++)
    {
        if (MIN(SIM_YEAR_RANGE) + nJ >= 2040) mgFgaDeflation2040[nJ] = 1.0
            * pow((1.0 / (1.0 + FgaDiscountFactor)), 2040-MIN(SIM_YEAR_RANGE)+nJ);
        else mgFgaDeflation2040[nJ] = 0.0;
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Tables
////////////////////////////////////////////////////////////////////////////////////////////////////

table_group TG_FullGenerationalAccounts             //EN NTA Full Generational Accounts
{
    tabFgaUnadjustedTotals, tabFgaPV,
    tabAdjustmentFga,
    tabFgaPV_2010, tabFgaPV_2040
};

table Person tabFgaUnadjustedTotals                 //EN FGA Totals
[is_resident && in_projected_time]
{
    {
        weighted_duration(fga_YL),                  //EN YL total
        weighted_duration(fga_TF),                  //EN TF total
        weighted_duration(fga_TGI),                 //EN TGI total
        weighted_duration(fga_TGO),                 //EN TGO total
        weighted_duration(fga_TF_adj),              //EN TF total adjusted
        weighted_duration(fga_TGI_adj),             //EN TGI total adjusted
        weighted_duration(fga_TGO_adj)              //EN TGO total adjusted
    }
    * sim_year
};

table Person tabFgaPV                               //EN FGA PV
[is_resident && person_type == PT_CHILD
&& trigger_transitions(is_alive,TRUE,FALSE)]
{
    educ_fate+ *
    {
        value_in(fga_YL_pv) / unit,                 //EN Present Value YL at birth
        value_in(fga_TF_pv) / unit,                 //EN Present Value TF at birth
        value_in(fga_TGI_pv) / unit,                //EN Present Value TGI at birth
        value_in(fga_TGO_pv) / unit,                //EN Present Value TGO at birth
        value_in(fga_TF_adj_pv) / unit,             //EN Present Value TF adjusted at birth
        value_in(fga_TGI_adj_pv) / unit,            //EN Present Value TGI adjsuted at birth
        value_in(fga_TGO_adj_pv) / unit             //EN Present Value TGO adjusted at birth
    }
    * year_of_birth
};


table Globals tabAdjustmentFga                      //EN FGA Adjustment factors
[globals_in_projected_time]
{
    {
        max_value_in(adj_factor_TFI),               //EN Adjustment TFI decimals=3
        max_value_in(adj_factor_TFO),               //EN Adjustment TFO decimals=3
        max_value_in(adj_factor_TGI),               //EN Adjustment TGI decimals=3
        max_value_in(adj_factor_TGO)                //EN Adjustment TGO decimals=3
    }
    * global_tab_sim_year
};



table Person tabFgaPV_2010                          //EN FGA PV 2010
[is_resident && person_type != PT_IMMIGRANT
&& trigger_transitions(is_alive,TRUE,FALSE)
&& year_of_birth <= 2010]
{
    educ_fate+ *
    {
        value_in(fga_YL_pv_2010) / unit,            //EN Present Value YL 2010
        value_in(fga_TF_pv_2010) / unit,            //EN Present Value TF 2010
        value_in(fga_TGI_pv_2010) / unit,           //EN Present Value TGI 2010
        value_in(fga_TGO_pv_2010) / unit,           //EN Present Value TGO 2010
        value_in(fga_TF_adj_pv_2010) / unit,        //EN Present Value TF adjusted 2010
        value_in(fga_TGI_adj_pv_2010) / unit,       //EN Present Value TGI adjusted 2010
        value_in(fga_TGO_adj_pv_2010) / unit        //EN Present Value TGO adjusted 2010
    }
    * age_2010
};


table Person tabFgaPV_2011                          //EN FGA PV 2011
[is_resident && person_type != PT_IMMIGRANT
&& trigger_transitions(is_alive,TRUE,FALSE)
&& year_of_birth <= 2011]
{
    educ_fate+ *
    {
        value_in(fga_YL_pv_2010) / unit,            //EN Present Value YL 2010
        value_in(fga_TF_pv_2010) / unit,            //EN Present Value TF 2010
        value_in(fga_TGI_pv_2010) / unit,           //EN Present Value TGI 2010
        value_in(fga_TGO_pv_2010) / unit,           //EN Present Value TGO 2010
        value_in(fga_TF_adj_pv_2010) / unit,        //EN Present Value TF adjusted 2010
        value_in(fga_TGI_adj_pv_2010) / unit,       //EN Present Value TGI adjusted 2010
        value_in(fga_TGO_adj_pv_2010) / unit        //EN Present Value TGO adjusted 2010
    }
    * age_2011
};

table Person tabFgaPV_2040                          //EN FGA PV 2040
[is_resident && person_type != PT_IMMIGRANT
&& trigger_transitions(is_alive,TRUE,FALSE)
&& year_of_birth <= 2040]
{
    educ_fate+ *
    {
        value_in(fga_YL_pv_2040) / unit,            //EN Present Value YL 2040
        value_in(fga_TF_pv_2040) / unit,            //EN Present Value TF 2040
        value_in(fga_TGI_pv_2040) / unit,           //EN Present Value TGI 2040
        value_in(fga_TGO_pv_2040) / unit,           //EN Present Value TGO 2040
        value_in(fga_TF_adj_pv_2040) / unit,        //EN Present Value TF adjusted 2040
        value_in(fga_TGI_adj_pv_2040) / unit,       //EN Present Value TGI adjusted 2040
        value_in(fga_TGO_adj_pv_2040) / unit        //EN Present Value TGO adjusted 2040
    }
    * age_2040
};