"""
This module will define the forward and simulate behavior of the Godley-Lavoie 2006 PC model.
"""
__author__ = ["Karl Naumann-Woleske"]
__credits__ = ["Karl Naumann-Woleske"]
__license__ = "MIT"
__maintainer__ = ["Karl Naumann-Woleske"]
import logging
import torch
from macrostat.core.behavior import Behavior
from macrostat.models.GL06PC.parameters import ParametersGL06PC
from macrostat.models.GL06PC.scenarios import ScenariosGL06PC
from macrostat.models.GL06PC.variables import VariablesGL06PC
logger = logging.getLogger(__name__)
[docs]
class BehaviorGL06PC(Behavior):
"""Behavior class for the Godley-Lavoie 2006 PC model."""
version = "GL06PC"
def __init__(
self,
parameters: ParametersGL06PC | None = None,
scenarios: ScenariosGL06PC | None = None,
variables: VariablesGL06PC | None = None,
scenario: int = 0,
debug: bool = False,
):
"""Initialize the behavior of the Godley-Lavoie 2006 SIM model.
Parameters
----------
parameters: ParametersGL06PC | None
The parameters of the model.
scenarios: ScenariosGL06PC | None
The scenarios of the model.
variables: VariablesGL06PC | None
The variables of the model.
record: bool
Whether to record the model output.
scenario: int
The scenario to use for the model.
"""
if parameters is None:
parameters = ParametersGL06PC()
if scenarios is None:
scenarios = ScenariosGL06PC()
if variables is None:
variables = VariablesGL06PC()
super().__init__(
parameters=parameters,
scenarios=scenarios,
variables=variables,
scenario=scenario,
debug=debug,
)
[docs]
def initialize(self):
r"""Initialize the behavior of the Godley-Lavoie 2006 PC model.
Within the book the initialization is generally to set all non-scenario
variables to zero. Accordingly
Equations
---------
.. math::
:nowrap:
\begin{align}
C(0) &= 0 \\
G(0) &= 0 \\
Y(0) &= 0 \\
T(0) &= 0 \\
YD(0) &= 0 \\
V(0) &= 0 \\
H_s(0) &= 0 \\
H_h(0) &= 0 \\
B_h(0) &= 0 \\
B_s(0) &= 0 \\
B_{CB}(0) &= 0 \\
r(0) &= 0 \\
\end{align}
Dependency
----------
Sets
-----
- ConsumptionHousehold
- ConsumptionGovernment
- NationalIncome
- InterestEarnedOnBillsHousehold
- InterestEarnedOnBillsCentralBank
- CentralBankProfits
- Taxes
- HouseholdMoneyStock
- CentralBankMoneyStock
- HouseholdBillStock
- GovernmentBillStock
- CentralBankBillStock
- Wealth
- InterestRate
- DisposableIncome
"""
self.state["ConsumptionHousehold"] = torch.zeros(1)
self.state["ConsumptionGovernment"] = torch.zeros(1)
self.state["NationalIncome"] = torch.zeros(1)
self.state["InterestEarnedOnBillsHousehold"] = torch.zeros(1)
self.state["InterestEarnedOnBillsCentralBank"] = torch.zeros(1)
self.state["CentralBankProfits"] = torch.zeros(1)
self.state["Taxes"] = torch.zeros(1)
self.state["HouseholdMoneyStock"] = torch.zeros(1)
self.state["CentralBankMoneyStock"] = torch.zeros(1)
self.state["HouseholdBillStock"] = torch.zeros(1)
self.state["GovernmentBillStock"] = torch.zeros(1)
self.state["CentralBankBillStock"] = torch.zeros(1)
self.state["Wealth"] = torch.zeros(1)
self.state["InterestRate"] = torch.zeros(1)
self.state["DisposableIncome"] = torch.zeros(1)
[docs]
def step(self, t: int, scenario: dict):
"""Step function of the Godley-Lavoie 2006 PC model."""
# Scenario items
self.consumption_government(t, scenario)
self.set_interest_rate(t, scenario)
# Items based on prior
self.interest_earned_on_bills_household(t, scenario)
self.interest_earned_on_bills_central_bank(t, scenario)
# Solution of the step
self.national_income(t, scenario)
self.taxes(t, scenario)
self.disposable_income(t, scenario)
self.consumption(t, scenario)
self.wealth(t, scenario)
self.household_bill_holdings(t, scenario)
self.household_money_stock(t, scenario)
self.central_bank_profits(t, scenario)
self.government_bill_issuance(t, scenario)
self.central_bank_bill_holdings(t, scenario)
self.central_bank_money_stock(t, scenario)
[docs]
def consumption_government(self, t: int, scenario: dict):
r"""Calculate the consumption of the government. This is
given exogenously by the scenario.
Parameters
----------
t: int
The time step.
scenario: dict
The scenario.
Dependency
----------
- scenario: ConsumptionGovernment
Sets
-----
- ConsumptionGovernment
"""
self.state["ConsumptionGovernment"] = scenario["GovernmentDemand"]
[docs]
def set_interest_rate(self, t: int, scenario: dict):
r"""Set the interest rate. This is given exogenously by the scenario.
Parameters
----------
t: int
The time step.
scenario: dict
The scenario.
Dependency
----------
- scenario: InterestRate
Sets
-----
- InterestRate
"""
self.state["InterestRate"] = scenario["InterestRate"]
[docs]
def interest_earned_on_bills_household(self, t: int, scenario: dict):
r"""Calculate the interest earned on bills by the household.
Parameters
----------
t: int
The time step.
scenario: dict
The scenario.
Equations
---------
.. math::
:nowrap:
\begin{align}
r(t-1)B_h(t-1)
\end{align}
Dependency
----------
- prior: InterestRate
- prior: HouseholdBillStock
Sets
-----
- InterestEarnedOnBillsHousehold
"""
self.state["InterestEarnedOnBillsHousehold"] = (
self.prior["InterestRate"] * self.prior["HouseholdBillStock"]
)
[docs]
def interest_earned_on_bills_central_bank(self, t: int, scenario: dict):
r"""Calculate the interest earned on bills by the central bank.
Parameters
----------
t: int
The time step.
scenario: dict
The scenario.
Equations
---------
.. math::
:nowrap:
\begin{align}
r(t-1)B_{CB}(t-1)
\end{align}
Dependency
----------
- prior: InterestRate
- prior: CentralBankBillStock
Sets
-----
- InterestEarnedOnBillsCentralBank
"""
self.state["InterestEarnedOnBillsCentralBank"] = (
self.prior["InterestRate"] * self.prior["CentralBankBillStock"]
)
[docs]
def national_income(self, t: int, scenario: dict):
r"""Calculate the national income based on the closed-form solution derived in the documentation.
The closed-form solution is used to avoid the need to solve the system of equations iteratively, thus
preserving the differentiability of the model trajectory.
Parameters
----------
t: int
The time step.
scenario: dict
The scenario.
Equations
---------
.. math::
:nowrap:
\begin{align}
Y(t) = \frac{\alpha_1(1-\theta)r(t-1)B_h(t-1) + \alpha_2 V(t-1) + G(t)}{1 - \alpha_1(1-\theta)}
\end{align}
Dependency
----------
- state: InterestEarnedOnBillsHousehold
- state: ConsumptionGovernment
- prior: Wealth
Sets
-----
- NationalIncome
"""
self.state["NationalIncome"] = (
# Spending out of bond income
self.params["PropensityToConsumeIncome"]
* (1 - self.params["TaxRate"])
* self.state["InterestEarnedOnBillsHousehold"]
# Spending out of wealth
+ self.params["PropensityToConsumeSavings"] * self.prior["Wealth"]
# Government spending
+ self.state["ConsumptionGovernment"]
) / (
# Multiplier
1
- self.params["PropensityToConsumeIncome"] * (1 - self.params["TaxRate"])
)
[docs]
def taxes(self, t: int, scenario: dict):
r"""Calculate the taxes.
Parameters
----------
t: int
The time step.
scenario: dict
The scenario.
Equations
---------
.. math::
:nowrap:
\begin{align}
T(t) = \theta (Y(t) + r(t-1)B_h(t-1))
\end{align}
Dependency
----------
- state: NationalIncome
- state: InterestEarnedOnBillsHousehold
Sets
-----
- Taxes
"""
self.state["Taxes"] = self.params["TaxRate"] * (
self.state["NationalIncome"] + self.state["InterestEarnedOnBillsHousehold"]
)
[docs]
def disposable_income(self, t: int, scenario: dict):
r"""Calculate the disposable income.
Parameters
----------
t: int
The time step.
scenario: dict
The scenario.
Equations
---------
.. math::
:nowrap:
\begin{align}
YD(t) = Y(t) - T(t) + r(t-1)B_h(t-1)
\end{align}
Dependency
----------
- state: NationalIncome
- state: Taxes
- state: InterestEarnedOnBillsHousehold
Sets
-----
- DisposableIncome
"""
self.state["DisposableIncome"] = (
self.state["NationalIncome"]
- self.state["Taxes"]
+ self.state["InterestEarnedOnBillsHousehold"]
)
[docs]
def consumption(self, t: int, scenario: dict):
r"""Calculate the consumption.
Parameters
----------
t: int
The time step.
scenario: dict
The scenario.
Equations
---------
.. math::
:nowrap:
\begin{align}
C(t) = \alpha_1 YD(t) + \alpha_2 V(t-1)
\end{align}
Dependency
----------
- state: DisposableIncome
- prior: Wealth
Sets
-----
- ConsumptionHousehold
"""
self.state["ConsumptionHousehold"] = (
self.params["PropensityToConsumeIncome"] * self.state["DisposableIncome"]
+ self.params["PropensityToConsumeSavings"] * self.prior["Wealth"]
)
[docs]
def wealth(self, t: int, scenario: dict):
r"""Calculate the wealth.
Parameters
----------
t: int
The time step.
scenario: dict
The scenario.
Equations
---------
.. math::
:nowrap:
\begin{align}
V(t) = V(t-1) + YD(t) - C(t)
\end{align}
Dependency
----------
- state: DisposableIncome
- state: ConsumptionHousehold
- prior: Wealth
Sets
-----
- Wealth
"""
self.state["Wealth"] = (
self.prior["Wealth"]
+ self.state["DisposableIncome"]
- self.state["ConsumptionHousehold"]
)
[docs]
def household_bill_holdings(self, t: int, scenario: dict):
r"""Calculate the household bill holdings.
Parameters
----------
t: int
The time step.
scenario: dict
The scenario.
Equations
---------
.. math::
:nowrap:
\begin{align}
\frac{B_h(t)}{V(t)} = \lambda_0 + \lambda_1 r(t) - \lambda_2 \frac{YD(t)}{V(t)}
\end{align}
Dependency
----------
- state: DisposableIncome
- state: Wealth
- state: InterestRate
Sets
-----
- HouseholdBillStock
"""
self.state["HouseholdBillStock"] = self.state["Wealth"] * (
# Baseline share
self.params["WealthShareBills_Constant"]
# Interest rate effect
+ self.params["WealthShareBills_InterestRate"] * self.state["InterestRate"]
# Income-to-wealth ratio effect
- self.params["WealthShareBills_Income"]
* self.state["DisposableIncome"]
/ self.state["Wealth"]
)
[docs]
def household_money_stock(self, t: int, scenario: dict):
r"""Calculate the household deposits as a residual.
Parameters
----------
t: int
The time step.
scenario: dict
The scenario.
Equations
---------
.. math::
:nowrap:
\begin{align}
H_h(t) = V(t) - B_h(t)
\end{align}
Dependency
----------
- state: Wealth
- state: HouseholdBillStock
Sets
-----
- HouseholdMoneyStock
"""
self.state["HouseholdMoneyStock"] = (
self.state["Wealth"] - self.state["HouseholdBillStock"]
)
[docs]
def central_bank_profits(self, t: int, scenario: dict):
r"""Calculate the central bank profits (income on bills held).
Parameters
----------
t: int
The time step.
scenario: dict
The scenario.
Equations
---------
.. math::
:nowrap:
\begin{align}
r(t-1)B_{CB}(t-1)
\end{align}
Dependency
----------
- prior: InterestRate
- prior: CentralBankBillStock
Sets
-----
- CentralBankProfits
"""
self.state["CentralBankProfits"] = (
self.prior["InterestRate"] * self.prior["CentralBankBillStock"]
)
[docs]
def government_bill_issuance(self, t: int, scenario: dict):
r"""Calculate the government bill issuance.
Parameters
----------
t: int
The time step.
scenario: dict
The scenario.
Equations
---------
.. math::
:nowrap:
\begin{align}
B_s(t) = B_s(t-1) + (G(t) - r(t-1)B_s(t-1)) - (T(t) + r(t-1)B_{CB}(t-1))
\end{align}
Dependency
----------
- prior: GovernmentBillStock
- state: GovernmentDemand
- state: Taxes
- state: CentralBankProfits
- state: InterestEarnedOnBillsCentralBank
Sets
-----
- GovernmentBillStock
"""
self.state["GovernmentBillStock"] = (
self.prior["GovernmentBillStock"]
+ (
# Government demand
scenario["GovernmentDemand"]
# Interest expense on bills issued
+ self.prior["InterestRate"] * self.prior["GovernmentBillStock"]
)
- (
# Tax revenue
self.state["Taxes"]
# Central bank profits
+ self.state["CentralBankProfits"]
)
)
[docs]
def central_bank_bill_holdings(self, t: int, scenario: dict):
r"""Calculate the central bank bill holdings.
Parameters
----------
t: int
The time step.
scenario: dict
The scenario.
Equations
---------
.. math::
:nowrap:
\begin{align}
B_{CB}(t) = B_{s}(t) - B_{h}(t)
\end{align}
Dependency
----------
- state: GovernmentBillStock
- state: HouseholdBillStock
Sets
-----
- CentralBankBillStock
"""
self.state["CentralBankBillStock"] = (
self.state["GovernmentBillStock"] - self.state["HouseholdBillStock"]
)
[docs]
def central_bank_money_stock(self, t: int, scenario: dict):
r"""Calculate the central bank money stock.
Parameters
----------
t: int
The time step.
scenario: dict
The scenario.
Equations
---------
.. math::
:nowrap:
\begin{align}
H_{s}(t) = H_{s}(t-1) + (B_{CB}(t) - B_{CB}(t-1))
\end{align}
Dependency
----------
- state: CentralBankBillStock
- prior: CentralBankMoneyStock
- prior: CentralBankBillStock
Sets
-----
- CentralBankMoneyStock
"""
self.state["CentralBankMoneyStock"] = (
self.prior["CentralBankMoneyStock"]
+ self.state["CentralBankBillStock"]
- self.prior["CentralBankBillStock"]
)