Eleonora Priori, Jack Birner, Marco Mazzoli, and Pietro Terna
Report on the development of an ABM stock-flow consistent model, a framework capable of handling micro-founded macro research questions.
Comments welcome. Please do not quote.
Design and development of the model by Eleonora Priori and Pietro Terna.
Last updated: July 18, 2022
%%javascript
// to avoid scroll in windows
IPython.OutputArea.prototype._should_scroll = function(lines) {
return false;
}
%matplotlib inline
import random as r
import matplotlib.pyplot as plt
import commonVar as cmv
import numpy as np
from tools import *
from metaActions import *
from generateSeeds import *
from plot import *
from initSeries import *
import sys
We observe both the real and monetary sides of the economy.
We consider loans and deposits, with their interests.
Enterprises have initial endowments.
When agents abstein from consuming, their savings increase liquidity.
Investments are uniquely for replacement, without technical progress.
We use specific random sequences for both each agent and each function.
symbol table in $\LaTeX$
$a_i$ - with $a_i \in \mathbf{A}$; agent number $N=|\mathbf{A}|$, agentList
andagentNum
$a^e_i$ - with $a^e_i \in \mathbf{A^e}$ and $\mathbf{A^e} \subset \mathbf{A}$; employer number $N^e=|\mathbf{A^e}|$ in range $[N^e_{min},N^e_{max}]$, employerList
$\mathbf{F}$ - firms' set, with $f_j \in \mathbf{F}$ being $N^f = |\mathbf{F}|$, with $N^f = |\mathbf{F}| = |\mathbf{A^e}|$ , firmList
$\mathbf{A}^w$ - working agents' set, being $\mathbf{A}^w \subseteq \mathbf{A}$, with $N^w_{i,t}=|\mathbf{A}^w_i|$ number of working agents employed by employer $i$ at time $t$, also including self-employed employers, with $a_i \in \mathbf{A}^e$
$\mathbf{B}$ - banks' set, with $b_j \in \mathbf{B}$ being $N^b = |\mathbf{B}|$, bankList
$x^d$ - interest rate on deposits, interestRateOnDeposits
$x^{l^a}$ - interest rate on loans to (private) agents, interestRateOnLoansVsAgents
$x^{l^f}$ - interest rate on loans to firms, interestRateOnLoansVsFirms
$X^d_{a|f,b}$ - amount of positive interests on deposits for a given interval $t$ for agents ($a$) or firms ($f$), and negative for banks ($b$), interestOnDeposits
$X^l_{a|f,b}$ - amount of negative interests on loans for a given interval $t$ for agents ($a$) or firms ($f$), and positive for banks ($b$), interestOnLoans
$p$ - price price
$u$ - unemployment rate unemploymentRate
$dimensional~heterogeneity$ is a $true/false$ chooser, forcing increasing firms to attract more workers. dimensionalHeterogeneity
$\pi_{i,t}$ - labor productivity, a uniformly distributed decimal number in range $[\pi_{min},\pi_{max}]$,productivity
$\Delta\pi_{i,t}$ - uniperiodal additive productivity correction in range $[\Delta\pi_{min},\Delta\pi_{max}]$, productivityDelta
$q_{i,t}$ - production in quantity, production
$\Pi_{i,t}$ - profit, profit
$\rho$ - profit distribution share, rho
$\delta_{i,t}$ - dividend $\rho\Pi_{i,t}$, dividend
or perceivedDividend
$W$ - wage wage
$R_{i,t}$ - revenues, revenues
, including both sales revenues, salesRevenues
, and active interests
$s_{i,t}$ - sales in quantity, sales
$v_{i,t}$ - inventories (final, initial), initialInventories
, finalInventories
$d_{i}$ - deperibility share of the production, deperibilityShare
, setting $d_{max}$
$c_{i,t}$ - consumption rate, a uniformly distributed decimal number in range $[c_{min},c_{max}]$,consumptionRate
$C_{i,t}$ - consumption of $i$ in $t$
$I_{i,t}$ - investment plan of $i$ in $t$, a uniformly distributed realization in range $[I_{min},I_{max}]$,investmentProgram
$\lambda$ -parameter limiting the investment plan, in $I_{i,t} \le \lambda\Pi_{i,t-1}$ , Lambda
$H_{i,t}$ - high powered money (cash) held by individuals (also acting as employers), cashMoney
$Q_{i,t}$ - checking account money deposits held by $a_i$ at time $t$, eventually also negative checkingAccount
$Q^f_{i,t}$ - firm's bank account (with positive or negative balance), bankAccount
$Q^b_{i,t}$ - bank's account (with positive or negative balance) mantained with the central bank, centralBankAccount
$Q^T_{i,t}$ - bank treasury account at central bank, bankTreasuryAccountAtCentralBank
$\alpha$ - parameter determining the mean of the random normal distribution of the initial endowments of both firms and banks as $\alpha N^w_i$, being $i$ a firm or a bank, alphaF
or alphaB
$\beta$ - parameter determining the standard deviation $\sigma$ of the random normal distribution of the initial endowments of both firms and banks, with $\sigma=\frac{\alpha}{\beta}N^w_i$, being $i$ a firm or a bank, beta
the investment and consumption actions are repeated in each cycle, looking around randomly for the sellers; currently nOfConsumptionActions
$=30$ and nOfInvestmentActions
$=10$; each consumption buy action is at maximum the 20% of the planned consumptions in that cycle; instead, each investment buy action can reach the whole amount of the investment program of the cycle; each buy action is limited by the residual capabilty of the seller
magically, the same good can be a consumption item or an investment one
$T$ - number of cycles ncycles
$t$ - current cycle cycle
The structure of an agent: it can represent an entrepreneur, a worker, an unemployed person.
When an agent is created, the initialization process defines:
num
entrepreneur
, set to $false$myEmployer
, set to $0$myFirm
, set to $0$revenues
, initial value $0$sales
, initial value $0$initialInventories
, set to $0$finalInventories
, set to $0$deperibilityShare
production
. production with $t>0$revenues
, initial value $0$each agent has the function:
buyConsumptionGoods
$C_{i,t}=c_{i,t} (W+D_{i,t-1}+X^d_{i,t-1}-X^l_{i,t-1})$; using $D_{i,t-1},X^d_{i,t-1},X^l_{i,t-1}$ we introduce lags with (possible) cyclical effect
being $bu$ the buyer and $se$ the seller (firm), for each fraction $C_{i,t}/k$
($k$ is the number of buying actions in each cycle with random share [0,maxConsumptionShareInSubstep
))
$\Delta Q^f_{se,t}=C_{bu,t}/k$
$\Delta Q_{bu,t}=-C_{bu,t}/k$
each firm has the functions:
produce function (production in quantity), with:
$\pi_{i,t}=\pi_{i,t-1}+\Delta\pi_{i,t}$
$q_{i,t}=N^w_{i,t} \pi_{i,t}$
payWages
paying $W$ to each worker in each time $t$
$\Delta Q_{i,t}=W$ for $a_i \in \mathbf{A}^w$
$\Delta Q^f_{i,t}=-W \mathbf{N}^w_i$ for $a_i \in \mathbf{A}^e$
buyInvestmentGoods
$I_{j,t}$ for $f_j \in \mathbf{F}$ ($I_{j,t}$ is exogenously set), , with $I_{i,t} \le \lambda\Pi_{i,t-1}$, being $\lambda\Pi_{i,t-1}$ a proxy of investment sustainability, introducing a lag with (possible) cyclical effect
being $bu$ the buyer (firm) and $se$ the seller (firm), for each fraction $I_{j,t}/k$
($k$ is the number of investment actions in each cycle, with random share [0,maxInvestmentShareInSubstep
))
$\Delta Q^f_{se,t}=I_{bu,t}/k$
$\Delta Q^f_{bu,t}=-I_{bu,t}/k$
makeBalanceSheet
$v^f_{i,t}=v^i_{i,t}+(q_{i,t}-s_{i,t}) (1 - d_{i})$
$R_{i,t}=p s_{i,t}+X^d_{i,t}$
$\Pi_{i,t}=R_{i,t}-W N^w_{i,t}-X^l_{i,t}+p(v^f_{i,t}-v^i_{i,t})$
reordering, we have:
$\underbrace{\Pi_{i,t}+W N^w_{i,t}+X^l_{i,t}}_{\textrm{direct added value}}=\underbrace{R_{i,t}+p(v^f_{i,t}-v^i_{i,t})}_{\textrm{indirect added value (*)}}$
(*) the cost of bought-in materials and components is missing by construction in this version of the model
distributeDividend
$\delta_{i,t}=\rho\Pi_{i,t}$
$\Delta Q_{i,t}=\delta_{i,t}$
$\Delta Q^f_{i,t}=-\delta_{i,t}$
each bank has the functions:
produce function (production of bank services in quantity), analogously with the firm one
payWages
paying $W$ to each worker in each time $t$
$\Delta Q_{i,t}=W$ for $a_i \in \mathbf{A}^w$
$\Delta Q^f_{i,t}=-W \mathbf{N}^w_i$ for $a_i \in \mathbf{A}^e$
buyInvestmentGoods
$I_{j,t}$ for $f_j \in \mathbf{F}$ ($I_{j,t}$ is exogenously set), , with $I_{i,t} \le \lambda\Pi_{i,t-1}$, being $\lambda\Pi_{i,t-1}$ a proxy of investment sustainability, introducing a lag with (possible) cyclical effect
being $bu$ the buyer (firm) and $se$ the seller (firm), for each fraction $I_{j,t}/k$
($k$ is the number of investment actions in each cycle, with random share [0,maxInvestmentShareInSubstep
))
$\Delta Q^f_{se,t}=I_{bu,t}/k$
$\Delta Q^b_{bu,t}=-I_{bu,t}/k$
distributeDividend
$\delta_{i,t}=\rho\Pi_{i,t}$
$\Delta Q_{i,t}=\delta_{i,t}$
$\Delta Q^b_{i,t}=-\delta_{i,t}$
makeBalanceSheet, with:
being $d_{i}=1$ we have $v^f_{i,t}=v^i_{i,t}=0$
$R_{i,t}=p s_{i,t}+\sum_{a_i}X^l_{i,t}+\sum_{f_i}X^l_{i,t}$
$\Pi_{i,t}=R_{i,t}-W N^w_{i,t}-\sum_{a_i}X^d_{i,t}-\sum_{f_i}X^d_{i,t}$
reordering, we have:
$\underbrace{\Pi_{i,t}+W N^w_{i,t}+\sum_{a_i}X^d_{i,t}}_{\textrm{direct added value}}=\underbrace{R_{i,t}-\sum_{f_i}X^d_{i,t}}_{\textrm{indirect added value (*)}}$
(*) the cost of bought-in materials and components is missing by construction in this version of the model, excepted the interests on deposits paid to firms
Every time we observe a transaction between an agent (or a firm) and its bank, we record the corresponding financial flow on the checking account (or bank account) of the agent (or firm) and on that mantained by the bank with the central bank
debitingCheckingAccount with $\mathcal{L}$ measuring the part which is a loan, if any
For the amount $\mathcal{M} > 0$, debiting the account of agent $i$ at bank $j$
$\Delta Q_i=-\mathcal{M}$
With $\mathcal{L}=\begin{cases}
0,& \text{if } Q_{i,t-1} \geq 0 \land \mathcal{M} \leq Q_{i,t-1}\ \mathcal{M}- Q_{i,t-1},& \text{if } Q_{i,t-1} \geq 0 \land \mathcal{M} \gt Q_{i,t-1}\ \mathcal{M}, & \text{if } Q_{i,t-1} \lt 0 \end{cases}$
modifying the correspondent bank $j$ deposit at the central bank
$\Delta Q^b_j=-\mathcal{M} + \mathcal{L}$
The account $Q_i$ can be positive or negative (in case, also accounted into the loans).
debitingBankAccount with $\mathcal{L}$ measuring the part which is a loan, if any
For the amount $\mathcal{M}$, debiting the account of firm $i$ at bank $j$
$\Delta Q^f_i=-\mathcal{M}$
With $\mathcal{L}=\begin{cases}
0,& \text{if } Q^f_{i,t-1} \geq 0 \land \mathcal{M} \leq Q^f_{i,t-1}\ \mathcal{M}- Q^f_{i,t-1},& \text{if } Q^f_{i,t-1} \geq 0 \land \mathcal{M} \gt Q^f_{i,t-1}\ \mathcal{M}, & \text{if } Q^f_{i,t-1} \lt 0 \end{cases}$
modifying the correspondent bank $j$ deposit at the central bank
$\Delta Q^b_j=-\mathcal{M} + \mathcal{L}$
The account $Q^f_i$ can be positive or negative (in case, also accounted into the loans).
bankDebitingCentralBankAccount
For the amount $\mathcal{M}$, debiting the account of bank $j$ at the central bank
$\Delta Q^b_j=-\mathcal{M}$
being the amount $\mathcal{M}$ a payment on charge of the bank, considering also the specific treasury account of bank $j$
$\Delta Q^T_j=-\mathcal{M}$
The account $Q^b_j$ can be positive or negative (in case, also accounted into the loans of the central bank).
creditingCheckingAccount with $\mathcal{L}$ measuring the part which is a loan reinbursement, if any
For the amount $\mathcal{M} > 0$, crediting the account of agent $i$ at bank $j$
$\Delta Q_i=\mathcal{M}$
With $\mathcal{L}=\begin{cases}
\mathcal{M},& \text{if } Q_{i,t-1} \leq 0 \land \mathcal{M} \leq |Q_{i,t-1}|\ |Q_{i,t-1}|,& \text{if } Q_{i,t-1} \leq 0 \land \mathcal{M} \gt |Q_{i,t-1}|\ 0, & \text{if } Q_{i,t-1} \gt 0 \end{cases}$
modifying the correspondent bank $j$ deposit at the central bank
$\Delta Q^b_j=\mathcal{M} - \mathcal{L}$
The account $Q_i$ can be positive or negative (in case, also accounted into the loans).
creditingBankAccount with $\mathcal{L}$ measuring the part which is a loan reinbursement, if any
For the amount $\mathcal{M}$, crediting the account of firm $i$ at bank $j$
$\Delta Q^f_i=-\mathcal{M}$
With $\mathcal{L}=\begin{cases}
\mathcal{M},& \text{if } Q^f_{i,t-1} \leq 0 \land \mathcal{M} \leq |Q^f_{i,t-1}|\ |Q^f_{i,t-1}|,& \text{if } Q^f_{i,t-1} \leq 0 \land \mathcal{M} \gt |Q^f_{i,t-1}|\ 0, & \text{if } Q^f_{i,t-1} \gt 0 \end{cases}$
modifying the correspondent bank $j$ deposit at the central bank
$\Delta Q^b_j=\mathcal{M} - \mathcal{L}$
The account $Q^f_i$ can be positive or negative (in case, also accounted into the loans).
bankCreditingCentralBankAccount
For the amount $\mathcal{M}$, crediting the account of bank $j$ at the central bank
$\Delta Q^b_j=\mathcal{M}$
being the amount $\mathcal{M}$ a payment on charge of the bank, considering also the specific treasury account of bank $j$
$\Delta Q^T_j=\mathcal{M}$
The account $Q^b_j$ can be positive or negative (in case, also accounted into the loans of the central bank).
computeAndApplyInterests
interests on Loans to Firms (firm $i$ and bank $j$)
we use $Q^f_{i,t}$, final balance of the interval, as if it had been constant throughout the period
$X^l_{i,j}= Q^f_{i,t} x^{l^f}$
$\Delta Q^f_{i,t}=-X^l_{i,j}$
$\Delta Q^b_j = X^l_{i,j}$
$\Delta Q^T_j = X^l_{i,j}$
interests on Loans to Agents (agent $i$ and bank $j$)
we use $Q^a_{i,t}$, final balance of the interval, as if it had been constant throughout the period
$X^l_{i,j}= Q^a_{i,t} x^{l^a}$
$\Delta Q^a_{i,t}=-X^l_{i,j}$
$\Delta Q^b_j = X^l_{i,j}$
$\Delta Q^T_j = X^l_{i,j}$
interests on Deposits by Firms (firm $i$ and bank $j$)
we use $Q^f_{i,t}$, final balance of the interval, as if it had been constant throughout the period
$X^d_{i,j}= Q^f_{i,t} x^{d^f}$
$\Delta Q^f_{i,t}=X^d_{i,j}$
$\Delta Q^b_j = -X^d_{i,j}$
$\Delta Q^T_j = -X^d_{i,j}$
interests on Deposits by Agents (agent $i$ and bank $j$)
we use $Q^a_{i,t}$, final balance of the interval, as if it had been constant throughout the period
$X^d_{i,j}= Q^a_{i,t} x^{d^a}$
$\Delta Q^a_{i,t}=X^d_{i,j}$
$\Delta Q^b_j = -X^d_{i,j}$
$\Delta Q^T_j = -X^d_{i,j}$
computeAndApplyInterests
interests on Loans to Firms (firm $i$ and bank $j$)
we use $Q^f_{i,t}$, final balance of the interval, as if it had been constant throughout the period
$X^l_{i,j}= Q^f_{i,t} x^{l^f}$
$\Delta Q^f_{i,t}=-X^l_{i,j}$
$\Delta Q^b_j = X^l_{i,j}$
$\Delta Q^T_j = X^l_{i,j}$
interests on Loans to Agents (agent $i$ and bank $j$)
we use $Q^a_{i,t}$, final balance of the interval, as if it had been constant throughout the period
$X^l_{i,j}= Q^a_{i,t} x^{l^a}$
$\Delta Q^a_{i,t}=-X^l_{i,j}$
$\Delta Q^b_j = X^l_{i,j}$
$\Delta Q^T_j = X^l_{i,j}$
interests on Deposits by Firms (firm $i$ and bank $j$)
we use $Q^f_{i,t}$, final balance of the interval, as if it had been constant throughout the period
$X^d_{i,j}= Q^f_{i,t} x^{d^f}$
$\Delta Q^f_{i,t}=X^d_{i,j}$
$\Delta Q^b_j = -X^d_{i,j}$
$\Delta Q^T_j = -X^d_{i,j}$
interests on Deposits by Agents (agent $i$ and bank $j$)
we use $Q^a_{i,t}$, final balance of the interval, as if it had been constant throughout the period
$X^d_{i,j}= Q^a_{i,t} x^{d^a}$
$\Delta Q^a_{i,t}=X^d_{i,j}$
$\Delta Q^b_j = -X^d_{i,j}$
$\Delta Q^T_j = -X^d_{i,j}$
class Agent():
def __init__(self, num,r,seed):
self.num=num
self.entrepreneur=False
#self.myFirm=0
self.myEnterprise=0
self.myEmployer=0
self.consumptionRate=0
self.cashMoney=0
self.checkingAccountTminus1=0
self.checkingAccount=0
self.perceivedWage=0
self.perceivedDividend=0
self.myBank=0
self.interestOnDeposits=0
self.interestOnLoans=0
self.r=r.Random()
self.r.seed(seed)
self.myFirmBankList=[]
def copyCheckingAccountBalance(self):
self.checkingAccountTminus1=self.checkingAccount
def buyConsumptionGoods(self,k):
if k==0:
self.consumptionRate=self.r.uniform(cmv.consumptionRateMin,cmv.consumptionRateMax)
self.consumption=(self.perceivedWage+self.perceivedDividend+\
self.interestOnDeposits-self.interestOnLoans)*self.consumptionRate
if self.consumption < 0: self.consumption=0
self.interestOnDeposits=0
self.interestOnLoans=0
self.perceivedWage=0
self.perceivedDividend=0
self.madeConsumption=0
if self.myFirmBankList==[]: self.myFirmBankList=cmv.firmList+cmv.bankList
self.r.shuffle(self.myFirmBankList)
mySeller=self.myFirmBankList[0]
self.purchase=self.r.uniform(0,cmv.maxConsumptionShareInSubstep)*self.consumption
# mean value should be calibrated with thenumber of buy action
self.purchase=min(self.purchase,self.consumption-self.madeConsumption)
self.purchase=min(self.purchase,cmv.price*(mySeller.production+\
mySeller.initialInventories-mySeller.sales))
if self.purchase > 0:
mySeller.sales+=self.purchase/cmv.price
if mySeller.__class__.__name__=="Firm": mySeller.myBank.creditingBankAccount(mySeller,self.purchase)
if mySeller.__class__.__name__=="Bank": \
mySeller.bankCreditingCentralBankAccount(self.purchase) #mySeller is a bank
self.myBank.debitingCheckingAccount(self,self.purchase)
self.madeConsumption+=self.purchase
class Firm():
def __init__(self, num, r,seed):
self.num=num
self.myWorkers=[]
self.myEntrepreneur=0
self.productivity=0
self.initialInventories=0
self.finalInventories=0
self.bankAccount=0
self.bankAccountTminus1=0
self.salesRevenues=0 #sales*price
self.revenues=0
self.sales=0
self.deperibilityShare=r.uniform(0,cmv.maxDeperibilityShare)
self.investmentProgram=0
self.profit=0
self.madeInvestment=0
self.interestOnDeposits=0
self.interestOnLoans=0
self.addedValue=0
self.myBank=0
self.r=r.Random()
self.r.seed(seed)
def copyBankAccountBalance(self):
self.bankAccountTminus1=self.bankAccount
def produce(self):
# clean interests values while starting this cycle
self.interestOnLoans=0
self.interestOnDeposits=0
self.initialInventories=self.finalInventories
self.productivity+=self.r.uniform(cmv.productivityDeltaMin,cmv.productivityDeltaMax)
self.productivity=max(self.productivity,0)
self.production=len(self.myWorkers)*self.productivity
self.sales=0
def payWages(self):
for anAgent in self.myWorkers:
anAgent.perceivedWage=cmv.wage
anAgent.myBank.creditingCheckingAccount(anAgent,cmv.wage)
#anAgent.checkingAccount+=cmv.wage
#anAgent.myBank.centralBankAccount+=cmv.wage
self.myBank.debitingBankAccount(self,cmv.wage*len(self.myWorkers))
#self.bankAccount-=cmv.wage*len(self.myWorkers)
#self.myBank.centralBankAccount-=cmv.wage*len(self.myWorkers)
def buyInvestmentGoods(self,k):
if k==0:
profitControl=max(0,self.profit)
self.investmentProgram=\
min(r.uniform(cmv.investmentMin,cmv.investmentMax),cmv.Lambda*profitControl)
self.madeInvestment=0
self.r.shuffle(cmv.firmList)
mySeller=cmv.firmList[0]
self.myInvestment=self.r.uniform(0,cmv.maxInvestmentShareInSubstep)*self.investmentProgram
self.myInvestment=min(self.myInvestment,cmv.price*(mySeller.production+\
mySeller.initialInventories-mySeller.sales))
if self.myInvestment > 0:
mySeller.sales+=self.myInvestment/cmv.price
mySeller.myBank.creditingBankAccount(mySeller,self.myInvestment)
self.myBank.debitingBankAccount(self,self.myInvestment)
self.investmentProgram-=self.myInvestment
self.madeInvestment+=self.myInvestment
def makeBalanceSheet(self):
self.lostProduction=0
if self.production - self.sales > 0:
self.lostProduction=(self.production - self.sales)*self.deperibilityShare
#print(self.num, lostProduction,self.productivity)
self.finalInventories=self.initialInventories+self.production-\
self.sales-self.lostProduction
self.salesRevenues=self.sales*cmv.price
self.revenues=self.salesRevenues+self.interestOnDeposits
self.profit=self.revenues - len(self.myWorkers)*cmv.wage\
- self.interestOnLoans + \
(self.finalInventories-self.initialInventories)*cmv.price
self.addedValue=self.profit+self.interestOnLoans+len(self.myWorkers)*cmv.wage
def distributeDividend(self):
if self.profit > 0:
dividend=cmv.rho*self.profit
self.myEntrepreneur.perceivedDividend=dividend
self.myEntrepreneur.myBank.creditingCheckingAccount(self.myEntrepreneur,dividend)
self.myBank.debitingBankAccount(self,dividend)
class Bank(Firm):
def __init__(self, num, r,seed):
super().__init__(num,r,seed)
self.myPrivateClients=[]
self.myCommercialClients=[]
self.myDebtsVsAgents=0
self.myDebtsVsFirms=0
self.myCreditsVsAgents=0
self.myCreditsVsFirms=0
self.centralBankAccountTminus1=0
self.centralBankAccount=0
self.bankTreasuryAccountAtCentralBankTminus1=0
self.bankTreasuryAccountAtCentralBank=0
# attribute deletions
del self.bankAccount
del self.bankAccountTminus1
del self.myBank
self.myPrivateClientsTotalInterestOnDeposits=0
self.myPrivateClientsTotalInterestOnLoans=0
self.myCommercialClientsTotalInterestOnDeposits=0
self.myCommercialClientsTotalInterestOnLoans=0
self.r=r.Random()
self.r.seed(seed)
def copyAccountsAtCentralBank(self):
self.centralBankAccountTminus1=self.centralBankAccount
self.bankTreasuryAccountAtCentralBankTminus1=self.bankTreasuryAccountAtCentralBank
def debitingCheckingAccount(self,aClient,amount): # agents' accounts
if aClient.checkingAccount >= 0 and amount <= aClient.checkingAccount: L = 0
if aClient.checkingAccount >= 0 and amount > aClient.checkingAccount: L = amount - aClient.checkingAccount
if aClient.checkingAccount < 0: L = amount
aClient.checkingAccount-=amount
self.centralBankAccount+=-amount + L # look at central bank operation in debiting checking account formulas
def debitingBankAccount(self,aClient,amount): # firms' accounts
if aClient.bankAccount >= 0 and amount <= aClient.bankAccount: L = 0
if aClient.bankAccount >= 0 and amount > aClient.bankAccount: L = amount - aClient.bankAccount
if aClient.bankAccount < 0: L = amount
aClient.bankAccount-=amount
self.centralBankAccount+=-amount + L # look at central bank operation in debiting bank account formulas
def bankDebitingCentralBankAccount(self,amount):
self.centralBankAccount-=amount
self.bankTreasuryAccountAtCentralBank-=amount
def creditingCheckingAccount(self,aClient,amount): # agents' accounts
if aClient.checkingAccount <= 0 and amount <= abs(aClient.checkingAccount): L = amount
if aClient.checkingAccount <= 0 and amount > abs(aClient.checkingAccount): L = abs(aClient.checkingAccount)
if aClient.checkingAccount > 0: L = 0
aClient.checkingAccount+=amount
self.centralBankAccount+=amount - L # look at central bank operation in crediting checking account formulas
def creditingBankAccount(self,aClient,amount): # firms' accounts
if aClient.bankAccount <= 0 and amount <= abs(aClient.bankAccount): L = amount
if aClient.bankAccount <= 0 and amount > abs(aClient.bankAccount): L = abs(aClient.bankAccount)
if aClient.bankAccount > 0: L = 0
aClient.bankAccount+=amount
self.centralBankAccount+=amount - L # look at central bank operation in crediting bank account formulas
def bankCreditingCentralBankAccount(self,amount):
self.centralBankAccount+=amount
self.bankTreasuryAccountAtCentralBank+=amount
def payWages(self):
for anAgent in self.myWorkers:
anAgent.perceivedWage=cmv.wage
anAgent.myBank.creditingCheckingAccount(anAgent,cmv.wage)
self.bankDebitingCentralBankAccount(cmv.wage*len(self.myWorkers))
def buyInvestmentGoods(self,k):
if k==0:
profitControl=max(0,self.profit)
self.investmentProgram=\
min(r.uniform(cmv.investmentMin,cmv.investmentMax),cmv.Lambda*profitControl)
self.madeInvestment=0
self.r.shuffle(cmv.firmList)
mySeller=cmv.firmList[0]
self.myInvestment=self.r.uniform(0,cmv.maxInvestmentShareInSubstep)*self.investmentProgram
self.myInvestment=min(self.myInvestment,cmv.price*(mySeller.production+\
mySeller.initialInventories-mySeller.sales))
if self.myInvestment > 0:
mySeller.sales+=self.myInvestment/cmv.price
mySeller.myBank.creditingBankAccount(mySeller,self.myInvestment)
self.bankDebitingCentralBankAccount(self.myInvestment)
self.investmentProgram-=self.myInvestment
self.madeInvestment+=self.myInvestment
def makeBalanceSheet(self):
self.lostProduction=0
#if self.production - self.sales > 0:
# self.lostProduction=self.production - self.sales
self.finalInventories=0
self.salesRevenues=self.sales*cmv.price
self.revenues=self.salesRevenues + self.myPrivateClientsTotalInterestOnLoans\
+ self.myCommercialClientsTotalInterestOnLoans
self.profit=self.revenues - len(self.myWorkers)*cmv.wage\
- self.myPrivateClientsTotalInterestOnDeposits - self.myCommercialClientsTotalInterestOnDeposits
self.addedValue=self.profit+len(self.myWorkers)*cmv.wage\
- self.myPrivateClientsTotalInterestOnLoans - self.myCommercialClientsTotalInterestOnLoans \
+ self.myPrivateClientsTotalInterestOnDeposits
def distributeDividend(self):
if self.profit > 0:
dividend=cmv.rho*self.profit
self.myEntrepreneur.perceivedDividend=dividend
self.myEntrepreneur.myBank.creditingCheckingAccount(self.myEntrepreneur,dividend)
self.bankDebitingCentralBankAccount(dividend)
def computeAndApplyInterests(self):
#interest are always calculate as positive values, then we add or subctract them
#to and from the accounts and we add them to revenues or costs
for aPrivateClient in self.myPrivateClients:
if aPrivateClient.checkingAccount >=0: #interests on Deposits by Agents
interests=aPrivateClient.checkingAccount*cmv.interestRateOnDeposits
aPrivateClient.checkingAccount+=interests
aPrivateClient.interestOnDeposits=interests
self.bankCreditingCentralBankAccount(interests)
else: #aPrivateClient.checkingAccount < 0 #interests on Loans to Agents
interests=abs(aPrivateClient.checkingAccount*cmv.interestRateOnLoansVsAgents)
aPrivateClient.checkingAccount-=interests
aPrivateClient.interestOnLoans=interests
self.bankDebitingCentralBankAccount(interests)
for aCommercialClient in self.myCommercialClients:
if aCommercialClient.bankAccount >=0: #interests on Deposits by Firms
interests=aCommercialClient.bankAccount*cmv.interestRateOnDeposits
aCommercialClient.bankAccount+=interests
aCommercialClient.interestOnDeposits=interests
self.bankDebitingCentralBankAccount(interests)
else: #aCommercialClient.bankAccount < 0 #interests on Loans to Firms
interests=abs(aCommercialClient.bankAccount*cmv.interestRateOnLoansVsFirms)
aCommercialClient.bankAccount-=interests
aCommercialClient.interestOnLoans=interests
self.bankCreditingCentralBankAccount(interests)
self.myPrivateClientsTotalInterestOnDeposits=\
sum(list(self.myPrivateClients[i].interestOnDeposits for i \
in range(len(self.myPrivateClients))))
self.myPrivateClientsTotalInterestOnLoans=\
sum(list(self.myPrivateClients[i].interestOnLoans for i \
in range(len(self.myPrivateClients))))
self.myCommercialClientsTotalInterestOnDeposits=\
sum(list(self.myCommercialClients[i].interestOnDeposits for i \
in range(len(self.myCommercialClients))))
self.myCommercialClientsTotalInterestOnLoans=\
sum(list(self.myCommercialClients[i].interestOnLoans for i \
in range(len(self.myCommercialClients))))
def makeFinancialAccounts(self):
self.myDebtsVsAgents=0
self.myDebtsVsFirms=0
self.myCreditsVsAgents=0
self.myCreditsVsFirms=0
for aPrivateClient in self.myPrivateClients:
if aPrivateClient.checkingAccount>=0: \
self.myDebtsVsAgents+=aPrivateClient.checkingAccount
if aPrivateClient.checkingAccount<0: \
self.myCreditsVsAgents+=abs(aPrivateClient.checkingAccount)
for aCommercialClient in self.myCommercialClients:
if aCommercialClient.bankAccount>=0: \
self.myDebtsVsFirms+=aCommercialClient.bankAccount
if aCommercialClient.bankAccount<0: \
self.myCreditsVsFirms+=abs(aCommercialClient.bankAccount)
agent basic creation
creation of entrepreneur list
selecting entrepreneurs and creating their firms or their banks
with a given (heterogeneous) productivity
linking the firm or the bank to its entrepreneur, considering the entrepreneur itself as a worker in its firm or bank
creation of a temporary workforce list of to-be-employed agent, escluding entrepreneurs (already self employed)
applying the unemployement rate to exclude agents
assigning workforce (to-be-employed agents) to firms or banks, with a reinforcement mechanism, gradually giving more attraction/hiring capability to firms or banks growing the most
assigning agents and firms to banks in a random way
endowments provided to the enterprises are proportional to the initial workforce, being extracted from a random-normal distribution with $\mu=\alpha N^w_i$ and $\sigma=\frac{\alpha}{\beta}N^w_i$ (substituting $\alpha$ with $\alpha^f$ for the firms, or with $\alpha^b$ for the banks)
def setup(r,seed):
seedManager(r,seed,'setup',setup)
#print(r.random(),setup.r.random())
cmv.agentList=[]
for n in range(cmv.agentNum):
anAgent=Agent(n+1,r,cmv.agentSeedList[n])
cmv.agentList.append(anAgent)
# creation of: entrepreneur list; firm list; bank list
cmv.entrepreneurNum=setup.r.randint(cmv.entrepreneurMin, cmv.entrepreneurMax)
cmv.bankNum=setup.r.randint(cmv.bankMin, cmv.bankMax)
cmv.entrepreneurList=[]
cmv.firmList=[]
cmv.bankList=[]
entrepreneurCandidates=cmv.agentList.copy()
for n in range(cmv.entrepreneurNum):
i=setup.r.randint(0,len(entrepreneurCandidates)-1)
entrepreneurCandidates[i].entrepreneur=True
if len(cmv.bankList) < cmv.bankNum:
newEnterprise=Bank(entrepreneurCandidates[i].num,\
r,cmv.bankSeedList[len(cmv.bankList)])
else:
newEnterprise=Firm(entrepreneurCandidates[i].num,\
r,cmv.firmSeedList[len(cmv.firmList)])
entrepreneurCandidates[i].myEnterprise=newEnterprise
entrepreneurCandidates[i].myEmployer=newEnterprise
newEnterprise.myEntrepreneur=entrepreneurCandidates[i]
newEnterprise.myWorkers.append(entrepreneurCandidates[i])
newEnterprise.productivity=\
setup.r.uniform(cmv.productivityMin,cmv.productivityMax)
cmv.entrepreneurList.append(entrepreneurCandidates.pop(i))
if newEnterprise.__class__.__name__=="Bank": cmv.bankList.append(newEnterprise)
if newEnterprise.__class__.__name__=="Firm": cmv.firmList.append(newEnterprise)
cmv.firmNum=len(cmv.firmList)
# creation of workforce list
toBeEmployed=[]
for anAgent in cmv.agentList:
if not anAgent.entrepreneur: toBeEmployed.append(anAgent)
for k in range(round(cmv.unemploymentRate*cmv.agentNum)):
toBeEmployed.pop(setup.r.randint(0,len(toBeEmployed)))
#len(toBeEmployed)
# assigning workforce to firms and banks
tmpEnterpriseListWithDuplications=cmv.firmList+cmv.bankList
for anAgent in toBeEmployed:
choice=setup.r.choice(tmpEnterpriseListWithDuplications)
anAgent.myEmployer=choice
choice.myWorkers.append(anAgent)
if cmv.dimensionalHeterogeneity: tmpEnterpriseListWithDuplications.append(choice)
# assigning agents to firms and banks
if len(cmv.bankList)>0:
for anAgent in cmv.agentList:
anAgent.myBank=setup.r.choice(cmv.bankList)
anAgent.myBank.myPrivateClients.append(anAgent)
for aFirm in cmv.firmList:
aFirm.myBank=setup.r.choice(cmv.bankList)
aFirm.myBank.myCommercialClients.append(aFirm)
# assigning endowments to firms and banks
cmv.totalInitFirmEndowments=0
for aFirm in cmv.firmList:
aFirm.initEn=setup.r.gauss(cmv.alphaF*len(aFirm.myWorkers),\
(cmv.alphaF/cmv.beta)*len(aFirm.myWorkers))
aFirm.myBank.creditingBankAccount(aFirm,aFirm.initEn)
cmv.totalInitFirmEndowments+=aFirm.initEn
cmv.totalInitBankEndowments=0
for aBank in cmv.bankList:
aBank.initEn=setup.r.gauss(cmv.alphaB*len(aBank.myWorkers),\
(cmv.alphaB/cmv.beta)*len(aBank.myWorkers))
aBank.bankCreditingCentralBankAccount(aBank.initEn)
cmv.totalInitBankEndowments+=aBank.initEn
initSeries()
metaActions.py
)¶copyAccounts is only used to keep note of financial account balances of agents, firms, and banks in previous cycle, i.e., $t-1$
produceAll orders to the firms to produce and to collects the results
payWagesAll orders to the firms to pay wages, also to the entrepreneurs
buyConsumptionGoodsAll orders to the agents to buy consumption goods
buyInvestmentGoodsAll orders to the firms to buy investment goods
buyConsumptionOrInvestmentGoodsAll orders to the agents and to the firms to buy consumption or investment goods
makeBalanceSheetAll with firm making accounts
distributeDividendAll attributing the $\rho$ share of firm profits to the entrepreneurs
accountCashMoneyAll summarizing eveyone cash money at the end of a cycle
accountCheckingAccountAll summarizing eveyone checking accounts at the end of a cycle
accountBankingAccountAll summarizing firm banking accounts at the end of a cycle
computeAndApplyInterestsAll calculating the interests on deposits and loans for each agent and firm (and symmetrically for banks) and updatating accounts
makeBankFinancialAccountsAll summmarinzing all the checking and bank accounts
model parameters
¶cmv.agentNum=100
cmv.entrepreneurMin=6
cmv.entrepreneurMax=20
cmv.bankMin=2
cmv.bankMax=3
if cmv.bankMax > cmv.entrepreneurMin:
print ("Bank maximum number cannot exceed the minimum number of firms!")
sys.exit(0)
cmv.price=1
cmv.unemploymentRate=0
cmv.dimensionalHeterogeneity=True
cmv.productivityMin=0.8
cmv.productivityMax=1.2
cmv.productivityDeltaMin=cmv.productivityMin-1
cmv.productivityDeltaMax=cmv.productivityMax-1
cmv.maxDeperibilityShare=0.8
cmv.wage=1
cmv.rho=0.35
cmv.consumptionRateMin=0.7
cmv.consumptionRateMax=1
cmv.investmentMin=1
cmv.investmentMax=15
cmv.Lambda=3
cmv.nOfConsumptionActions=30
cmv.maxConsumptionShareInSubstep=0.3
cmv.nOfInvestmentActions=10
cmv.maxInvestmentShareInSubstep=0.3
cmv.interestRateOnDeposits=0.005
cmv.interestRateOnLoansVsAgents=0.03
cmv.interestRateOnLoansVsFirms=0.08
cmv.alphaF=25
cmv.alphaB=10
cmv.beta=5
cmv.ncycles=100
cmv.cycle=0
model machine
¶a random seed determining the random number sequences
a list of actions (meta ones)
an engine excecuting the meta actions (their code in metaAcions,py
file, in the same folder of the notebook; online, look a the model GitHub
random seed sequence, to have independent each class instance or function using random number, based on generateSeed()
in generateSeeds.py
file, in the same folder of the notebook; online, look a the model GitHub
display tools; their code is hidden into the file tools.py
, in the same folder of the notebook; online, look a the model GitHub
# the seed must be in range -2147483648 to 2147483647
r.seed(12345)
generateSeeds()
setup(r,cmv.functionSeedList[0])
cmv.actionList=["copyAccounts()","produceAll()","payWagesAll()",\
"buyConsumptionOrInvestmentGoodsAll(r,cmv.functionSeedList[3])",\
"computeAndApplyInterestsAll()","makeBalanceSheetAll()",\
"distributeDividendAll()","accountCashMoneyAll()",\
"accountCheckingAccountAll()","accountBankAccountAll()",\
"makeBankFinancialAccountsAll()"\
]
for cmv.cycle in range(cmv.ncycles):
for anAction in cmv.actionList:
exec(anAction)
makeHist()
nationalAccounts()
makePlots()
------------------------------------------- # of enterprises 12 # of firms 10 # of banks 2 ------------------------------------------- ------------------------------------------- "national" accounts ------------------------------------------- t total initial consum. invest. final a.v. invent. invent. 1 96.599 0.000 | 84.515 0.000 12.084 2 93.606 12.084 | 83.374 9.415 12.901 3 91.589 12.901 | 87.631 7.320 9.538 4 85.116 9.538 | 79.221 15.433 0.000 5 88.020 0.000 | 82.209 5.009 0.802 6 85.772 0.802 | 78.382 8.038 0.153 7 80.430 0.153 | 69.889 10.694 0.000 8 82.401 0.000 | 69.884 12.517 0.000 9 80.559 0.000 | 64.771 15.789 0.000 10 78.652 0.000 | 68.259 10.393 0.000 11 77.711 0.000 | 65.462 12.249 0.000 12 78.634 0.000 | 69.833 8.801 0.000 13 79.295 0.000 | 69.795 9.500 0.000 14 72.928 0.000 | 56.707 16.221 0.000 15 77.676 0.000 | 73.276 4.400 0.000 16 73.183 0.000 | 59.888 13.295 0.000 17 71.584 0.000 | 63.137 8.447 0.000 18 67.118 0.000 | 57.555 9.563 0.000 19 69.300 0.000 | 60.946 8.355 0.000 20 74.172 0.000 | 65.344 8.828 0.000 21 73.648 0.000 | 57.567 16.080 0.000 22 74.948 0.000 | 66.906 8.042 0.000 23 77.282 0.000 | 67.792 9.490 0.000 24 75.399 0.000 | 65.052 10.347 0.000 25 62.768 0.000 | 52.917 9.851 0.000 26 57.586 0.000 | 51.033 6.553 0.000 27 68.165 0.000 | 59.742 8.423 0.000 28 59.797 0.000 | 54.066 5.731 0.000 29 53.200 0.000 | 42.525 10.675 0.000 30 55.925 0.000 | 51.482 4.443 0.000 31 60.951 0.000 | 55.646 5.305 0.000 32 65.322 0.000 | 60.442 4.881 0.000 33 56.321 0.000 | 50.680 5.641 0.000 34 58.265 0.000 | 53.021 5.244 0.000 35 61.758 0.000 | 50.060 11.698 0.000 36 67.081 0.000 | 61.268 5.813 0.000 37 62.830 0.000 | 54.206 8.624 0.000 38 58.094 0.000 | 54.219 3.876 0.000 39 46.384 0.000 | 42.132 4.252 0.000 40 51.262 0.000 | 46.424 4.838 0.000 41 57.191 0.000 | 51.251 5.941 0.000 42 56.712 0.000 | 47.616 9.096 0.000 43 53.477 0.000 | 47.202 6.275 0.000 44 55.315 0.000 | 48.620 6.695 0.000 45 50.523 0.000 | 48.831 1.693 0.000 46 49.655 0.000 | 42.347 7.308 0.000 47 47.118 0.000 | 39.851 7.267 0.000 48 53.817 0.000 | 46.404 7.413 0.000 49 58.269 0.000 | 50.952 7.317 0.000 50 65.198 0.000 | 61.759 3.439 0.000 51 62.642 0.000 | 52.046 10.596 0.000 52 70.464 0.000 | 51.593 18.870 0.000 53 72.503 0.000 | 56.397 16.107 0.000 54 69.243 0.000 | 60.141 9.102 0.000 55 65.182 0.000 | 57.159 8.022 0.000 56 64.766 0.000 | 51.146 13.619 0.000 57 67.561 0.000 | 56.767 10.794 0.000 58 70.079 0.000 | 63.359 6.720 0.000 59 73.266 0.000 | 66.735 6.532 0.000 60 72.168 0.000 | 62.655 9.513 0.000 61 77.714 0.000 | 69.270 8.444 0.000 62 83.121 0.000 | 70.515 12.606 0.000 63 82.777 0.000 | 74.911 7.866 0.000 64 94.422 0.000 | 72.145 22.276 0.000 65 89.801 0.000 | 75.400 14.401 0.000 66 91.020 0.000 | 74.779 16.241 0.000 67 91.732 0.000 | 71.743 19.989 0.000 68 87.746 0.000 | 72.022 15.724 0.000 69 89.301 0.000 | 76.025 13.276 0.000 70 87.407 0.000 | 71.014 16.393 0.000 71 87.807 0.000 | 77.087 10.721 0.000 72 93.441 0.000 | 82.617 10.824 0.000 73 94.137 0.000 | 76.419 17.718 0.000 74 93.163 0.000 | 82.788 10.376 0.000 75 94.940 0.000 | 85.510 9.430 0.000 76 85.108 0.000 | 70.071 15.037 0.000 77 81.575 0.000 | 72.194 9.381 0.000 78 79.800 0.000 | 71.153 8.647 0.000 79 83.116 0.000 | 76.883 6.233 0.000 80 80.266 0.000 | 64.490 15.776 0.000 81 78.695 0.000 | 71.016 7.679 0.000 82 76.340 0.000 | 68.935 7.405 0.000 83 77.360 0.000 | 63.714 13.645 0.000 84 81.507 0.000 | 71.820 9.687 0.000 85 78.084 0.000 | 68.327 9.757 0.000 86 72.218 0.000 | 64.456 7.763 0.000 87 69.504 0.000 | 59.905 9.599 0.000 88 76.627 0.000 | 64.572 12.055 0.000 89 71.604 0.000 | 55.953 15.650 0.000 90 79.837 0.000 | 73.238 6.599 0.000 91 82.962 0.000 | 75.044 7.917 0.000 92 83.087 0.000 | 68.151 14.936 0.000 93 84.737 0.000 | 70.314 14.423 0.000 94 90.627 0.000 | 80.543 10.084 0.000 95 93.556 0.000 | 85.085 8.471 0.000 96 92.732 0.000 | 78.319 14.413 0.000 97 86.315 0.000 | 65.047 21.268 0.000 98 89.351 0.000 | 77.963 11.388 0.000 99 79.245 0.000 | 65.172 14.073 0.000 100 77.796 0.000 | 68.755 9.042 0.000