Finance
Finance: asset prices, growth processes, wealth, systemic risk, and arbitrage.
ArbitrageDensityElement(label, visual=None, *, rho=0.0, D=0.5, A_x=0.0, E=0.5, A_t=0.0)
Bases: Element
Density of a good carried by random-walk traders, minimally coupled to an exchange rate connection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the density. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
rho
|
Annotated[object, StateSpec(domain=closed_open(0, oo))]
|
The density of the good. |
0.0
|
D
|
Annotated[object, ParameterSpec(domain=open(0, oo))]
|
The diffusion constant of the traders. |
0.5
|
A_x
|
Annotated[object, ParameterSpec()]
|
The initial spatial component of the exchange rate connection. |
0.0
|
E
|
Annotated[object, ParameterSpec()]
|
The arbitrage field strength, the growth rate of the spatial component. |
0.5
|
A_t
|
Annotated[object, ParameterSpec()]
|
The temporal component of the exchange rate connection. |
0.0
|
Examples:
>>> from skcomplex.systems.economics.finance import ArbitrageDensityElement
>>> ArbitrageDensityElement('market', E=1.0).E
1.0
Source code in src/skcomplex/systems/economics/finance/_arbitrage.py
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |
AssetElement(label, visual=None, *, price=1.0)
Bases: Element
Traded asset described by its price.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the asset. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
price
|
Annotated[float, StateSpec(domain=open(0, oo))]
|
The initial price. |
1.0
|
Examples:
>>> from skcomplex.systems.economics.finance import AssetElement
>>> AssetElement('stock', price=100.0).price
100.0
Source code in src/skcomplex/systems/economics/common/_asset.py
34 35 36 37 38 39 40 41 42 | |
BalanceSheetElement(label, visual=VisualSpec('agents', {'color_by': 'status'}), *, external=0.0, equity=0.0, payment=0.0, status=SOLVENT)
Bases: Element
Bank of an interbank network, with its external assets, its equity, its payments, and its state of default.
The bank is a passive agent that the contagion of the system updates, a solvency cascade through its equity or a clearing of payments through its payment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the agent or group. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
VisualSpec('agents', {'color_by': 'status'})
|
external
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The external assets. |
0.0
|
equity
|
Annotated[float, StateSpec()]
|
The equity, the assets minus the liabilities. |
0.0
|
payment
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The payment the bank makes on its interbank liabilities. |
0.0
|
status
|
Annotated[float, StateSpec(domain=NN)]
|
0 for solvent, 1 for defaulting in this step, and 2 for defaulted. |
SOLVENT
|
Examples:
>>> from skcomplex.core.components.elements import GroupElement
>>> from skcomplex.systems.economics.finance import BalanceSheetElement
>>> GroupElement('banks', element=BalanceSheetElement, size=3, values={'equity': 4.0}).size
3
Source code in src/skcomplex/systems/economics/common/_balance_sheet.py
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
BookInteraction(label, *, requesters, providers, rule=RandomSearchSpec(), limit=('bid', 'ask'), quantity=('demand', 'supply'), allowance='money', transfers=(('money', -1), ('shares', 1)), phase='trade', on_match=None, opening=100.0)
Bases: MatchingInteraction[SystemView]
Limit order book that matches the orders of the traders and reports the last traded price.
The book is a matching of the traders with themselves, which binds the requesters' limit to their bid and the
providers' to their ask, and every trade is two transfers, money from buyer to seller and shares from seller to
buyer, so the total money and the total shares stay the same, which the default run checks as invariants. The book
reports the last traded price, the previous price when nothing trades, and the traded volume.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the book. |
required |
requesters
|
Annotated[str, RoleSpec()]
|
The path of the group of buying traders. |
required |
providers
|
Annotated[str, RoleSpec()]
|
The path of the group of selling traders. |
required |
rule
|
MatchingRule
|
The spec of the algorithm that matches the orders, such as |
RandomSearchSpec()
|
limit
|
str | tuple[str, str]
|
The states with the limit prices of the buyers and of the sellers. |
('bid', 'ask')
|
quantity
|
str | tuple[str, str]
|
The states with the quantities the buyers want and the sellers offer. |
('demand', 'supply')
|
allowance
|
str
|
The state of a buyer with the money it can spend. |
'money'
|
transfers
|
Sequence[tuple[str, int]]
|
The states every trade moves, money paid by the buyer and shares delivered to it. |
(('money', -1), ('shares', 1))
|
phase
|
str | None
|
The phase the book clears in. |
'trade'
|
on_match
|
Callable[[MatchSpec, SystemView], None] | None
|
A function of every trade and the system view, run after the transfers, or |
None
|
opening
|
float
|
The price before the first trade. |
100.0
|
Examples:
>>> from skcomplex.systems.economics.finance import BookInteraction
>>> BookInteraction('book', requesters='traders', providers='traders').reports
('price', 'volume')
Source code in src/skcomplex/systems/economics/finance/_order_book.py
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | |
DebtRankCascadeInteraction(label, *, banks, impact=())
Bases: Interaction
Synchronous spread of distress, h_i = min(1, h_i + sum_j W_ji h_j) over the distressed banks j.
A bank whose distress becomes positive turns distressed, and a distressed bank turns inactive after one step, so every bank passes its distress on once.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
banks
|
Annotated[str, RoleSpec()]
|
The path of the group of banks. |
required |
impact
|
Sequence[Sequence[float]]
|
The impact matrix, |
()
|
Examples:
>>> from skcomplex.systems.economics.finance import DebtRankCascadeInteraction
>>> DebtRankCascadeInteraction('cascade', banks='banks', impact=[[0.0, 0.5], [0.0, 0.0]]).impact
[[0.0, 0.5], [0.0, 0.0]]
Source code in src/skcomplex/systems/economics/finance/_contagion.py
122 123 124 125 126 127 128 129 130 131 | |
spread(system)
Advance the distress and the states of every bank by one step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system
|
SystemView
|
The system. |
required |
Source code in src/skcomplex/systems/economics/finance/_contagion.py
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | |
DefaultCascadeInteraction(label, *, rule=None, phase=None, banks, liabilities=(), threshold=0.0, recovery=0.0)
Bases: FeedbackInteraction[SystemView]
Synchronous cascade of defaults, in which the creditors of a defaulting bank write off their claims on it.
Every step the banks that defaulted in the last step pass their losses on: every creditor j of a defaulting bank
i loses (1 - recovery) L_ij of its equity, and a solvent bank whose equity falls below the threshold defaults.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the cascade. |
required |
rule
|
None
|
Unused, since the cascade overrides |
None
|
phase
|
str | None
|
The phase the cascade acts in, or |
None
|
banks
|
Annotated[str, RoleSpec()]
|
The path of the group of banks. |
required |
liabilities
|
Sequence[Sequence[float]]
|
The interbank liabilities, |
()
|
threshold
|
Annotated[float, ParameterSpec()]
|
The equity below which a bank defaults. |
0.0
|
recovery
|
Annotated[float, ParameterSpec(domain=closed(0, 1))]
|
The share of a claim on a defaulted bank that its creditor recovers. |
0.0
|
Examples:
>>> from skcomplex.systems.economics.finance import DefaultCascadeInteraction
>>> DefaultCascadeInteraction('cascade', banks='banks').reports
('defaults', 'losses')
Source code in src/skcomplex/systems/economics/finance/_solvency.py
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | |
act(system)
Pass on the losses of the defaulting banks and default the banks below the threshold.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system
|
SystemView
|
The system view of the cascade. |
required |
Source code in src/skcomplex/systems/economics/finance/_solvency.py
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | |
ExchangeLinkElement(label, visual=None, *, A=0.0, E=0.0)
Bases: Element
Link of a lattice with an exchange-rate potential A and its rate of change E.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the link or the group on the links. |
required |
visual
|
VisualSpec | None
|
How the link is drawn, or |
None
|
A
|
Annotated[float, StateSpec()]
|
The initial exchange-rate potential. |
0.0
|
E
|
Annotated[float, StateSpec()]
|
The initial value of |
0.0
|
Attributes:
| Name | Type | Description |
|---|---|---|
default_visual_ |
The visual of the link when it sets none. |
Examples:
>>> from skcomplex.systems.economics.finance import ExchangeLinkElement
>>> ExchangeLinkElement('link', A=0.5).A
0.5
Source code in src/skcomplex/systems/economics/finance/_gauge_arbitrage.py
91 92 93 94 95 96 97 98 99 100 101 | |
FireSaleInteraction(label, *, rule=None, phase=None, banks, assets, holdings=(), liabilities=(), alpha=1.0, leverage=20.0, selling='threshold')
Bases: FeedbackInteraction[SystemView]
Banks that sell common assets on losses, and the market impact that lowers the prices of what they sell.
Every step the banks value their holdings at the current prices. Under the rule 'threshold' a bank whose losses
exhaust its equity defaults and liquidates its whole portfolio, and otherwise stays passive. Under 'leverage' a
bank sells the same share of every holding to bring its assets back to leverage times its equity, and liquidates
everything when its equity is gone. The proceeds become cash, and the price of every asset falls to
p0 exp(-alpha x), where x is the share of the asset liquidated so far and p0 its price after the shock.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the fire sales. |
required |
rule
|
None
|
Unused, since the fire sales override |
None
|
phase
|
str | None
|
The phase the fire sales act in, or |
None
|
banks
|
Annotated[str, RoleSpec()]
|
The path of the group of banks. |
required |
assets
|
Annotated[str, RoleSpec()]
|
The path of the group of assets. |
required |
holdings
|
tuple[tuple[float, ...], ...]
|
The initial holdings, |
()
|
liabilities
|
tuple[float, ...]
|
The liabilities of every bank. |
()
|
alpha
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The market impact. |
1.0
|
leverage
|
Annotated[float, ParameterSpec(domain=open(1, oo))]
|
The target ratio of assets to equity of the rule |
20.0
|
selling
|
str
|
The rule of the banks, |
'threshold'
|
Raises:
| Type | Description |
|---|---|
ValidationError
|
The rule is unknown, raised by |
Examples:
>>> from skcomplex.systems.economics.finance import FireSaleInteraction
>>> FireSaleInteraction('sales', banks='banks', assets='assets').reports
('defaults', 'sold')
Source code in src/skcomplex/systems/economics/finance/_fire_sales.py
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | |
act(system)
Value the portfolios, sell, and move the prices by the market impact.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system
|
SystemView
|
The system view of the fire sales. |
required |
Source code in src/skcomplex/systems/economics/finance/_fire_sales.py
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | |
GeometricBrownianMotionInteraction(label, *, target, mu=0.05, sigma=0.2, process=None, index=None)
Bases: RateInteraction
Geometric Brownian motion, dS = mu * S * dt + sigma * S * dW, of the price of an asset.
The Wiener process dW is independent by default, or process index of a WienerProcessSpec that correlates it
with the motions of other assets.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the asset. |
required |
mu
|
Annotated[float, ParameterSpec()]
|
The drift. |
0.05
|
sigma
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The volatility. |
0.2
|
process
|
Annotated[WienerProcessSpec | None, RoleSpec(noise=True)]
|
The Wiener processes, one of which drives the price, or |
None
|
index
|
int | None
|
The process of |
None
|
Examples:
>>> from skcomplex.systems.economics.finance import GeometricBrownianMotionInteraction
>>> from skcomplex.core.specs import WienerProcessSpec
>>> GeometricBrownianMotionInteraction('gbm', target='stock', sigma=0.3).sigma
0.3
>>> market = WienerProcessSpec('market', dimension=2)
>>> GeometricBrownianMotionInteraction('gbm', target='stock', process=market, index=1).index
1
Source code in src/skcomplex/systems/economics/common/_geometric_brownian_motion.py
51 52 53 54 55 56 57 58 59 60 61 62 63 | |
GibratFirmElement(label, visual=None, *, x=100.0, previous=100.0, mu=1.02, sigma=0.05)
Bases: Element
Firm whose size is multiplied every step by an independent normal growth factor, x = lambda x.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the agent or group. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
x
|
Annotated[float, StateSpec()]
|
The initial size. |
100.0
|
previous
|
Annotated[float, StateSpec()]
|
The size before the last step. |
100.0
|
mu
|
Annotated[float, ParameterSpec()]
|
The mean of the growth factor. |
1.02
|
sigma
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The standard deviation of the growth factor. |
0.05
|
Examples:
>>> from skcomplex.core.components.elements import GroupElement
>>> from skcomplex.systems.economics.finance import GibratFirmElement
>>> GroupElement('firms', element=GibratFirmElement, size=10, values={'mu': 1.0}).size
10
Source code in src/skcomplex/systems/economics/finance/_growth_processes.py
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
get_growth(agent, system)
staticmethod
Return the size multiplied by a growth factor drawn from a normal distribution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
GibratFirmView
|
The firm. |
required |
system
|
SystemView
|
The system view of the growth. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
size |
float
|
The size after the step. |
Source code in src/skcomplex/systems/economics/finance/_growth_processes.py
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | |
GoodSiteElement(label, visual=None, *, rho=1.0)
Bases: Element
Site of a lattice with a density rho of a good.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the site or the group on the sites. |
required |
visual
|
VisualSpec | None
|
How the site is drawn, or |
None
|
rho
|
Annotated[float, StateSpec()]
|
The initial density of the good. |
1.0
|
Attributes:
| Name | Type | Description |
|---|---|---|
default_visual_ |
The visual of the site when it sets none. |
Examples:
>>> from skcomplex.systems.economics.finance import GoodSiteElement
>>> GoodSiteElement('site', rho=2.0).rho
2.0
Source code in src/skcomplex/systems/economics/finance/_gauge_arbitrage.py
54 55 56 57 58 59 60 61 62 | |
GuruMarketInteraction(label, *, rule=None, phase=None, traders, tau=100.0, beta_step=1.5, opening=10.0)
Bases: FeedbackInteraction[SystemView]
Order-driven market of noise traders who imitate the expectation of a guru, on a network rewired every day.
Every step is a trading day. First every trader picks a random trader j and moves its link from the trader k
it follows to j with probability 1 / (1 + exp(-beta (f_j - f_k))), where the fitness f is the wealth relative
to the richest trader (Eqs. 3.4 and 3.5 of Caiani et al. 2016). The guru is the trader of the largest in-degree of
the day before, and the intensity of choice beta grows by beta_step every day the guru survives and returns to
1 when it is replaced. Every trader draws its expected return sigma_i eps (Eq. 3.3) and adopts the one of the
trader it follows, except the guru.
Then tau intraday operations run, each by a trader drawn at random. With the expected price
p_ref exp(sqrt(tau) r) (Eq. 3.1), a trader expecting a rise bids U(p (1 - gamma1), p_hat) for a random share of
its free cash, and a trader expecting a fall asks U(p_hat, p (1 + gamma2)) for a random share of its free stocks
(Eq. 3.2 and Table 3.1). An order that crosses the book is a market order that trades with the best quotes by price
and time priority, and what is left rests as a limit order, whose cash or stocks stay tied in the book until it
trades or expires at the end of the day. The price is the last traded price, the mid quote when an operation trades
nothing, and the previous price when the book is empty.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the market. |
required |
rule
|
None
|
Unused, since the market overrides |
None
|
phase
|
str | None
|
The phase the market acts in, or |
None
|
traders
|
Annotated[str, RoleSpec()]
|
The path of the group of traders. |
required |
tau
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The intraday operations of a day. |
100.0
|
beta_step
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The growth of the intensity of choice every day the guru survives. |
1.5
|
opening
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The price before the first day. |
10.0
|
Examples:
>>> from skcomplex.systems.economics.finance import GuruMarketInteraction
>>> GuruMarketInteraction('market', traders='traders').reports[:2]
('price', 'log_return')
Source code in src/skcomplex/systems/economics/finance/_guru_order_book.py
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | |
act(system)
Rewire the network, form the expectations, and run the trading day.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system
|
SystemView
|
The system view of the market. |
required |
Source code in src/skcomplex/systems/economics/finance/_guru_order_book.py
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | |
GuruTraderElement(label, visual=VisualSpec('agents', {'color_by': 'followers'}), *, cash=1000.0, stocks=100.0, wealth=2000.0, expectation=0.0, follows=0, sigma=0.01, followers=0)
Bases: Element
Noise trader of an order-driven market, who follows the expectation of the trader it is linked to.
The trader holds cash and stocks, has one outgoing link to the trader whose expected return it adopts, and expects
returns of its own volatility sigma. The market of the system rewires its link and runs its orders.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the agent or group. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
VisualSpec('agents', {'color_by': 'followers'})
|
cash
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The cash of the trader, including the cash held by its limit orders. |
1000.0
|
stocks
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The stocks of the trader, including the stocks held by its limit orders. |
100.0
|
wealth
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The cash plus the stocks at the price of the day. |
2000.0
|
expectation
|
Annotated[float, StateSpec()]
|
The expected return of the day after imitation. |
0.0
|
follows
|
Annotated[float, StateSpec(domain=NN)]
|
The index of the trader whose expectation the trader adopts. |
0
|
sigma
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The volatility of the expected returns of the trader. |
0.01
|
followers
|
Annotated[float, StateSpec(domain=NN)]
|
The number of traders that follow the trader, its in-degree. |
0
|
Examples:
>>> from skcomplex.core.components.elements import GroupElement
>>> from skcomplex.systems.economics.finance import GuruTraderElement
>>> GroupElement('traders', element=GuruTraderElement, size=3).size
3
Source code in src/skcomplex/systems/economics/finance/_guru_order_book.py
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | |
InterbankElement(label, visual=None, *, h=0.0, status=UNDISTRESSED, value=0.0)
Bases: Element
Bank of the DebtRank cascade, with its level of distress, its state, and its economic value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the agent or group. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
h
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The level of distress, between 0 and 1, where 1 is default. |
0.0
|
status
|
Annotated[float, StateSpec(domain=NN)]
|
0 for undistressed, 1 for distressed, and 2 for inactive. |
UNDISTRESSED
|
value
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The economic value, the bank's share of all interbank lending. |
0.0
|
Examples:
>>> from skcomplex.core.components.elements import GroupElement
>>> from skcomplex.systems.economics.finance import InterbankElement
>>> GroupElement('banks', element=InterbankElement, size=3, values={'h': [1.0, 0.0, 0.0]}).size
3
Source code in src/skcomplex/systems/economics/finance/_contagion.py
61 62 63 64 65 66 67 68 69 70 71 72 73 | |
KestenFirmElement(label, visual=None, *, x=100.0, lambda_low=0.48, lambda_high=1.48, b_low=0.0, b_high=1.0)
Bases: Element
Firm whose size follows Kesten's process, x = lambda x + b, with uniform random lambda and b.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the agent or group. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
x
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The initial size. |
100.0
|
lambda_low
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The lower bound of the multiplicative factor. |
0.48
|
lambda_high
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The upper bound of the multiplicative factor. |
1.48
|
b_low
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The lower bound of the additive term. |
0.0
|
b_high
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The upper bound of the additive term. |
1.0
|
Examples:
>>> from skcomplex.core.components.elements import GroupElement
>>> from skcomplex.systems.economics.finance import KestenFirmElement
>>> GroupElement('firms', element=KestenFirmElement, size=10, values={'b_high': 2.0}).size
10
Source code in src/skcomplex/systems/economics/finance/_growth_processes.py
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | |
get_growth(agent, system)
staticmethod
Return the size multiplied by a random factor plus a random term.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
KestenFirmView
|
The firm. |
required |
system
|
SystemView
|
The system view of the growth. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
size |
float
|
The size after the step. |
Source code in src/skcomplex/systems/economics/finance/_growth_processes.py
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | |
MarketAssetElement(label, visual=None, *, price=1.0, liquidated=0.0)
Bases: Element
Asset held by banks, whose price falls with the share of it liquidated, p = exp(-alpha x).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the agent or group. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
price
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The price of the asset, 1 before any sale. |
1.0
|
liquidated
|
Annotated[float, StateSpec(domain=closed(0, 1))]
|
The share of the asset sold so far. |
0.0
|
Examples:
>>> from skcomplex.core.components.elements import GroupElement
>>> from skcomplex.systems.economics.finance import MarketAssetElement
>>> GroupElement('assets', element=MarketAssetElement, size=4).size
4
Source code in src/skcomplex/systems/economics/finance/_fire_sales.py
56 57 58 59 60 61 62 63 64 65 66 | |
NetworkSaverElement(label, visual=None, *, W=1.0, J=1.0, sigma=0.5, degree=1.0)
Bases: Element
Saver of Bouchaud and Mezard, whose wealth earns random returns and flows to and from its exchange partners.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the saver. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
W
|
Annotated[object, StateSpec(domain=open(0, oo))]
|
The wealth. |
1.0
|
J
|
Annotated[object, ParameterSpec(domain=closed_open(0, oo))]
|
The exchange rate with the partners. |
1.0
|
sigma
|
Annotated[object, ParameterSpec(domain=closed_open(0, oo))]
|
The volatility of the returns. |
0.5
|
degree
|
Annotated[object, ParameterSpec(domain=open(0, oo))]
|
The mean number of exchange partners |
1.0
|
Examples:
>>> from skcomplex.systems.economics.finance import NetworkSaverElement
>>> NetworkSaverElement('saver', W=2.0).W
2.0
Source code in src/skcomplex/systems/economics/finance/_wealth.py
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | |
PaymentClearingInteraction(label, *, rule=None, phase=None, banks, liabilities=())
Bases: FeedbackInteraction[SystemView]
Clearing of interbank payments by the iteration p <- min(p_bar, e + Pi^T p) of Eisenberg and Noe.
Every step every bank pays the smaller of what it owes, p_bar_i = sum_j L_ij, and what it has, its external assets
plus the payments it receives, which its debtors make in proportion to their liabilities, Pi_ij = L_ij / p_bar_i.
From full payments the iteration falls to the greatest clearing vector, and a bank that pays less than it owes
defaults.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the clearing. |
required |
rule
|
None
|
Unused, since the clearing overrides |
None
|
phase
|
str | None
|
The phase the clearing acts in, or |
None
|
banks
|
Annotated[str, RoleSpec()]
|
The path of the group of banks. |
required |
liabilities
|
Sequence[Sequence[float]]
|
The interbank liabilities, |
()
|
Examples:
>>> from skcomplex.systems.economics.finance import PaymentClearingInteraction
>>> PaymentClearingInteraction('clearing', banks='banks').reports
('shortfall', 'defaults')
Source code in src/skcomplex/systems/economics/finance/_solvency.py
128 129 130 131 132 133 134 135 136 137 138 139 | |
act(system)
Make one round of payments and record the shortfall and the defaults.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system
|
SystemView
|
The system view of the clearing. |
required |
Source code in src/skcomplex/systems/economics/finance/_solvency.py
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | |
ReflectingFloorInteraction(label, *, target, c=0.9, phase=None)
Bases: MapInteraction
Lower bound on the sizes of a group at a fraction of their mean before the step, x = max(x, c <x_{t-1}>).
It is a map of the agent form that raises every size below the floor to the floor, the mean of the states
previous of the group times c.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the group of firms. |
required |
c
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The fraction of the previous mean size below which no size falls. |
0.9
|
phase
|
str | None
|
The phase of the step the floor acts in, or |
None
|
Examples:
>>> from skcomplex.systems.economics.finance import ReflectingFloorInteraction
>>> ReflectingFloorInteraction('floor', target='firms', c=0.5).c
0.5
Source code in src/skcomplex/systems/economics/finance/_growth_processes.py
210 211 212 213 214 215 216 217 218 219 | |
StockTraderElement(label, visual=VisualSpec('agents', {'color_by': 'strategy', 'color_range': (0.0, 1.0)}), *, strategy=0.0, money=1000.0, shares=10.0, bid=0.0, ask=0.0, demand=0.0, supply=0.0, wealth=0.0, gain=0.0, fundamental=100.0, reversion=0.2, extrapolation=1.0, noise=0.02)
Bases: Element
Trader who forecasts the price as a fundamentalist or a chartist, quotes a limit order, and imitates.
A fundamentalist expects the price p to revert to the fundamental value F, p + reversion (F - p), and a
chartist expects the last change to go on, p + extrapolation (p - p'), both with a relative noise. The trader
bids its expectation for one share when it is above the price and it can pay, and asks its expectation for one
share when it is below and it holds one. After trading, an ImitationInteraction of rule 'better' lets a trader
whose wealth grew less than that of a random neighbour copy the neighbour's strategy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the agent or group. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
VisualSpec('agents', {'color_by': 'strategy', 'color_range': (0.0, 1.0)})
|
strategy
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
0 for a fundamentalist, 1 for a chartist. |
0.0
|
money
|
Annotated[float, StateSpec()]
|
The money of the trader. |
1000.0
|
shares
|
Annotated[float, StateSpec()]
|
The shares of the trader. |
10.0
|
bid
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The limit price of a buy order. |
0.0
|
ask
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The limit price of a sell order. |
0.0
|
demand
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The shares wanted in the step. |
0.0
|
supply
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The shares offered in the step. |
0.0
|
wealth
|
Annotated[float, StateSpec()]
|
The money plus the shares at the last price. |
0.0
|
gain
|
Annotated[float, StateSpec()]
|
The change of the wealth in the last step. |
0.0
|
fundamental
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The fundamental value of the share. |
100.0
|
reversion
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The share of the gap to the fundamental value a fundamentalist expects to close. |
0.2
|
extrapolation
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The share of the last change of the price a chartist expects to repeat. |
1.0
|
noise
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The standard deviation of the relative noise of a forecast. |
0.02
|
Examples:
>>> from skcomplex.core.components.elements import GroupElement
>>> from skcomplex.systems.economics.finance import StockTraderElement
>>> GroupElement('traders', element=StockTraderElement, size=4, values={'strategy': 1.0}).size
4
Source code in src/skcomplex/systems/economics/finance/_order_book.py
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | |
get_gain(agent, system)
staticmethod
Return the change of the wealth valued at the last price, zero before the first valuation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
StockTraderView
|
The trader. |
required |
system
|
SystemView
|
The system view of the accounting. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
gain |
float
|
The change of the wealth in the step. |
Source code in src/skcomplex/systems/economics/finance/_order_book.py
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | |
get_wealth(agent, system)
staticmethod
Return the money plus the shares valued at the last price.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
StockTraderView
|
The trader. |
required |
system
|
SystemView
|
The system view of the accounting. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
wealth |
float
|
The wealth of the trader. |
Source code in src/skcomplex/systems/economics/finance/_order_book.py
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | |
quote(agent, system)
Forecast the price and quote a limit order for one share.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
StockTraderView
|
The trader. |
required |
system
|
SystemView
|
The system. |
required |
Source code in src/skcomplex/systems/economics/finance/_order_book.py
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
SwitchingExchangeElement(label, visual=None, *, x=0.1, k=50, n_traders=100.0, r=0.01, v=0.5, g=1.0, sigma=0.01, epsilon=0.002, delta=0.01)
Bases: Element
Foreign exchange market whose rate deviation follows the share of fundamentalists of Kirman's recruitment chain.
The deviation x = s - s* of the exchange rate from its fundamental value follows Eq. 1.36 of Caiani et al.
(2016), (1 + r) x_t = [1 - v n_t + g (1 - n_t)] x_t-1 - g (1 - n_t) x_t-2 + sigma eps_t, with a standard normal
shock eps_t of the supply of foreign exchange. Of the N traders, k are fundamentalists, n = k / N. Every
step one trader meets another at random, after Kirman (1993): a chartist turns fundamentalist with probability
(1 - k / N) (epsilon + (1 - delta) k / (N - 1)) and a fundamentalist turns chartist with probability
(k / N) (epsilon + (1 - delta) (N - k) / (N - 1)), by a spontaneous change epsilon or by recruitment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the market. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
x
|
Annotated[float, StateSpec(lags=1)]
|
The deviation of the exchange rate from its fundamental value. |
0.1
|
k
|
Annotated[float, StateSpec(domain=NN)]
|
The number of fundamentalists. |
50
|
n_traders
|
Annotated[float, ParameterSpec(domain=open(1, oo))]
|
The number of traders |
100.0
|
r
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The interest rate of the domestic currency. |
0.01
|
v
|
Annotated[float, ParameterSpec(domain=closed(0, 1))]
|
The share of the deviation that fundamentalists expect to close. |
0.5
|
g
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The share of the last change that chartists expect to repeat. |
1.0
|
sigma
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The standard deviation of the shocks of the deviation. |
0.01
|
epsilon
|
Annotated[float, ParameterSpec(domain=closed(0, 1))]
|
The probability of a spontaneous change of strategy. |
0.002
|
delta
|
Annotated[float, ParameterSpec(domain=closed(0, 1))]
|
One minus the probability that a trader recruits the trader it meets. |
0.01
|
Examples:
>>> from skcomplex.systems.economics.finance import SwitchingExchangeElement
>>> SwitchingExchangeElement('market', g=1.2).g
1.2
Source code in src/skcomplex/systems/economics/finance/_switching_exchange.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | |
get_share(s)
staticmethod
Return the share of fundamentalists n = k / N.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
s
|
SimpleNamespace
|
The namespace of the market. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
share |
Expression
|
The share of fundamentalists. |
Source code in src/skcomplex/systems/economics/finance/_switching_exchange.py
96 97 98 99 100 101 102 103 104 105 106 107 108 | |
TraderCurrentInteraction(label, *, target, links, D=0.5, q=0.2)
Bases: NeighborInteraction
Trader current J = -D (rho_t - rho_s - q A (rho_s + rho_t) / 2) along the links, down the covariant gradient.
The covariant derivative is D_mu = d_mu - A_mu of Schwichtenberg (2020 Eq. 2.55), with the charge q of its
Eq. 4.24, and the current is minus the diffusion constant times this derivative of the good, as in Eq. 2.56. The
current moves the good from the source of a link to its target (footnote 18 of §2.1), and it is the source of the
field of the link with the sign of the Ampere-Maxwell law of Eq. 2.39, E' = ... - J, so the Gauss law holds as the
good moves. These signs give the potential a mass, A'' = ... - D q rho A, for a positive density and charge, so
the fields stay bounded.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction, unique among the parts of its system. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the group on the sites. |
required |
links
|
Annotated[str, RoleSpec()]
|
The path of the group on the edges. |
required |
D
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The diffusivity of the good. |
0.5
|
q
|
Annotated[float, ParameterSpec()]
|
The charge of the good. |
0.2
|
Examples:
>>> from skcomplex.systems.economics.finance import TraderCurrentInteraction
>>> TraderCurrentInteraction('current', target='sites', links='links', q=0.5).q
0.5
Source code in src/skcomplex/systems/economics/finance/_gauge_arbitrage.py
136 137 138 139 140 141 142 143 144 145 146 147 148 149 | |
arbitrage_traders(n_sites=200, *, length=20.0, D=0.5, A_x=0.0, E=0.5, A_t=0.0)
Return Schwichtenberg's diffusion of a good by random-walk traders, minimally coupled to exchange rates.
The density of the good follows (d_t - A_t) rho = D (d_x - A_x(t))^2 rho on a periodic line, with the exchange
rate connection A_x(t) = A_x + E t. The arbitrage opportunity is the field strength F_tx = E. Without it, the
traders diffuse the good symmetrically, and with it, they drift at the velocity 2 D A_x(t).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_sites
|
int
|
The number of sites of the line. |
200
|
length
|
float
|
The length of the line. |
20.0
|
D
|
float
|
The diffusion constant of the traders. |
0.5
|
A_x
|
float
|
The initial spatial component of the exchange rate connection. |
0.0
|
E
|
float
|
The arbitrage field strength, the growth rate of the spatial component. |
0.5
|
A_t
|
float
|
The temporal component of the exchange rate connection. |
0.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the density of the good |
Examples:
>>> from skcomplex.systems.economics.finance import arbitrage_traders
>>> arbitrage_traders(50).elements[0].values['E']
0.5
Source code in src/skcomplex/systems/economics/finance/_arbitrage.py
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | |
bouchaud_mezard_wealth(n_agents=20, *, graph=None, J=1.0, sigma=0.5, wealth=1.0)
Return Bouchaud and Mezard's wealth dynamics, random multiplicative returns with exchange between neighbours.
Agent i follows the Stratonovich equation dW_i = sigma W_i dB_i + (J / c) sum_j (W_j - W_i) dt over its
neighbours j on a network of mean degree c. Without a graph, the agents are the members of a group and every
agent exchanges with every other, c = N - 1, the complete graph at a cost linear in the number of agents. A given
graph keeps the agents on a field over its edges. Exchange conserves the total wealth, and on the complete graph
the relative wealth W_i / <W> approaches a stationary distribution with the Pareto tail
P(W_i / <W> > w) ~ w^-mu of exponent mu = 1 + 2 J / sigma^2.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_agents
|
int
|
The number of agents, used when no graph is given. |
20
|
graph
|
object
|
The NetworkX graph of the exchanges, or |
None
|
J
|
float
|
The exchange rate between agents. |
1.0
|
sigma
|
float
|
The volatility of the returns. |
0.5
|
wealth
|
float | Sequence[float]
|
The initial wealth of every agent, or one value per agent. |
1.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the wealth |
Examples:
>>> from skcomplex.systems.economics.finance import bouchaud_mezard_wealth
>>> bouchaud_mezard_wealth(10).elements[0].values['J']
1.0
Source code in src/skcomplex/systems/economics/finance/_wealth.py
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | |
correlated_geometric_brownian_motion(prices=(100.0, 100.0), *, mu=(0.05, 0.08), sigma=(0.2, 0.3), rho=0.7)
Return two assets whose prices follow geometric Brownian motions driven by correlated Wiener processes.
A WienerProcessSpec of dimension 2 with the covariance [[1, rho], [rho, 1]] drives the two prices, so their log
returns over a short time have the correlation rho.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prices
|
tuple[float, float]
|
The initial prices of the two assets. |
(100.0, 100.0)
|
mu
|
tuple[float, float]
|
The drifts of the two assets. |
(0.05, 0.08)
|
sigma
|
tuple[float, float]
|
The volatilities of the two assets. |
(0.2, 0.3)
|
rho
|
float
|
The correlation of the two Wiener processes, from -1 to 1. |
0.7
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the assets |
Examples:
>>> from skcomplex.systems.economics.finance import correlated_geometric_brownian_motion
>>> correlated_geometric_brownian_motion(rho=0.5).interactions[1].process.covariance
[[1.0, 0.5], [0.5, 1.0]]
Source code in src/skcomplex/systems/economics/finance/_correlated_assets.py
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |
debtrank(liabilities=None, capital=None, *, distressed=(0,), psi=1.0, n_banks=10, density=0.3, random_state=0)
Return the DebtRank cascade of distress from a set of banks through their interbank loans.
liabilities[i][j] is the loan from bank j to bank i, which j loses when i defaults, and the impact of i
on j is min(1, liabilities[i][j] / capital[j]). The banks in distressed start with distress psi. The
DebtRank is the final value at risk minus the initial one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
liabilities
|
Sequence[Sequence[float]] | None
|
The interbank liabilities, or |
None
|
capital
|
Sequence[float] | None
|
The capital of every bank, or |
None
|
distressed
|
Sequence[int]
|
The indices of the banks distressed at the start. |
(0,)
|
psi
|
float
|
The initial distress of those banks, where 1 is default. |
1.0
|
n_banks
|
int
|
The number of banks of a random network. |
10
|
density
|
float
|
The probability of a loan between two banks of a random network. |
0.3
|
random_state
|
int | Generator | None
|
The seed or generator of a random network. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the group |
Examples:
>>> from skcomplex.systems.economics.finance import debtrank
>>> debtrank([[0.0, 5.0], [0.0, 0.0]], [10.0, 10.0]).elements[0].prepare().size_
2
Source code in src/skcomplex/systems/economics/finance/_contagion.py
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | |
default_cascade(liabilities=None, equity=None, *, shocked=(0,), shock=1.0, threshold=0.0, recovery=0.0, n_banks=250, degree=4.0, interbank_share=0.2, capital_ratio=0.04, random_state=0)
Return a cascade of defaults through interbank exposures, from a shock to the external assets of some banks.
Banks are linked by contracts, liabilities[i][j] the amount bank i owes bank j. A bank whose equity falls
below the threshold h defaults, and its creditors write off their claims on it, losing (1 - R) L_ij of their
equity at the next step, which may default them in turn. This is the cascade of Thurner et al. (2018, Section
5.5.3.2), and with h = 0 and the recovery rate R = 0 it is the contagion on default of Gai and Kapadia (2010) as
Bardoscia et al. (2021, Section 3.1) review it. The shocked banks lose the share shock of their external assets at
the start. Without a given network, every bank has assets of 100, a fifth of them interbank claims split evenly over
a random number of debtors of mean degree, and capital of 4 percent, the network of Gai and Kapadia, whose
cascades are large in a window of intermediate degrees and rare for sparse or dense networks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
liabilities
|
Sequence[Sequence[float]] | None
|
The interbank liabilities, or |
None
|
equity
|
Sequence[float] | None
|
The equity of every bank before the shock, or |
None
|
shocked
|
Sequence[int]
|
The indices of the banks whose external assets the shock hits. |
(0,)
|
shock
|
float
|
The share of their external assets the shocked banks lose. |
1.0
|
threshold
|
float
|
The equity below which a bank defaults. |
0.0
|
recovery
|
float
|
The share of a claim on a defaulted bank that its creditor recovers. |
0.0
|
n_banks
|
int
|
The number of banks of the random network. |
250
|
degree
|
float
|
The mean number of debtors of a bank of the random network. |
4.0
|
interbank_share
|
float
|
The share of the assets of a bank of the random network that are interbank claims. |
0.2
|
capital_ratio
|
float
|
The capital of a bank of the random network as a share of its assets. |
0.04
|
random_state
|
int | Generator | None
|
The seed or generator of the random network. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the group |
Examples:
>>> from skcomplex.systems.economics.finance import default_cascade
>>> default_cascade([[0.0, 5.0], [0.0, 0.0]], [1.0, 2.0]).elements[0].prepare().size_
2
Source code in src/skcomplex/systems/economics/finance/_solvency.py
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | |
eisenberg_noe_clearing(liabilities=None, external=None, *, n_banks=50, density=0.1, random_state=0)
Return the clearing of interbank payments of Eisenberg and Noe, a fixed point of proportional payments.
Bank i owes L_ij to bank j, p_bar_i in all, and holds external assets e_i. A clearing vector pays
p_i = min(p_bar_i, e_i + sum_j Pi_ji p_j), every bank paying in full or all it has, its debtors paying in
proportion Pi_ij = L_ij / p_bar_i, the liquidity contagion of Bardoscia et al. (2021, Section 3.1). Every step is
one round of the iteration from full payments, which falls monotonically to the greatest clearing vector, the
solution of the linear programme max sum_i p_i with p <= p_bar and p <= e + Pi^T p. Without a given network
the liabilities are random and the external assets are small for a few banks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
liabilities
|
Sequence[Sequence[float]] | None
|
The interbank liabilities, or |
None
|
external
|
Sequence[float] | None
|
The external assets of every bank, or |
None
|
n_banks
|
int
|
The number of banks of a random network. |
50
|
density
|
float
|
The probability of a liability between two banks of a random network. |
0.1
|
random_state
|
int | Generator | None
|
The seed or generator of a random network. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the group |
Examples:
>>> from skcomplex.systems.economics.finance import eisenberg_noe_clearing
>>> eisenberg_noe_clearing([[0.0, 2.0], [1.0, 0.0]], [0.5, 1.0]).elements[0].prepare().size_
2
Source code in src/skcomplex/systems/economics/finance/_solvency.py
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | |
gauge_arbitrage_market(size=16, *, D=0.5, q=0.2, bump=1.0, seed=0)
Return exchange-rate potentials on links as lattice Maxwell fields, sourced by traders who move a good on sites.
The potentials follow A_t = E and E_t = -codifferential(dA) - J, and the good follows rho_t =
-codifferential(J) with the current J = -D (d rho - q A rho) along its covariant gradient, after Schwichtenberg
(2020 §2.1 and §2.2.1). Here E is F_0i of the book, so codifferential(E) equals the excess of the good over
its mean, as in its Gauss law, Eq. 2.37, with a uniform background of the mean density that keeps the periodic
lattice neutral. The system departs from the book in two places. The book writes Eq. 2.39 with no metric, which
gives A_tt = +codifferential(dA) - J, where every mode with a curl grows, so the system takes the sign of a wave.
And Eq. 2.56 applies the covariant derivative twice, which does not conserve the good, so the system applies it once
inside the divergence of the current. The book gives no values of D and q and sets mu_0 by no number, so D,
q, and mu_0 = 1 are choices of this system.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
size
|
int
|
The number of sites along both axes. |
16
|
D
|
float
|
The diffusivity of the good. |
0.5
|
q
|
float
|
The charge of the good. |
0.2
|
bump
|
float
|
The height of the random part of the initial density above a density of 1. |
1.0
|
seed
|
int
|
The seed of the initial density. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system. |
Examples:
>>> from skcomplex.systems.economics.finance import gauge_arbitrage_market
>>> [element.label for element in gauge_arbitrage_market(4).elements]
['sites', 'links']
Source code in src/skcomplex/systems/economics/finance/_gauge_arbitrage.py
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | |
geometric_brownian_motion(price=100.0, *, mu=0.05, sigma=0.2)
Return an asset whose price follows geometric Brownian motion.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
price
|
float
|
The initial price. |
100.0
|
mu
|
float
|
The drift. |
0.05
|
sigma
|
float
|
The volatility. |
0.2
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the asset |
Examples:
>>> from skcomplex.systems.economics.finance import geometric_brownian_motion
>>> geometric_brownian_motion(sigma=0.3).interactions[0].sigma
0.3
Source code in src/skcomplex/systems/economics/finance/_assets.py
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
gibrat_process(n_firms=200, *, x=100.0, mu=1.02, sigma=0.05)
Return firms that grow by Gibrat's law of proportionate effect, which makes their sizes lognormal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_firms
|
int
|
The number of firms. |
200
|
x
|
float
|
The initial size of every firm. |
100.0
|
mu
|
float
|
The mean of the growth factor. |
1.02
|
sigma
|
float
|
The standard deviation of the growth factor. |
0.05
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the group |
Examples:
>>> from skcomplex.systems.economics.finance import gibrat_process
>>> gibrat_process(10).elements[0].prepare().size_
10
Source code in src/skcomplex/systems/economics/finance/_growth_processes.py
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | |
guru_order_book(n_traders=100, *, tau=100, beta_step=1.5, sigma=0.01, cash=1000.0, stocks=100.0, opening=10.0, random_state=0)
Return the order-driven market of Grilli and Tedeschi, whose noise traders imitate gurus they choose by wealth.
Noise traders expect random returns of their own volatility, but every day each adopts the expectation of the
trader it follows on a directed communication network. Every day each trader moves its link to a random trader with
a logit probability of the difference of their wealths, whose intensity grows every day the guru, the most followed
trader, keeps its place, so followers concentrate on successful traders and their expectations synchronize. The
traders then place market and limit orders around a geometric Brownian forecast in an order book with price and
time priority, within the day. This is the model of Caiani et al. (2016, Chapter 3, Sections 3.2 and 3.4). Imitation
produces coordination periods in which most traders follow one guru, and the returns get fat tails and volatility
clusters. The source leaves two choices open: the volatilities are uniform on (0, sigma), and the intensity of
choice grows by beta_step every day the guru survives. The cash and the stocks of the traders are conserved,
which the default run checks as invariants.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_traders
|
int
|
The number of traders. |
100
|
tau
|
int
|
The intraday operations of a day. |
100
|
beta_step
|
float
|
The growth of the intensity of choice every day the guru survives. |
1.5
|
sigma
|
float
|
The largest volatility of the expected returns of a trader. |
0.01
|
cash
|
float
|
The initial cash of every trader. |
1000.0
|
stocks
|
float
|
The initial stocks of every trader. |
100.0
|
opening
|
float
|
The price before the first day. |
10.0
|
random_state
|
int | Generator | None
|
The seed or generator of the volatilities and the initial links. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the group |
Examples:
>>> from skcomplex.systems.economics.finance import guru_order_book
>>> guru_order_book(10).elements[0].prepare().size_
10
Source code in src/skcomplex/systems/economics/finance/_guru_order_book.py
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 | |
kesten_process(n_firms=200, *, x=100.0, lambda_low=0.48, lambda_high=1.48, b_low=0.0, b_high=1.0)
Return firms whose sizes follow Kesten's process, a random multiplicative factor plus a random positive term.
When the factor shrinks sizes on average, the additive term reinjects them, and the stationary distribution has a power-law tail.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_firms
|
int
|
The number of firms. |
200
|
x
|
float
|
The initial size of every firm. |
100.0
|
lambda_low
|
float
|
The lower bound of the multiplicative factor. |
0.48
|
lambda_high
|
float
|
The upper bound of the multiplicative factor. |
1.48
|
b_low
|
float
|
The lower bound of the additive term. |
0.0
|
b_high
|
float
|
The upper bound of the additive term. |
1.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the group |
Examples:
>>> from skcomplex.systems.economics.finance import kesten_process
>>> kesten_process(10).elements[0].prepare().size_
10
Source code in src/skcomplex/systems/economics/finance/_growth_processes.py
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 | |
kirman_exchange_rate(x=0.1, k=15, *, n_traders=30, r=0.01, v=0.5, g=1.0, sigma=0.01, epsilon=0.005, delta=0.01)
Return Kirman's foreign exchange market, whose traders switch between fundamentalism and chartism like ants.
Fundamentalists expect the exchange rate to revert to its fundamental value, s_t-1 + v (s* - s_t-1), and chartists
expect the last change to go on, s_t-1 + g (s_t-1 - s_t-2). With the mean-variance demand of both and the share
n_t of fundamentalists, the market clears at the deviation of Eq. 1.36 of Caiani et al. (2016, Section 1.3.2),
(1 + r) x_t = [1 - v n_t + g (1 - n_t)] x_t-1 - g (1 - n_t) x_t-2, written there with s_t-2 for x_t-2, a shock
of the supply of foreign exchange added. The share follows the recruitment chain of Kirman's ants, which the source
refers to and Kirman (1993) gives: when spontaneous changes are rarer than recruitment, epsilon < (1 - delta) /
(N - 1), the traders spend long periods mostly of one kind and switch suddenly. A market of fundamentalists is
stable with the eigenvalue (1 - v) / (1 + r) (Eq. 1.37), and a market of chartists oscillates, stable only while
g <= 1 + r (Eq. 1.38), so the volatility of the rate comes and goes with the chartists. One trader meets another
every step, so the defaults take a small market of 30 traders, whose regimes switch within a few thousand steps.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
float
|
The initial deviation of the exchange rate from its fundamental value, also its value one step earlier. |
0.1
|
k
|
int
|
The initial number of fundamentalists. |
15
|
n_traders
|
int
|
The number of traders. |
30
|
r
|
float
|
The interest rate of the domestic currency. |
0.01
|
v
|
float
|
The share of the deviation that fundamentalists expect to close. |
0.5
|
g
|
float
|
The share of the last change that chartists expect to repeat. |
1.0
|
sigma
|
float
|
The standard deviation of the shocks of the deviation. |
0.01
|
epsilon
|
float
|
The probability of a spontaneous change of strategy. |
0.005
|
delta
|
float
|
One minus the probability that a trader recruits the trader it meets. |
0.01
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the deviation |
Examples:
>>> from skcomplex.systems.economics.finance import kirman_exchange_rate
>>> kirman_exchange_rate(g=1.2).elements[0].g
1.2
Source code in src/skcomplex/systems/economics/finance/_switching_exchange.py
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | |
multiplicative_process(n_firms=200, *, x=100.0, mu=1.02, sigma=0.05, c=0.9)
Return Levy and Solomon's multiplicative process, whose floor at a fraction of the mean makes a power-law tail.
Every size is multiplied by a normal growth factor and then raised to c times the mean size of the step before
if it fell below it. With c = 0 the process is Gibrat's.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_firms
|
int
|
The number of firms. |
200
|
x
|
float
|
The initial size of every firm. |
100.0
|
mu
|
float
|
The mean of the growth factor. |
1.02
|
sigma
|
float
|
The standard deviation of the growth factor. |
0.05
|
c
|
float
|
The fraction of the previous mean size below which no size falls. |
0.9
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the group |
Examples:
>>> from skcomplex.systems.economics.finance import multiplicative_process
>>> multiplicative_process(c=0.5).interactions[-1].c
0.5
Source code in src/skcomplex/systems/economics/finance/_growth_processes.py
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 | |
order_book(width=20, height=20, *, chartists=0.3, fundamental=100.0, reversion=0.2, extrapolation=1.0, noise=0.02, imitation=0.1, random_state=0)
Return a stock market of fundamentalists and chartists on a grid who trade in a limit order book and imitate.
Every step every trader forecasts the price, as a fundamentalist who expects it to revert to the fundamental value or as a chartist who expects the last change to go on, and quotes a limit order for one share at its forecast. The order book matches the orders with price-time priority, and every trade moves money and a share between the two traders. Then traders copy the strategy of a neighbour whose wealth grew more. Fundamentalists hold the price near the fundamental value, chartists amplify its swings, and imitation lets the share of chartists wander, so the returns come in bursts with fat tails.
The two strategies are the fundamentalists and chartists of Lux and Marchesi (1999), and imitating a wealthier neighbour on the grid stands in for their switching between strategies. The order book is the order-driven market of Caiani et al. (2016, section 3.2.1). The traders of Caiani's chapter 3, noise traders who follow gurus of an evolving network, are a different model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
width
|
int
|
The number of columns of the grid, with one trader per cell. |
20
|
height
|
int
|
The number of rows of the grid. |
20
|
chartists
|
float
|
The initial share of chartists. |
0.3
|
fundamental
|
float
|
The fundamental value of the share. |
100.0
|
reversion
|
float
|
The share of the gap to the fundamental value a fundamentalist expects to close. |
0.2
|
extrapolation
|
float
|
The share of the last change of the price a chartist expects to repeat. |
1.0
|
noise
|
float
|
The standard deviation of the relative noise of a forecast. |
0.02
|
imitation
|
float
|
The probability that a trader looks at a neighbour in a step. |
0.1
|
random_state
|
int | Generator | None
|
The seed or generator of the initial strategies. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the group |
Examples:
>>> from skcomplex.systems.economics.finance import order_book
>>> order_book(5, 5).elements[0].prepare().size_
25
Source code in src/skcomplex/systems/economics/finance/_order_book.py
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 | |
overlapping_portfolio_fire_sales(n_banks=100, n_assets=100, *, diversification=10, leverage=20.0, alpha=1.0, shocked=0, shock=0.2, selling='threshold', random_state=0)
Return banks with overlapping portfolios whose fire sales of common assets spread their losses to one another.
Every bank invests equal amounts in diversification assets drawn at random, a bipartite network of banks and
assets, with assets leverage times its equity. A shock lowers the price of one asset, and banks react to their
losses: under the linear threshold rule a bank stays passive until its losses exhaust its equity and then
liquidates its whole portfolio, and under leverage targeting it sells a share of every holding to restore its
leverage. Sales lower prices through the market impact p = p0 exp(-alpha x) of the share x of an asset
liquidated, which hits every bank holding the asset, so losses travel between banks that share no contract, the
indirect contagion of Bardoscia et al. (2021, Section 3.2) after Caccioli et al. (2014). Larger impact and leverage
make the cascades larger, and leverage targeting sells more for small shocks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_banks
|
int
|
The number of banks. |
100
|
n_assets
|
int
|
The number of assets. |
100
|
diversification
|
int
|
The number of assets in every portfolio. |
10
|
leverage
|
float
|
The ratio of assets to equity of every bank, and the target of leverage targeting. |
20.0
|
alpha
|
float
|
The market impact. |
1.0
|
shocked
|
int
|
The index of the asset the shock hits. |
0
|
shock
|
float
|
The share of its price the shocked asset loses. |
0.2
|
selling
|
str
|
The rule of the banks, |
'threshold'
|
random_state
|
int | Generator | None
|
The seed or generator of the portfolios. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The system, with the groups |
Examples:
>>> from skcomplex.systems.economics.finance import overlapping_portfolio_fire_sales
>>> [group.prepare().size_ for group in overlapping_portfolio_fire_sales(10, 5, diversification=2).elements]
[10, 5]
Source code in src/skcomplex/systems/economics/finance/_fire_sales.py
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | |