ABMPC
Agent-Based Portfolio Choice (ABMPC) is an interpretation of the second sectoral system described by G&L. View the model accounting.
The model sees Household agents make a portfolio choice between non-interest bearing (high-powered cash) money and interest bearing bills akin to Government treasury bills. The interest rate offered will affect the composition of a Household agent's asset portfolio. That is, the proportion of interest-bearing assets to cash money a Household will decide to hold.
The Portfolio Decision
Mirroring Godley & Lavoie (G&L) pp 103 - 105.
Households make a two stage decision. In the first step, households decide how much they will save out of their income. In the second step, households decide how they will allocate their wealth, including their newly acquired wealth. The two decisions are made within the same model iteration. However, the two decisions are distinct and of a hierarchical form. The consumption decision determines the size of the end of period stock of wealth; the portfolio decision determines the allocation of the stock of wealth.
How is wealth allocated between money and bonds? Two traditions have prevailed. One related to the quantity theory of money, links money balances to the flow of income and the other, of more recent vintage, makes money balances some proportion of total wealth. The latter is related to the Keynesian notion of liquidity preference. The lower is liquidity preference, the lower is the money to wealth ratio.
The transactions demand for money and the liquidity preference story may both be comprised within a single model. Households wish to hold a certain proportion λ0 of their wealth in the form of interest-bearing bills, and hence, because there is no third asset, a proportion equal to (1 - λ0) in the form of money. This proportion, however, is modulated by two elements, the rate of return on Treasury bills and the level of disposable income relative to wealth.
Wealth Allocation Function
The allocation function PropIntBills incorporates an interpretation of G&L's Brainard-Tobin formula, slightly amended. ABMPC can run with multiple producers and households. In this system, household agents may face period(s) of unemployment with no knowledge of when they may be employed once again. If unemployed, an agent's disposable income will fall, leading (probably) to the denominator in the wealth to income calculation becoming immediately smaller than the numerator; blowing up G&L's interpretation of Brainard-Tobin. Therefore, if unemployed, a household agent will adjust its allocation of interest-bearing assets to money deposits based on a wealth to system average income calculation.
"""
See Godley & Lavoie, Monetary Economics, p104.
Serves a model run with either one producer and one household agent, or multiple agents,
with household agents facing the possibility of unemployment.
"""
# Utility: Catch divide by zero error.
def zero_division(n, d):
return n / d if d else 0
# The proportion of wealth a household agent will allocate to interest-bearing bills:
def PropIntBills(employed, Bhd, V, YD, YD_average, last_rb, rb):
agent_employed = employed
prop_bills_last = Bhd # (t-1)
wealth = V
disposable_income = YD
average_disposable_income = YD_average # System average disp income.
int_rate_last = last_rb # (t-1)
int_rate = rb
rb_change = (zero_division(int_rate - int_rate_last, int_rate_last) * 100)
wealth_income_ratio = zero_division(wealth, disposable_income)
wealth_average_income_ratio = zero_division(wealth, average_disposable_income)
if agent_employed:
# Approximating the Brainard-Tobin formula, slightly amended.
# See Godley & Lavoie, Monetary Economics, p104.
prop_bills = (((wealth * (1 - wealth_income_ratio))
+ (prop_bills_last
* (1 + (rb_change / 100))))
* wealth_income_ratio)
else:
# Portfolio decision during a period of unemployment.
prop_bills = ((wealth * wealth_average_income_ratio) * (1 + (rb_change / 100)))
# Limit maximum prop wealth going to interest-bearing bills to whole of wealth.
if prop_bills < wealth:
prop_bills_this = prop_bills
else:
prop_bills_this = wealth
return prop_bills_this
Test Output
Visit the shareable Hugging Face space, abmpc-test, to view the test output of agent-based portfolio choice.
Energy Use
An Environment agent sets the scene for a simplistic interpretation of the energy requirements of the system, specifically, the energy required by Producer agents in ABMPC. The code summary details the properties and actions behind stock and flow energy sources, as well as the cumulative negative externality returned.
ABMPC Environment Agent
class Environment(mesa.Agent):
"""The Environment agent."""
def __init__(self, unique_id, model):
super().__init__(unique_id, model)
self.breed = "Environment"
self.model_current_step = 0 # Model run step.
# See https://en.wikipedia.org/wiki/Names_of_large_numbers
# (10^21) One sextillion units of available (stock) fossil hydrocarbon energy.
self.units_stock_energy = Decimal(1000_000_000_000_000_000_000)
# Stock energy geopolitics:
# The 'ase' relates to the availability of stock (fossil hydrocarbon) energy.
# A number; from least to most available: 0.01 >= 'ase' <= 1.0.
self.availability_stock_energy = Decimal(1)
# Environment (Negative Externality):
self.cumulative_negative_externality = Decimal(0) # Use of stock energy.
# 3% of stock energy is environmental negative externality.
self.cumulative_negative_externality_rate = Decimal(0.03)
self.flow_energy_base = Decimal(5) # Start with an amount of renewable energy (units).
self.units_flow_energy = Decimal(0) # Units of available (stored) renewable energy.
def step(self):
"""
Functions (each and every step):
1. Add newly generated (renewable) energy.
"""
# See https://www.statista.com/outlook/io/energy/renewable-energy/worldwide
growth_flow_energy = Decimal(0.0388) # 3.88%
self.units_flow_energy += self.flow_energy_base # Add newly generated (renewable / flow) energy.
self.flow_energy_base = (self.flow_energy_base + (self.flow_energy_base
* growth_flow_energy))
ABMPC Producer Agent - Energy
class Producer(mesa.Agent):
"""A Producer agent."""
def __init__(self, unique_id, model):
super().__init__(unique_id, model)
self.breed = "Producer"
# Energy use
self.flow_energy_used = Decimal(0)
self.stock_energy_used = Decimal(0)
def step(self):
"""
Producer Functions (each and every step):
1 Choose and employ a household agent.
2 Connect with the Environment and account for government and household consumption demands.
3 Communicate to employed household agents their wage this step.
"""
#1
household = self.employ_household_process()
household.is_employed = True # Employ the chosen household.
#2
environment = self.model.get_agents_of_type(Environment)[0] # The Environment.
government_supplied_expenditure = Decimal(0)
household_supplied_expenditure = Decimal(0)
government_supplied_expenditure = self.government_expenditure_supplied # A wage includes services supplied to government (Gs) in response to government demands.
household_supplied_expenditure = self.consumption_goods_supplied # A wage includes services supplied to households (Cs) in response to household demands.
"""
Calculate energy required to provide the service and stock polution returned.
"""
# One monetary unit of demands will require one unit of energy to fulfil.
# Energy required based on combined (monetary) government agent and consumer agents desires.
total_energy_required = (government_supplied_expenditure + household_supplied_expenditure)
energy_shortfall = 0
# Opening energy flows.
opening_flow_energy = environment.units_flow_energy # To calculate flows of 'flow' (renewable) energy.
opening_stock_energy = (environment.units_stock_energy * environment.availability_stock_energy) # To calculate flows of 'stock' (fossil hydrocarbon) energy.
# Use stock (fossil hydrocarbon) energy to fill the first 5% of total energy required.
if environment.units_stock_energy > 0: # environment has remaining stock (fossil hydrocarbon) energy.
environment.units_stock_energy -= (total_energy_required * Decimal(0.05)) # Fill the portion of total energy required (for maintenance) from stock energy.
total_energy_required = total_energy_required * Decimal(0.95)
else:
sys.exit("Model exit. No available stock energy for system maintenance.")
# Use all available flow (renewable) energy and make up any shortfall with stock (fossil hydrocarbon) energy.
if environment.units_flow_energy > 0 and (total_energy_required <= environment.units_flow_energy): # No shortfall in flow energy
environment.units_flow_energy -= total_energy_required
elif environment.units_flow_energy > 0 and (total_energy_required > environment.units_flow_energy): # There is a shortfall of up to 100% of 'total_energy_required'.
energy_shortfall = total_energy_required - environment.units_flow_energy
_flow_energy_remaining = environment.units_flow_energy
environment.units_flow_energy -= _flow_energy_remaining # (will be 0).
if environment.units_stock_energy > 0 and (energy_shortfall <= environment.units_stock_energy): # Environment has remaining stock (fossil hydrocarbon) energy.
environment.units_stock_energy -= energy_shortfall # Shortfall might be 0 if total energy requirement has been met by flow energy.
else:
sys.exit("Model exit. No available stock energy to fill system shortfall.")
# Closing energy flows.
closing_flow_energy = environment.units_flow_energy # To calculate flows of 'flow' (renewable) energy.
closing_stock_energy = environment.units_stock_energy # To calculate flows of 'stock' (fossil hydrocarbon) energy.
# Flow of energy used by the Producer agent this step.
self.flow_energy_used = opening_flow_energy - closing_flow_energy
self.stock_energy_used = opening_stock_energy - closing_stock_energy
# Polution returned to environment.
environment.cumulative_negative_externality += self.stock_energy_used * environment.cumulative_negative_externality_rate
Steady State System
One monetary unit of demands from either Government or Households will require one unit of energy to fulfil. This is a test model run (170 steps) showing simplistic Producer energy use dynamics.
Model Run Parameters
- Run Name: ABMPC Test
- Government Expenditure: 20 units per step
- Taxation rate: 20% (Flat rate; all household agents)
- Coupon Rate: 0%
- Interest Rate: 0%
View the abmpc energy requirement chart.
System Context
View a sketch of ABMPC within a simple macro-financial context.