"""
Define banks' actions.
"""
"""
prev_vars!(agent::Bank) → nothing
Update banks' previous variables.
"""
function prev_vars!(agent::Bank)
agent.deposits_prev = agent.deposits
agent.hpm_prev = agent.hpm
agent.loans_prev = agent.loans
agent.ilf_rate_prev = agent.ilf_rate
agent.ilh_rate_prev = agent.ilh_rate
agent.id_rate_prev = agent.id_rate
agent.advances_prev = agent.advances
agent.bills_prev = agent.bills
agent.lending_facility_prev = agent.lending_facility
agent.deposit_facility_prev = agent.deposit_facility
agent.funding_costs_prev = agent.funding_costs
return nothing
end
"""
reset_vars!(agent::Bank) → nothing
Reset banks' variables.
"""
function reset_vars!(agent::Bank)
agent.flow = 0.0
agent.loans = 0.0
agent.deposits = 0.0
agent.loans_interests = 0.0
agent.deposits_interests = 0.0
agent.ON_interbank = 0.0
agent.Term_interbank = 0.0
agent.repayment = 0.0
agent.defaulted_loans = 0.0
agent.belongToBank = missing
empty!(agent.ib_customers)
return nothing
end
"""
hpm!(agent::Bank, μ, v) → agent.hpm
Update banks' holdings of reserves.
"""
function hpm!(agent::Bank, μ, v)
agent.hpm = (μ + v) * agent.deposits
return agent.hpm
end
"""
bills!(agent::Bank, model) → agent.bills
Update banks' holdings of bills (buffer variable). If bills are negative they are set to zero and banks ask for advances as buffer variable.
"""
function bills!(agent::Bank, model) # id
agent.bills = agent.deposits + agent.lending_facility - agent.loans - model.μ * agent.deposits - agent.deposit_facility + agent.networth
if agent.bills < 0.0
agent.bills = 0.0
end
return agent.bills
end
"""
advances!(agent::Bank, model) → agent.advances
Update banks' advances. If bills are negative, advances act as buffer variable, otherwise banks ask for a proportion of current deposits.
"""
function advances!(agent::Bank, model) # alternative id
if agent.bills == 0.0
agent.advances = agent.loans + agent.deposit_facility + agent.hpm - agent.deposits - agent.lending_facility - agent.networth
else
agent.advances = model.v * agent.deposits
end
return agent.advances
end
"""
update_status!(agent::Bank) → agent.status
Update banks' status in the interbank market: borrower, lender or neutral.
"""
function update_status!(agent::Bank)
if agent.flow < 0 && abs(agent.flow) > (agent.hpm - agent.hpm_prev)
agent.status = :borrower
elseif agent.flow > 0 && agent.flow > (agent.hpm - agent.hpm_prev)
agent.status = :lender
else
agent.status = :neutral
end
return agent.status
end
"""
ib_tot_demand!(agent::Bank) → agent.ib_tot_demand
Deficit banks define their total demand for reserves as dependent on their current outflow and `ΔH`.
"""
function ib_tot_demand!(agent::Bank)
if agent.status == :borrower
agent.ib_tot_demand = abs(agent.flow) - (agent.hpm - agent.hpm_prev)
end
return agent.ib_tot_demand
end
"""
ib_tot_supply!(agent::Bank) → agent.ib_tot_supply
Surplus banks define their total demand for reserves as dependent on their current inflow and `ΔH`.
"""
function ib_tot_supply!(agent::Bank)
if agent.status == :lender
agent.ib_tot_supply = agent.flow - (agent.hpm - agent.hpm_prev)
end
return agent.ib_tot_supply
end
"""
update_liq_preferences!(agent::Bank, model) → agent.liq_pref
Banks update their liquidity preferences which are anchored to their value types `agent.liq_values` at initialization and
adjust the value according to i) changes in overnight and term rates, and ii) their interbank status, such that:
1) if overnight (term) rates increase (decrease), borrowers (lenders) would prefer longer (shorter) maturity interbank contracts;
2) if overnight (term) rates decrease (increase), borrowers (lenders) would prefer shorter (longer) maturity interbank contracts;
"""
function update_liq_preferences!(agent::Bank, model)
if model.ion - model.ion_prev > 0 || model.iterm - model.iterm_prev < 0
if agent.status == :borrower
agent.liq_pref -= agent.liq_pref * model.pref
elseif agent.status == :lender
agent.liq_pref += agent.liq_pref * model.pref
end
elseif model.ion - model.ion_prev < 0 || model.iterm - model.iterm_prev > 0
if agent.status == :borrower
agent.liq_pref += agent.liq_pref * model.pref
elseif agent.status == :lender
agent.liq_pref -= agent.liq_pref * model.pref
end
end
agent.liq_pref = max(0.0, min(agent.liq_pref, 1.0))
return agent.liq_pref
end
"""
ib_on_demand!(agent::Bank) → agent.ib_on_demand
Banks define their demand for overnight interbank loans dependent on their liquidity preferences.
"""
function ib_on_demand!(agent::Bank)
if agent.status == :borrower
agent.ib_on_demand = agent.ib_tot_demand * agent.liq_pref
end
return agent.ib_on_demand
end
"""
ib_term_demand!(agent::Bank) → agent.ib_term_demand
Banks define their demand for term interbank loans as a residual.
"""
function ib_term_demand!(agent::Bank)
if agent.status == :borrower
agent.ib_term_demand = agent.ib_tot_demand - agent.ib_on_demand
end
return agent.ib_term_demand
end
"""
ib_on_supply!(agent::Bank) → agent.ib_on_supply
Banks define their supply for overnight interbank loans dependent on their liquidity preferences.
"""
function ib_on_supply!(agent::Bank)
if agent.status == :lender
agent.ib_on_supply = agent.ib_tot_supply * agent.liq_pref
end
return agent.ib_on_supply
end
"""
ib_term_supply!(agent::Bank) → agent.ib_term_supply
Banks define their supply for term interbank loans as a residual.
"""
function ib_term_supply!(agent::Bank)
if agent.status == :lender
agent.ib_term_supply = agent.ib_tot_supply - agent.ib_on_supply
end
return agent.ib_term_supply
end
"""
update_ib_demand_supply!(agent::Bank) → agent
Updates demand and supply in the interbank market based on the above functions.
"""
function update_ib_demand_supply!(agent::Bank)
CViM.ib_tot_demand!(agent)
CViM.ib_tot_supply!(agent)
CViM.ib_on_demand!(agent)
CViM.ib_term_demand!(agent)
CViM.ib_on_supply!(agent)
CViM.ib_term_supply!(agent)
return agent
end
"""
ib_on!(agent::Bank, model) → agent.ON_interbank
Updates banks' overnight stocks.
"""
function ib_on!(agent::Bank, model)
if agent.status == :borrower && !ismissing(agent.belongToBank)
if agent.ib_on_demand > model[agent.belongToBank].ib_on_supply
agent.ON_interbank = model[agent.belongToBank].ib_on_supply
model[agent.belongToBank].ON_interbank += agent.ON_interbank
elseif agent.ib_on_demand <= model[agent.belongToBank].ib_on_supply
agent.ON_interbank = agent.ib_on_demand
model[agent.belongToBank].ON_interbank += agent.ON_interbank
end
end
return agent.ON_interbank
end
"""
ib_term!(agent::Bank, model) → agent.Term_interbank
Updates banks' term stocks.
"""
function ib_term!(agent::Bank, model)
if agent.status == :borrower && !ismissing(agent.belongToBank)
if agent.ib_term_demand > model[agent.belongToBank].ib_term_supply
agent.Term_interbank = model[agent.belongToBank].ib_term_supply
model[agent.belongToBank].Term_interbank += agent.Term_interbank
elseif agent.ib_term_demand <= model[agent.belongToBank].ib_term_supply
agent.Term_interbank = agent.ib_term_demand
model[agent.belongToBank].Term_interbank += agent.Term_interbank
end
end
return agent.Term_interbank
end
"""
lending_facility!(agent::Bank) → agent.lending_facility
Deficit banks that do not find a suitable partner in the interbank market access the central bank's lending facility
to cover their outflows.
"""
function lending_facility!(agent::Bank)
if agent.status == :borrower && ismissing(agent.belongToBank)
agent.lending_facility = agent.ib_tot_demand
end
return agent.lending_facility
end
"""
deposit_facility!(agent::Bank) → agent.deposit_facility
Surplus banks that do not find a suitable partner in the interbank market access the central bank's deposit facility
to deposit their excess reserves deriving from payment inflows.
"""
function deposit_facility!(agent::Bank)
if agent.status == :lender && isempty(agent.ib_customers)
agent.deposit_facility = agent.ib_tot_supply
end
return agent.deposit_facility
end
"""
funding_costs!(agent::Bank, icb, ion, iterm) → agent.funding_costs
Banks compute their funding costs.
"""
function funding_costs!(agent::Bank, icb, ion, iterm, icbl)
if agent.status == :borrower
if !ismissing(agent.belongToBank)
if agent.ON_interbank > 0.0 && agent.Term_interbank > 0.0
agent.funding_costs = (icb + ion + iterm)/3
elseif agent.ON_interbank > 0.0 && agent.Term_interbank == 0.0
agent.funding_costs = (icb + ion)/2
elseif agent.ON_interbank == 0.0 && agent.Term_interbank > 0.0
agent.funding_costs = (icb + iterm)/2
end
else
agent.funding_costs = (icb + icbl)/2
end
else
agent.funding_costs = icb
end
return agent.funding_costs
end
"""
credit_rates!(agent::Bank, χ1, χ2, χ3) → agent.ilf_rate, agent.ilh_rate, agent.id_rate
Banks determine lending and deposit rates on the credit market.
"""
function credit_rates!(agent::Bank, χ1, χ2, χ3)
agent.ilf_rate = agent.funding_costs_prev + χ1
agent.ilh_rate = agent.funding_costs_prev + χ2
agent.id_rate = agent.funding_costs_prev - χ3
return agent.ilf_rate, agent.ilh_rate, agent.id_rate
end
"""
interests_payments!(agent::Bank, model) → model
Banks make interest payments on bills, reserves and advances.
"""
function interests_payments!(agent::Bank, model)
agent.bills_interests = model.ib * agent.bills_prev
agent.hpm_interests = model.icb * agent.hpm_prev
agent.advances_interests = model.icb * agent.advances_prev
agent.lending_facility_interests = model.icbl * agent.lending_facility_prev
agent.deposit_facility_interests = model.icbd * agent.deposit_facility_prev
return model
end
"""
profits!(agent::Bank) → agent.profits
Banks compute their profits.
"""
function profits!(agent::Bank)
agent.profits = agent.loans_interests + agent.hpm_interests + agent.bills_interests + agent.deposit_facility_interests -
agent.deposits_interests - agent.advances_interests - agent.lending_facility_interests # + agent.repayment
return agent.profits
end
"""
networth!(agent::Bank) → agent.networth
Banks update their networth.
"""
function networth!(agent::Bank)
agent.networth += agent.repayment - agent.defaulted_loans # agent.loans + agent.deposit_facility + agent.hpm + agent.bills - agent.deposits - agent.advances - agent.lending_facility
return agent.networth
end
"""
current_balance!(agent::Bank) → agent.balance_current
Update banks' current balances for SFC checks.
"""
function current_balance!(agent::Bank)
agent.balance_current = agent.loans_interests + agent.hpm_interests + agent.bills_interests + agent.deposit_facility_interests -
agent.deposits_interests - agent.advances_interests - agent.profits - agent.lending_facility_interests # + agent.repayment
return agent.balance_current
end
"""
capital_balance!(agent::Bank) → agent.balance_capital
Update banks' capital balances for SFC checks.
"""
function capital_balance!(agent::Bank)
agent.balance_capital = (agent.advances - agent.advances_prev) + (agent.deposits - agent.deposits_prev) +
(agent.lending_facility - agent.lending_facility_prev) -
(agent.loans - agent.loans_prev) -
(agent.bills - agent.bills_prev) -
(agent.hpm - agent.hpm_prev) -
(agent.deposit_facility - agent.deposit_facility_prev) + agent.repayment - agent.defaulted_loans
if abs(agent.balance_capital) > 1e-06
println(agent.id)
end
return agent.balance_capital
end
"""
SFC!(agent::Bank, model) → model
Define banks' SFC actions and update their accounting.
"""
function SFC!(agent::Bank, model)
CViM.hpm!(agent, model.μ, model.v)
CViM.networth!(agent)
CViM.bills!(agent, model)
CViM.advances!(agent, model)
CViM.capital_balance!(agent)
return model
end