Markets
Markets: prices, competition, retail, inventories, queues, and barter of Cobb-Douglas traders on trade networks.
AuctionLedgerInteraction(label, *, rule=None, phase=None)
Bases: FeedbackInteraction[ModelView]
Ledger that closes every trading period: it measures its surplus and gives every trader a new unit.
The realised surplus is the value of the units bought minus the cost of the units sold, and the allocative efficiency is its ratio to the maximum surplus of the supply and demand schedules.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the ledger. |
required |
phase
|
str | None
|
The phase the ledger acts in. |
None
|
Examples:
>>> from skcomplex.models.economics.markets import AuctionLedgerInteraction
>>> AuctionLedgerInteraction('ledger', phase='close').reports
('surplus', 'efficiency')
Source code in src/skcomplex/core/interactions/_feedback.py
41 42 43 44 45 46 47 48 49 50 | |
act(model)
Report the surplus and the efficiency of the trading period and open the next one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
ModelView
|
The model view scoped to the ledger. |
required |
Source code in src/skcomplex/models/economics/markets/_auction_ledger.py
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
BarterTraderElement(label, visual=None, *, good1=10.0, good2=10.0, mrs=1.0, links=0.0, partners=math.inf)
Bases: Element
Trader with a bundle of two goods and the Cobb-Douglas utility good1 good2, who records its rate.
Its marginal rate of substitution good2 / good1 is the price of the first good, in units of the second, at
which it is indifferent to trade. Every step it records the rate of its current bundle.
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
|
good1
|
Annotated[float, StateSpec(domain=open(0, oo))]
|
The holding of the first good. |
10.0
|
good2
|
Annotated[float, StateSpec(domain=open(0, oo))]
|
The holding of the second good. |
10.0
|
mrs
|
Annotated[float, StateSpec(domain=open(0, oo))]
|
The marginal rate of substitution of the bundle. |
1.0
|
links
|
Annotated[float, StateSpec(domain=NN)]
|
The number of trading partners the trader can search. |
0.0
|
partners
|
Annotated[float, StateSpec()]
|
The number of partners that can match with the trader in a step, without limit. |
inf
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import BarterTraderElement
>>> GroupElement('traders', element=BarterTraderElement, size=4).size
4
Source code in src/skcomplex/models/economics/markets/_barter_trader.py
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
get_rate(agent, model)
staticmethod
Return the marginal rate of substitution of the bundle, good2 / good1.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
BarterTraderView
|
The trader. |
required |
model
|
ModelView
|
The model view of the appraisal. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
mrs |
float
|
The marginal rate of substitution. |
Source code in src/skcomplex/models/economics/markets/_barter_trader.py
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | |
get_rate_gap(trader, other)
staticmethod
Return the gap between the logarithms of the rates of substitution of a trader and a trading partner.
The gap is minus infinity for a trader that is not a partner, so a trader takes a partner whenever it has one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trader
|
object
|
The trader that searches. |
required |
other
|
object
|
Another trader. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
gap |
float
|
The absolute difference of the logarithms of the two rates. |
Source code in src/skcomplex/models/economics/markets/_barter_trader.py
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | |
is_partner(trader, other)
staticmethod
Return whether another trader is a trading partner of a trader, a neighbour on the trade network.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trader
|
object
|
The trader that searches. |
required |
other
|
object
|
Another trader. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
partner |
bool
|
Whether the other trader is in a node next to the trader's node. |
Source code in src/skcomplex/models/economics/markets/_barter_trader.py
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | |
BartererElement(label, visual=VisualSpec('agents', {'color_by': 'chocolate_weight', 'color_range': (0.0, 1.0)}), *, chocolate=5.0, cigarettes=5.0, chocolate_weight=0.5, cigarettes_weight=0.5)
Bases: Element
Barterer who holds chocolate and cigarettes and values them with Cobb-Douglas weights.
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': 'chocolate_weight', 'color_range': (0.0, 1.0)})
|
chocolate
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The holding of chocolate. |
5.0
|
cigarettes
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The holding of cigarettes. |
5.0
|
chocolate_weight
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The Cobb-Douglas weight of chocolate. |
0.5
|
cigarettes_weight
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The Cobb-Douglas weight of cigarettes. |
0.5
|
Examples:
>>> from skcomplex.models.economics.markets import BartererElement
>>> GroupElement('barterers', element=BartererElement, size=2, values={'chocolate': [8.0, 2.0]}).size
2
Source code in src/skcomplex/models/economics/markets/_barter.py
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | |
BilateralBarterInteraction(label, *, requesters, providers, rule=RandomSearchSpec(), limit='limit', quantity='quantity', allowance='allowance', transfers=(), phase=None, on_match=None, units=100)
Bases: MatchingInteraction[ModelView]
Barter in which every trader trades with the neighbour it matched, the one whose rate differs the most.
A greedy matching pairs every trader, in random order, with the neighbour whose marginal rate of substitution
differs the most in logarithm, and a neighbour takes any number of partners. The score of a trader that is not a
neighbour is minus infinity, and a trader without neighbours trades with no one. Each pair trades single units of
the first good at the price (g2 + g2') / (g1 + g1') of their pooled bundles, which lies between their rates, while
the trade raises the utility of both. Besides the reporters of a matching, the reporters trades and searches
count the units traded and the neighbours searched in a step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
requesters
|
Annotated[str, RoleSpec()]
|
The path of the group of traders that search for a partner. |
required |
providers
|
Annotated[str, RoleSpec()]
|
The path of the group of traders that can be found, the same group. |
required |
rule
|
MatchingRule
|
The spec of the algorithm that pairs the traders, such as |
RandomSearchSpec()
|
limit
|
str | tuple[str, str]
|
The state with the limit of both sides, missing for traders, which then accept any partner. |
'limit'
|
quantity
|
str | tuple[str, str]
|
The states of the partners a requester wants and a provider takes, one and without limit for traders. |
'quantity'
|
allowance
|
str
|
The state of a requester with the most value it can give, missing for traders. |
'allowance'
|
transfers
|
Sequence[tuple[str, int]]
|
The states every match moves, none for traders, whose trades move the goods. |
()
|
phase
|
str | None
|
The phase the barter runs in, or |
None
|
on_match
|
Callable[[MatchSpec, ModelView], None] | None
|
A function of every match and the model view, run after the trade, or |
None
|
units
|
Annotated[int, ParameterSpec(domain=NN)]
|
The most units one pair trades in a step. |
100
|
Examples:
>>> from skcomplex.models.economics.markets import BilateralBarterInteraction
>>> BilateralBarterInteraction('barter', requesters='traders', providers='traders').units
100
Source code in src/skcomplex/models/economics/markets/_bilateral_barter.py
77 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 | |
match(model)
Pair and trade, and report the units traded and the neighbours searched besides the matching reporters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
ModelView
|
The model view of the interaction. |
required |
Source code in src/skcomplex/models/economics/markets/_bilateral_barter.py
139 140 141 142 143 144 145 146 147 148 149 150 | |
BreweryInteraction(label, *, factory)
Bases: TransferInteraction
Brewery of a supply chain, which brews the orders of the factory over its production delay.
The brewing is a transfer from the brewery into the beer in production at the factory and on to its inventory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the brewery. |
required |
factory
|
Annotated[str, RoleSpec()]
|
The path of the factory. |
required |
Examples:
>>> from skcomplex.models.economics.markets import BreweryInteraction
>>> BreweryInteraction('brewery', factory='factory').factory
'factory'
Source code in src/skcomplex/models/economics/markets/_brewery.py
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | |
CarDealershipElement(label, visual=None, *, inventory=200.0, demand=20.0, demand_step=2.0, step_time=25.0, coverage=10.0, perception_delay=5.0, response_delay=3.0, delivery_delay=5.0)
Bases: Element
Car dealership whose inventory deliveries fill and sales drain, ordered to close the gap to a desired coverage.
Sales are the demand, stepping up at step_time, limited by the inventory. The dealer perceives sales through a
first-order smoothing, desires coverage days of perceived sales, and orders the perceived sales plus the gap to
the desired inventory over the response delay, never negative. Orders arrive through a third-order delay. The
dealership holds the inventory and the parameters, and a transfer within it of the model moves the cars.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the dealership. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
inventory
|
Annotated[float, StateSpec(domain=closed_open(0, oo), quantity=cars)]
|
The initial number of cars on the lot. |
200.0
|
demand
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The customer demand in cars per day. |
20.0
|
demand_step
|
Annotated[float, ParameterSpec()]
|
The permanent change of the demand. |
2.0
|
step_time
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The day of the change of the demand. |
25.0
|
coverage
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The days of perceived sales the dealer wants on the lot. |
10.0
|
perception_delay
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The time over which the dealer averages sales. |
5.0
|
response_delay
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The time over which the dealer closes the inventory gap. |
3.0
|
delivery_delay
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The average time between an order and its delivery. |
5.0
|
Examples:
>>> from skcomplex.models.economics.markets import CarDealershipElement
>>> CarDealershipElement('dealer', inventory=150.0).inventory
150.0
Source code in src/skcomplex/models/economics/markets/_inventory.py
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | |
CarElement(label, visual=None, *, stage=WASH, work=525.0, crew=0)
Bases: Element
Car at the wash, waiting for or receiving a wash or a valet.
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
|
stage
|
Annotated[float, StateSpec(domain=NN)]
|
0 for the wash and 1 for the valet. |
WASH
|
work
|
Annotated[float, StateSpec()]
|
The person-seconds of work left at the current stage. |
525.0
|
crew
|
Annotated[float, StateSpec(domain=NN)]
|
The number of workers on the car in the current second. |
0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import CarElement
>>> GroupElement('cars', element=CarElement, size=1).size
1
Source code in src/skcomplex/models/economics/markets/_car.py
45 46 47 48 49 50 51 52 53 54 55 56 57 | |
CarWashOperationInteraction(label, *, cars, till, p_pass=0.33, p_enter=0.005, p_valet=0.5, wash_work=525.0, valet_work=1750.0, wash_price=4.0, valet_price=10.0, balk=3.0)
Bases: Interaction
Arrival of passing cars, completion of washes and valets, and payment, once every second.
A passing car turns in with a probability, unless the wash queue holds balk cars or more. A washed car stays for
a valet with a probability, and pays the wash price or the valet price when it leaves.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
cars
|
Annotated[str, RoleSpec()]
|
The path of the group of cars. |
required |
till
|
Annotated[str, RoleSpec()]
|
The path of the group that holds the till. |
required |
p_pass
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The probability that a car passes in a second. |
0.33
|
p_enter
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The probability that a passing car turns in. |
0.005
|
p_valet
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The probability that a washed car stays for a valet. |
0.5
|
wash_work
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The person-seconds of a wash. |
525.0
|
valet_work
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The person-seconds of a valet. |
1750.0
|
wash_price
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The price of a wash. |
4.0
|
valet_price
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The price of a wash with a valet. |
10.0
|
balk
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The length of the wash queue at which drivers no longer turn in. |
3.0
|
Examples:
>>> from skcomplex.models.economics.markets import CarWashOperationInteraction
>>> CarWashOperationInteraction('wash', cars='cars', till='till', p_enter=0.01).p_enter
0.01
Source code in src/skcomplex/models/economics/markets/_car_wash_operation.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 95 | |
operate(model)
Finish the cars whose work is done, reset the crews, and let a passing car turn in or drive on.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
ModelView
|
The model. |
required |
Source code in src/skcomplex/models/economics/markets/_car_wash_operation.py
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | |
CobwebInteraction(label, *, target, a=10.0, b=2.0, c=1.0, d=1.0)
Bases: MapInteraction
Cobweb model, where supply reacts to the previous price and demand clears the market.
Demand is a - b * price and supply is c + d * previous price, so the next price is
(a - c - d * price) / b, a map of the state price of the market.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the market. |
required |
a
|
Annotated[float, ParameterSpec()]
|
The demand intercept. |
10.0
|
b
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The demand slope. |
2.0
|
c
|
Annotated[float, ParameterSpec()]
|
The supply intercept. |
1.0
|
d
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The supply slope. |
1.0
|
Examples:
>>> from skcomplex.models.economics.markets import CobwebInteraction
>>> CobwebInteraction('cobweb', target='wheat', a=10, b=2, c=1, d=1).b
2
Source code in src/skcomplex/models/economics/markets/_cobweb.py
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | |
CommodityMarketElement(label, visual=None, *, inventory=25.0, capacity=100.0, demand=100.0, demand_step=10.0, step_time=2.0, desired_coverage=0.25, reference_price=1.0, supply_elasticity=0.1, demand_elasticity=0.25, expectation_time=1.0, construction_delay=3.0, lifetime=15.0)
Bases: Element
Commodity market whose inventory production fills and consumption drains, with capacity built after a delay.
The price is a falling table function of the coverage of the demand by the inventory relative to the desired coverage. Production is the capacity times the relative price to the supply elasticity, consumption the demand times the relative price to minus the demand elasticity. Capacity is ordered at the rate of retirements times a rising table function of the smoothed price, completed through a third-order delay, and retired over its lifetime. The market holds the stocks and the parameters, and transfers within it of the model move the commodity and the capacity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the market. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
inventory
|
Annotated[float, StateSpec(domain=closed_open(0, oo), quantity=commodity)]
|
The initial inventory of the commodity. |
25.0
|
capacity
|
Annotated[float, StateSpec(domain=closed_open(0, oo), quantity=capacity)]
|
The initial production capacity per year. |
100.0
|
demand
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The demand per year at the reference price. |
100.0
|
demand_step
|
Annotated[float, ParameterSpec()]
|
The permanent change of the demand. |
10.0
|
step_time
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The year of the change of the demand. |
2.0
|
desired_coverage
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The years of demand producers want the inventory to hold. |
0.25
|
reference_price
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The price at the desired coverage. |
1.0
|
supply_elasticity
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The elasticity of the utilization of capacity with respect to the price. |
0.1
|
demand_elasticity
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The elasticity of consumption with respect to the price, as a positive number. |
0.25
|
expectation_time
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The time over which producers smooth the price into their expected price. |
1.0
|
construction_delay
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The average time between an order of capacity and its completion. |
3.0
|
lifetime
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The average lifetime of capacity. |
15.0
|
Examples:
>>> from skcomplex.models.economics.markets import CommodityMarketElement
>>> CommodityMarketElement('market', lifetime=20.0).lifetime
20.0
Source code in src/skcomplex/models/economics/markets/_commodities.py
131 132 133 134 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 | |
ConsumerElement(label, visual=VisualSpec('agents', {'color_by': 'fair', 'color_range': (0.0, 1.0)}), *, fair=0.0, ethics=0.5, budget=2.0, premium=0.3, ethics_weight=2.0, price_weight=5.0, social_weight=2.0)
Bases: Element
Consumer who buys fair-trade or regular food, with an ethical concern, a budget, and the weights of its utility.
The utility of fair food is ethics_weight * ethics - price_weight * premium / budget + social_weight * share,
where share is the share of neighbours who bought fair food in the last step, and the utility of regular food is
zero. A consumer whose budget does not cover the price 1 + premium of fair food buys regular food.
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': 'fair', 'color_range': (0.0, 1.0)})
|
fair
|
Annotated[float, StateSpec(domain=FiniteEnumeratedSet([0, 1]))]
|
One when the consumer bought fair food in the last step, zero otherwise. |
0.0
|
ethics
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The ethical concern of the consumer, between zero and one. |
0.5
|
budget
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The money the consumer can spend on one unit of food, regular food costing one. |
2.0
|
premium
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The extra price of fair food over regular food. |
0.3
|
ethics_weight
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The weight of ethical concern in the utility of fair food. |
2.0
|
price_weight
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The weight of the premium relative to the budget. |
5.0
|
social_weight
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The weight of the share of neighbours who buy fair food. |
2.0
|
Examples:
>>> from skcomplex.models.economics.markets import ConsumerElement
>>> GroupElement('consumers', element=ConsumerElement, size=4, values={'ethics': 0.5}).size
4
Source code in src/skcomplex/models/economics/markets/_fair_food.py
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | |
CournotAdjustmentInteraction(label, *, target, a=1500.0, b=10.0, error=0.0)
Bases: MapInteraction
Simultaneous best responses of two firms to their beliefs about the rival's last output.
Under the inverse demand P = a - b Q, each firm sets q_i = (a - c_i) / (2 b) - belief_j / 2, where the
belief is the rival's last output scaled by a factor drawn uniformly from [1 - error, 1 + error]. It is a
synchronous map of the agent form of the outputs, so both firms respond to the outputs of the step before.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the group of the two firms. |
required |
a
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The intercept of the inverse demand. |
1500.0
|
b
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The slope of the inverse demand. |
10.0
|
error
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The largest relative error of a firm's belief about the rival's output. |
0.0
|
Examples:
>>> from skcomplex.models.economics.markets import CournotAdjustmentInteraction
>>> CournotAdjustmentInteraction('market', target='firms', error=0.1).check().error
0.1
Source code in src/skcomplex/models/economics/markets/_cournot_adjustment.py
46 47 48 49 50 51 52 53 54 55 56 57 58 | |
CournotBestResponseElement(label, *, q_i=0.0, q_j=0.0, demand=10.0, c_i=1.0, c_j=2.0, lambda_i=0.0, lambda_j=0.0)
Bases: Element
Quantities of two firms at the best responses of a Cournot game, where each firm holds a share of the other.
The conditions are alpha - 2 q_i - q_j = c_i / (1 + lambda_i) and its mirror (Forrest 2018 Eq. 21.5), whose
solution is q_i = (alpha - 2 c_i / (1 + lambda_i) + c_j / (1 + lambda_j)) / 3 (Eq. 21.6).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the element. |
required |
q_i
|
Annotated[float, StateSpec()]
|
The initial guess of the quantity of the first firm, which the equations replace. |
0.0
|
q_j
|
Annotated[float, StateSpec()]
|
The initial guess of the quantity of the second firm, which the equations replace. |
0.0
|
demand
|
Annotated[float, ParameterSpec()]
|
The intercept |
10.0
|
c_i
|
Annotated[float, ParameterSpec()]
|
The unit cost of the first firm. |
1.0
|
c_j
|
Annotated[float, ParameterSpec()]
|
The unit cost of the second firm. |
2.0
|
lambda_i
|
Annotated[float, ParameterSpec()]
|
The cross holding of the first firm. |
0.0
|
lambda_j
|
Annotated[float, ParameterSpec()]
|
The cross holding of the second firm. |
0.0
|
Examples:
>>> from skcomplex.models.economics.markets import CournotBestResponseElement
>>> CournotBestResponseElement('duopoly', demand=8.0).demand
8.0
Source code in src/skcomplex/models/economics/markets/_cournot_best_response.py
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
CustomerElement(label, visual=None, *, s1=0.5, s2=0.5, shop=0.0, freshness=1.0, T=0.1)
Bases: Element
Customer who remembers how satisfied it was with the products of each of two shops.
The customer visits the shop k of larger satisfaction S_k more often, with the logit utility S_k / T, and
holds the freshness of the product it bought last.
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
|
s1
|
Annotated[float, StateSpec()]
|
The satisfaction with the first shop. |
0.5
|
s2
|
Annotated[float, StateSpec()]
|
The satisfaction with the second shop. |
0.5
|
shop
|
Annotated[float, StateSpec(domain=FiniteEnumeratedSet([0, 1]))]
|
The index of the shop the customer visits, 0 or 1. |
0.0
|
freshness
|
Annotated[float, StateSpec(domain=closed(0, 1))]
|
The freshness of the product the customer bought last. |
1.0
|
T
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The temperature of the choice, the randomness of the customer. |
0.1
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import CustomerElement
>>> GroupElement('customers', element=CustomerElement, size=10, values={'s1': 0.5, 's2': 0.5}).size
10
Source code in src/skcomplex/models/economics/markets/_customer.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | |
destination(agent, model)
staticmethod
Return the node of the shop the customer chose.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
AgentViewProtocol
|
The customer. |
required |
model
|
ModelViewProtocol
|
The model view of the movement. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
node |
int | None
|
The node of the shop, or |
Source code in src/skcomplex/models/economics/markets/_customer.py
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | |
payoff(agent, model, option)
staticmethod
Return the freshness of the product the customer bought last, the payoff of the shop it visited.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
CustomerView
|
The customer. |
required |
model
|
ModelView
|
The model view of the reinforcement. |
required |
option
|
int
|
The index of the shop the customer visited. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
freshness |
float
|
The freshness of the product. |
Source code in src/skcomplex/models/economics/markets/_customer.py
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | |
preference(agent)
staticmethod
Return p_1 - p_2 = tanh((S_1 - S_2) / 2T), how much more likely the customer visits the first shop.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
CustomerView
|
The customer. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
preference |
float
|
The difference of the probabilities of visiting the first and the second shop. |
Source code in src/skcomplex/models/economics/markets/_customer.py
135 136 137 138 139 140 141 142 143 144 145 146 147 | |
utility(agent, model, option)
staticmethod
Return the utility S_k / T of visiting shop k.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
CustomerView
|
The customer. |
required |
model
|
ModelView
|
The model view of the choice. |
required |
option
|
float
|
The index of the shop. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
utility |
float
|
The satisfaction with the shop divided by the temperature. |
Source code in src/skcomplex/models/economics/markets/_customer.py
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | |
DuopolistElement(label, visual=None, *, output=50.0, cost=0.0)
Bases: Element
Firm of a Cournot duopoly, described by its output and its constant marginal cost.
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
|
output
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The initial output. |
50.0
|
cost
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The marginal cost. |
0.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import DuopolistElement
>>> GroupElement('firms', element=DuopolistElement, size=2, values={'output': [100.0, 100.0]}).size
2
Source code in src/skcomplex/models/economics/markets/_duopolist.py
39 40 41 42 43 44 45 46 47 48 49 | |
EchelonElement(label, visual=None, *, inventory=12.0, in_transit=8.0, backlog=4.0, expected=4.0, supply_line=16.0, desired=13.44, theta=0.36, alpha=0.26, beta=0.34, dispatch_time=1.0, mail_delay=2.0, shipping_delay=2.0)
Bases: Element
Echelon of a supply chain, which ships its backlog from its inventory and orders by anchoring and adjustment.
It ships its backlog over the dispatch time, limited by its inventory. Its expected demand adapts to incoming
orders at the rate theta, and it orders its expected demand plus alpha times the gap between its desired stock
and its effective inventory, the inventory less the backlog, less beta times its supply line, never negative.
Its orders reach its supplier after the mail delay, and the beer its supplier ships arrives after the shipping
delay.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the echelon. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
inventory
|
Annotated[float, StateSpec(domain=closed_open(0, oo), quantity=beer)]
|
The initial inventory, in cases. |
12.0
|
in_transit
|
Annotated[float, StateSpec(domain=closed_open(0, oo), quantity=beer)]
|
The initial beer on its way to the echelon. |
8.0
|
backlog
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The initial orders waiting to ship. |
4.0
|
expected
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The initial expected demand. |
4.0
|
supply_line
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The initial beer ordered and not received. |
16.0
|
desired
|
Annotated[float, ParameterSpec()]
|
The desired stock |
13.44
|
theta
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The rate at which the expected demand adapts to incoming orders. |
0.36
|
alpha
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The fraction of the stock gap ordered per week. |
0.26
|
beta
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The weight of the supply line in the stock gap. |
0.34
|
dispatch_time
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The time over which the echelon ships its backlog. |
1.0
|
mail_delay
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The average time an order of the echelon takes to reach its supplier. |
2.0
|
shipping_delay
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The average time a shipment takes to reach the echelon from its supplier. |
2.0
|
Examples:
>>> from skcomplex.models.economics.markets import EchelonElement
>>> EchelonElement('retailer', inventory=10.0).inventory
10.0
Source code in src/skcomplex/models/economics/markets/_echelon.py
76 77 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 | |
EmployerElement(label, visual=None, *, bid=0.0, demand=0.0, posted=-1.0, vacancy_rate=0.5, low_wage=0.5, high_wage=1.0)
Bases: Element
Firm that posts a vacancy with a random wage offer in some steps, filled by at most one worker.
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
|
bid
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The wage offered for the vacancy. |
0.0
|
demand
|
Annotated[float, StateSpec(domain=NN)]
|
The number of open vacancies, one or zero. |
0.0
|
posted
|
Annotated[float, StateSpec()]
|
The step in which the vacancy was posted. |
-1.0
|
vacancy_rate
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The probability of posting a vacancy in a step. |
0.5
|
low_wage
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The lowest wage offer. |
0.5
|
high_wage
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The highest wage offer. |
1.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import EmployerElement
>>> GroupElement('firms', element=EmployerElement, size=5).size
5
Source code in src/skcomplex/models/economics/markets/_employer.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | |
get_posting()
staticmethod
Return the states a firm sets in the phase of offers, in their order.
The firm withdraws its last vacancy and posts a new one at the vacancy rate, with a uniform wage offer and the step of posting.
Returns:
| Name | Type | Description |
|---|---|---|
posting |
tuple[tuple[str, Callable[[EmployerView, ModelView], float]], ...]
|
The name of every state and the function of its value, of the firm and the model view. |
Source code in src/skcomplex/models/economics/markets/_employer.py
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | |
ExchangeInteraction(label, *, source, target, goods=GOODS, pairing='pairs', quantity=0.1, phase='trade')
Bases: TransferInteraction
Bilateral barter between paired traders, a transfer whose trades repeat while both traders gain.
Every step the transfer pairs the traders, and every pair barters small quantities of every pair of goods at the
geometric mean of their marginal rates of substitution while both gain. A trader holds every good in the state of
its name and its Cobb-Douglas weight in the state <good>_weight. Every trade moves goods between the two traders,
so the total of every good stays the same, which the default run checks as invariants. The exchange reports the
mean price of the second good in units of the first, the standard deviation dispersion of its logarithm over
the trades of the step, and the number of trades volume.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the exchange. |
required |
source
|
str
|
The path of the group of traders. |
required |
target
|
str
|
The path of the group of traders, the source again. |
required |
goods
|
tuple[str, ...]
|
The names of the traded goods. |
GOODS
|
pairing
|
str
|
How the transfer pairs the traders, such as |
'pairs'
|
quantity
|
float
|
The quantity of the bought good in every trade. |
0.1
|
phase
|
str
|
The phase the trades run in. |
'trade'
|
Examples:
>>> from skcomplex.models.economics.markets import ExchangeInteraction
>>> ExchangeInteraction('exchange', source='traders', target='traders').reports
('price', 'dispersion', 'volume')
Source code in src/skcomplex/models/economics/markets/_exchange_interaction.py
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | |
report_trades(model)
Report the mean price of the second good in the first, its dispersion, and the trades of the step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
ModelViewProtocol
|
The model view of the exchange. |
required |
Source code in src/skcomplex/models/economics/markets/_exchange_interaction.py
122 123 124 125 126 127 128 129 130 131 132 133 134 | |
transfer(source, target, model)
Barter between two traders while both gain, and keep the trades of the step for its report.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
AgentViewProtocol
|
The first trader. |
required |
target
|
AgentViewProtocol
|
The second trader. |
required |
model
|
ModelViewProtocol
|
The model view of the exchange. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
traded |
bool
|
Whether the traders made a trade. |
Source code in src/skcomplex/models/economics/markets/_exchange_interaction.py
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | |
FactoryElement(label, visual=None, *, inventory=12.0, in_transit=8.0, backlog=4.0, expected=4.0, supply_line=16.0, desired=13.44, theta=0.36, alpha=0.26, beta=0.34, dispatch_time=1.0, mail_delay=2.0, shipping_delay=2.0, production_delay=3.0)
Bases: EchelonElement
Factory of a supply chain, an echelon whose orders a brewery brews over the production delay.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the factory. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
inventory
|
Annotated[float, StateSpec(domain=closed_open(0, oo), quantity=beer)]
|
The initial inventory, in cases. |
12.0
|
in_transit
|
Annotated[float, StateSpec(domain=closed_open(0, oo), quantity=beer)]
|
The initial beer on its way to the echelon. |
8.0
|
backlog
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The initial orders waiting to ship. |
4.0
|
expected
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The initial expected demand. |
4.0
|
supply_line
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The initial beer ordered and not received. |
16.0
|
desired
|
Annotated[float, ParameterSpec()]
|
The desired stock |
13.44
|
theta
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The rate at which the expected demand adapts to incoming orders. |
0.36
|
alpha
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The fraction of the stock gap ordered per week. |
0.26
|
beta
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The weight of the supply line in the stock gap. |
0.34
|
dispatch_time
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The time over which the echelon ships its backlog. |
1.0
|
mail_delay
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The average time an order of the echelon takes to reach its supplier. |
2.0
|
shipping_delay
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The average time a shipment takes to reach the echelon from its supplier. |
2.0
|
production_delay
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The average time the brewery takes to brew an order, through a third-order delay. |
3.0
|
Examples:
>>> from skcomplex.models.economics.markets import FactoryElement
>>> FactoryElement('factory').production_delay
3.0
Source code in src/skcomplex/models/economics/markets/_factory.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 95 96 97 98 99 100 101 102 103 104 105 | |
ForagerElement(label, visual=VisualSpec('agents', {'color_by': 'sugar'}), *, sugar=10.0, vision=1.0, metabolism=1.0)
Bases: Element
Agent that moves to the richest free cell in sight, harvests its sugar, burns its metabolism, and may starve.
In its own activation, a forager sees vision cells along each of the four lattice directions and moves to the
free cell with the most sugar, the nearest among equals, or stays when no cell in sight beats its own, by a
MovementInteraction of the best step with a vision. Transfers then harvest the sugar of its cell and burn its
metabolism, and a LifeCycleInteraction removes it when its wealth falls below zero.
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': 'sugar'})
|
sugar
|
Annotated[float, StateSpec()]
|
The wealth of the forager. |
10.0
|
vision
|
Annotated[float, StateSpec(domain=NN)]
|
The number of cells the forager sees in every direction. |
1.0
|
metabolism
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The sugar the forager burns in a step. |
1.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import ForagerElement
>>> GroupElement('foragers', element=ForagerElement, size=3, values={'vision': 2.0}).size
3
Source code in src/skcomplex/models/economics/markets/_forager.py
47 48 49 50 51 52 53 54 55 56 57 58 59 | |
GoodsTraderElement(label, visual=VisualSpec('agents', {'color_by': 'sugar_weight', 'color_range': (0.0, 1.0)}), *, sugar=10.0, spice=10.0, salt=0.0, sugar_weight=0.5, spice_weight=0.5, salt_weight=0.0)
Bases: Element
Trader who holds goods and values them with Cobb-Douglas weights.
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': 'sugar_weight', 'color_range': (0.0, 1.0)})
|
sugar
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The holding of sugar. |
10.0
|
spice
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The holding of spice. |
10.0
|
salt
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The holding of salt. |
0.0
|
sugar_weight
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The Cobb-Douglas weight of sugar. |
0.5
|
spice_weight
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The Cobb-Douglas weight of spice. |
0.5
|
salt_weight
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The Cobb-Douglas weight of salt, zero when salt is not traded. |
0.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import GoodsTraderElement
>>> GroupElement('traders', element=GoodsTraderElement, size=4, values={'sugar': 5.0}).size
4
Source code in src/skcomplex/models/economics/markets/_goods_trader.py
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | |
HeuristicPricingInteraction(label, *, rule=None, phase=None, traders, rate=1.1, strength=1.2, cost=1.0, risk=1.0, noise=0.01, initial=0.1)
Bases: FeedbackInteraction[ModelView]
Market maker that clears the risky asset at the price where the mean forecast of the traders is met.
The deviation x of the price from its fundamental value clears at R x_t = sum_h n_h f_h + eps_t, where n_h
is the share of traders using heuristic h. The fundamentalists forecast the fundamental, f = 0, and the trend
chasers extrapolate the last deviation, f = g x_{t-1}, both as heuristics.fundamental with a reversion of 0
and g. The realised fitness of a heuristic is the profit of its last forecast,
(x_t - R x_{t-1}) (f_h(t - 1) - R x_{t-1}) / (a sigma^2), minus its cost.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the institution. |
required |
rule
|
Callable[[ModelView], None] | None
|
Unused, since the institution overrides |
None
|
phase
|
str | None
|
The phase the institution clears in. |
None
|
traders
|
Annotated[str, RoleSpec()]
|
The path of the group of traders. |
required |
rate
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The gross return |
1.1
|
strength
|
Annotated[float, ParameterSpec()]
|
The extrapolation |
1.2
|
cost
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The cost of the fundamentalist heuristic. |
1.0
|
risk
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The risk aversion times the variance of returns, |
1.0
|
noise
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The standard deviation of the noise of the price. |
0.01
|
initial
|
Annotated[float, ParameterSpec()]
|
The initial deviation of the price from its fundamental value. |
0.1
|
Examples:
>>> from skcomplex.models.economics.markets import HeuristicPricingInteraction
>>> HeuristicPricingInteraction('pricing', traders='traders').reports
('deviation', 'trend_share', 'fitness_fundamentalist', 'fitness_trend')
Source code in src/skcomplex/models/economics/markets/_heuristic_pricing.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | |
act(model)
Clear the price from the forecasts of the traders' heuristics and report the fitnesses.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
ModelView
|
The model view of the institution. |
required |
Source code in src/skcomplex/models/economics/markets/_heuristic_pricing.py
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 | |
HeuristicTraderElement(label, visual=None, *, predictor=0.0, fundamentalist_fitness=0.0, trend_fitness=0.0)
Bases: Element
Trader who holds the index of the forecasting heuristic in use, 0 for the fundamentalist and 1 for the trend.
The trader scores every heuristic by its last realised fitness, fundamentalist_fitness and trend_fitness, which
a reinforcement of rate 1 sets every step and a logit choice reads.
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
|
predictor
|
Annotated[float, StateSpec(domain=NN)]
|
The index of the heuristic in use. |
0.0
|
fundamentalist_fitness
|
Annotated[float, StateSpec()]
|
The last realised fitness of the fundamentalist heuristic. |
0.0
|
trend_fitness
|
Annotated[float, StateSpec()]
|
The last realised fitness of the trend heuristic. |
0.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import HeuristicTraderElement
>>> GroupElement('traders', element=HeuristicTraderElement, size=10, values={'predictor': 1.0}).size
10
Source code in src/skcomplex/models/economics/markets/_heuristic_trader.py
50 51 52 53 54 55 56 57 58 59 60 61 62 | |
get_fitness(agent, model, option)
staticmethod
Return the score of a heuristic of a trader, its last realised fitness.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
HeuristicTraderView
|
The trader. |
required |
model
|
ModelView
|
The model view of the choice. |
required |
option
|
float
|
The index of the heuristic. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
fitness |
float
|
The last realised fitness of the heuristic. |
Source code in src/skcomplex/models/economics/markets/_heuristic_trader.py
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | |
get_realised_fitness(agent, model, index)
staticmethod
Return the fitness of a heuristic that the market maker reported last, zero before the first report.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
HeuristicTraderView
|
The trader. |
required |
model
|
ModelView
|
The model view of the reinforcement. |
required |
index
|
int
|
The index of the heuristic. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
fitness |
float
|
The last reported fitness of the heuristic. |
Source code in src/skcomplex/models/economics/markets/_heuristic_trader.py
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | |
JobseekerElement(label, visual=None, *, ask=1.0, supply=1.0, employer=-1.0, wage=0.0, duration=0.0, hired=-1.0, offer=-1.0, separation=0.05, reservation=1.0, decline=0.1)
Bases: Element
Worker who loses its job at the separation rate and, while unemployed, lowers its reservation wage.
A worker who loses its job searches from the next step. An unemployed worker asks the reservation wage
w_0 (1 - decline)^d, where d is the number of steps of search, and is hired by the matching market.
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
|
ask
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The reservation wage. |
1.0
|
supply
|
Annotated[float, StateSpec(domain=NN)]
|
One while the worker searches in the current step, zero otherwise. |
1.0
|
employer
|
Annotated[float, StateSpec(reference=firms)]
|
The id of the employer, or -1 for an unemployed worker. |
-1.0
|
wage
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The wage of the current job. |
0.0
|
duration
|
Annotated[float, StateSpec(domain=NN)]
|
The number of steps of the current spell of search. |
0.0
|
hired
|
Annotated[float, StateSpec()]
|
The step of the last hire. |
-1.0
|
offer
|
Annotated[float, StateSpec()]
|
The step in which the offer of the last hire was posted. |
-1.0
|
separation
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The probability that a job is destroyed in a step. |
0.05
|
reservation
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The reservation wage at the start of a search. |
1.0
|
decline
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The relative fall of the reservation wage per step of search. |
0.1
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import JobseekerElement
>>> GroupElement('workers', element=JobseekerElement, size=5).size
5
Source code in src/skcomplex/models/economics/markets/_jobseeker.py
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | |
get_search()
staticmethod
Return the states a worker sets in the phase of offers before the separations, in their order.
A worker unemployed at the start of the step searches, with a reservation wage that falls with the duration of its search.
Returns:
| Name | Type | Description |
|---|---|---|
search |
tuple[tuple[str, Callable[[JobseekerView, ModelView], float]], ...]
|
The name of every state and the function of its value, of the worker and the model view. |
Source code in src/skcomplex/models/economics/markets/_jobseeker.py
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | |
get_spell()
staticmethod
Return the states a worker sets in the phase of offers after the separations, in their order.
A worker who lost its job earns no wage, and the duration of a search grows while the worker searches.
Returns:
| Name | Type | Description |
|---|---|---|
spell |
tuple[tuple[str, Callable[[JobseekerView, ModelView], float]], ...]
|
The name of every state and the function of its value, of the worker and the model view. |
Source code in src/skcomplex/models/economics/markets/_jobseeker.py
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | |
MarketElement(label, visual=None, *, price=1.0)
Bases: Element
Market of one good described by its price.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the market. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
price
|
Annotated[float, StateSpec()]
|
The initial price. |
1.0
|
Examples:
>>> from skcomplex.models.economics.markets import MarketElement
>>> MarketElement('wheat', price=2.0).price
2.0
Source code in src/skcomplex/models/economics/markets/_market.py
31 32 33 34 35 36 37 38 39 | |
PricePointElement(label, *, distribution=0.5, price=1.0, alpha=0.25, beta=0.5, n_firms=2.0)
Bases: Element
Equilibrium distribution of prices at one price, which makes a firm indifferent among its prices.
A firm that charges P sells to its loyal share alpha, and to the switchers beta when it undercuts all its
m - 1 rivals, each with the probability 1 - F(P), for the expected profit P (alpha + beta (1 - F)^(m - 1)).
In equilibrium every price gives the profit alpha of selling to the loyal share at the highest price 1, which
F(P) = 1 - (alpha (1 - P) / (beta P))^(1 / (m - 1)) solves (Forrest 2018 Lemma 20.1).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the point or the group. |
required |
distribution
|
Annotated[float, StateSpec()]
|
The initial guess of |
0.5
|
price
|
Annotated[float, StateSpec(domain=open_closed(0, 1))]
|
The price |
1.0
|
alpha
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The loyal share of every firm. |
0.25
|
beta
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The share of switchers. |
0.5
|
n_firms
|
Annotated[float, ParameterSpec(domain=closed_open(2, oo))]
|
The number of firms |
2.0
|
Examples:
>>> from skcomplex.models.economics.markets import PricePointElement
>>> PricePointElement('point', price=0.5).price
0.5
Source code in src/skcomplex/models/economics/markets/_price_point.py
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | |
get_profit(member)
staticmethod
Return the expected profit of a firm at the price of a member, for the observables of a run.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
member
|
SimpleNamespace
|
The namespace of the states and parameters of the member. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
profit |
Expression
|
The expected profit |
Source code in src/skcomplex/models/economics/markets/_price_point.py
69 70 71 72 73 74 75 76 77 78 79 80 81 | |
PricingFirmElement(label, price=1.0, scores=0.0)
Bases: Element
Firm that charges one price of a grid and counts what every price would have earned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the firm or the group. |
required |
price
|
Annotated[float, StateSpec()]
|
The price the firm charges. |
1.0
|
scores
|
Annotated[ArrayLike, StateSpec(vector=True)]
|
The sum of the payoffs of every price of the grid against the prices of the rival so far. |
0.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import PricingFirmElement
>>> GroupElement('firms', element=PricingFirmElement, size=2).size
2
Source code in src/skcomplex/models/economics/markets/_pricing_firm.py
35 36 37 38 39 40 41 42 43 | |
PricingGameSpec(prices, alpha, beta)
dataclass
Bases: BaseSpec
Grid of prices of two firms, each with a loyal share, that share the switchers who pay the lower price.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prices
|
Array
|
The prices the firms choose among, increasing. |
required |
alpha
|
float
|
The loyal share of every firm. |
required |
beta
|
float
|
The share of switchers. |
required |
Examples:
>>> import numpy as np
>>> from skcomplex.models.economics.markets import PricingGameSpec
>>> PricingGameSpec(np.array([0.5, 1.0]), 0.25, 0.5).beta
0.5
payoff(agent, model, k)
Return what the price of index k earns against the price the rival charged in this step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
PricingFirmView
|
The firm. |
required |
model
|
ModelView
|
The model view, which holds the rival. |
required |
k
|
int
|
The index of the price. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
payoff |
float
|
The profit of the price. |
Source code in src/skcomplex/models/economics/markets/_pricing_game_spec.py
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
utility(agent, model, option)
Return what a price has earned so far against the prices of the rival, its score.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
PricingFirmView
|
The firm. |
required |
model
|
ModelView
|
The model view, which the score does not read. |
required |
option
|
float
|
The price. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
utility |
float
|
The score of the price. |
Source code in src/skcomplex/models/economics/markets/_pricing_game_spec.py
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | |
ProductElement(label, visual=None, *, shelved=0.0, tau_a=1.0)
Bases: Element
Product on the shelf of a shop, which ages from the time it was shelved, its freshness exp(-age / tau_a).
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
|
shelved
|
Annotated[float, StateSpec()]
|
The time at which the product was put on the shelf. |
0.0
|
tau_a
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The time over which the product ages. |
1.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import ProductElement
>>> GroupElement('products', element=ProductElement, size=4, location=[0, 0, 1, 1]).size
4
Source code in src/skcomplex/models/economics/markets/_product.py
42 43 44 45 46 47 48 49 50 51 52 | |
restock(product, customer, model)
staticmethod
Return the amount shelved - t that resets the shelving time of a sold product to the time of the sale.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
product
|
ProductView
|
The product sold. |
required |
customer
|
CustomerView
|
The customer who buys it. |
required |
model
|
ModelView
|
The model view of the purchase. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
amount |
float
|
The amount taken from the shelving time. |
Source code in src/skcomplex/models/economics/markets/_product.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | |
sell(product, customer, model)
staticmethod
Return the amount that sets the freshness the customer holds to exp(-(t - shelved) / tau_a).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
product
|
ProductView
|
The product sold. |
required |
customer
|
CustomerView
|
The customer who buys it. |
required |
model
|
ModelView
|
The model view of the purchase. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
amount |
float
|
The change of the freshness the customer holds. |
Source code in src/skcomplex/models/economics/markets/_product.py
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | |
QuadraticSupplyMarketElement(label, visual=None, *, P=1.0, k=1.0, beta=10.0, lam=1.0, delta=1.0, alpha=2.0, gamma=-0.1)
Bases: Element
Market of one good whose price adjusts to the excess of a linear demand over a quadratic supply.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the market. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
P
|
Annotated[float, StateSpec()]
|
The initial price. |
1.0
|
k
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The speed of the price adjustment. |
1.0
|
beta
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The demand at price zero. |
10.0
|
lam
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The slope of the demand. |
1.0
|
delta
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The supply at price zero. |
1.0
|
alpha
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The linear intensity of the supply. |
2.0
|
gamma
|
Annotated[float, ParameterSpec()]
|
The quadratic intensity of the supply, negative for saturation. |
-0.1
|
Examples:
>>> from skcomplex.models.economics.markets import QuadraticSupplyMarketElement
>>> QuadraticSupplyMarketElement('market', P=2.0).P
2.0
Source code in src/skcomplex/models/economics/markets/_prices.py
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | |
ResidentElement(label, visual=VisualSpec('agents', {'color_by': 'travel', 'color_range': (0.0, 1.0)}), *, bid=20.0, demand=1.0, money=1000.0, travel=1.0, distance_cost=1.0, online=0.0)
Bases: Element
Shopper who wants one unit a step and shops in person, paying for travel, or online, where distance is free.
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': 'travel', 'color_range': (0.0, 1.0)})
|
bid
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The highest price the shopper pays. |
20.0
|
demand
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The units still wanted in the step. |
1.0
|
money
|
Annotated[float, StateSpec()]
|
The money of the shopper. |
1000.0
|
travel
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The travel cost per cell of the current step, zero online. |
1.0
|
distance_cost
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The travel cost per cell of shopping in person. |
1.0
|
online
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The probability of shopping online in a step. |
0.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import ResidentElement
>>> GroupElement('shoppers', element=ResidentElement, size=3, values={'online': 1.0}).size
3
Source code in src/skcomplex/models/economics/markets/_resident.py
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
get_preference(shopper, shop)
staticmethod
Return the preference of a shopper for a shop, the opposite of the delivered price.
The delivered price is the shop's ask plus the shopper's travel cost per cell times the distance to the shop.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shopper
|
object
|
The shopper. |
required |
shop
|
object
|
The shop. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
preference |
float
|
The opposite of the delivered price, higher for a preferred shop. |
Source code in src/skcomplex/models/economics/markets/_resident.py
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | |
get_travel(agent, model)
staticmethod
Return the travel cost per cell of the step, zero when the shopper shops online with its probability.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
ResidentView
|
The shopper. |
required |
model
|
ModelView
|
The model view of the plan. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
travel |
float
|
The travel cost per cell. |
Source code in src/skcomplex/models/economics/markets/_resident.py
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | |
RetailDemandInteraction(label, *, retailer)
Bases: TransferInteraction
Customers of a supply chain, who take the shipments of the retailer.
The sales are a transfer from the inventory of the retailer to the customers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the customers. |
required |
retailer
|
Annotated[str, RoleSpec()]
|
The path of the retailer. |
required |
Examples:
>>> from skcomplex.models.economics.markets import RetailDemandInteraction
>>> RetailDemandInteraction('customers', retailer='retailer').retailer
'retailer'
Source code in src/skcomplex/models/economics/markets/_retail_demand.py
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | |
RetailerElement(label, visual=None, *, inventory=12.0, in_transit=8.0, backlog=4.0, expected=4.0, supply_line=16.0, desired=13.44, theta=0.36, alpha=0.26, beta=0.34, dispatch_time=1.0, mail_delay=2.0, shipping_delay=2.0, demand=4.0, demand_step=4.0, step_time=5.0)
Bases: EchelonElement
Retailer of a supply chain, an echelon whose customers order their demand, which steps once.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the retailer. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
inventory
|
Annotated[float, StateSpec(domain=closed_open(0, oo), quantity=beer)]
|
The initial inventory, in cases. |
12.0
|
in_transit
|
Annotated[float, StateSpec(domain=closed_open(0, oo), quantity=beer)]
|
The initial beer on its way to the echelon. |
8.0
|
backlog
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The initial orders waiting to ship. |
4.0
|
expected
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The initial expected demand. |
4.0
|
supply_line
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The initial beer ordered and not received. |
16.0
|
desired
|
Annotated[float, ParameterSpec()]
|
The desired stock |
13.44
|
theta
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The rate at which the expected demand adapts to incoming orders. |
0.36
|
alpha
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The fraction of the stock gap ordered per week. |
0.26
|
beta
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The weight of the supply line in the stock gap. |
0.34
|
dispatch_time
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The time over which the echelon ships its backlog. |
1.0
|
mail_delay
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The average time an order of the echelon takes to reach its supplier. |
2.0
|
shipping_delay
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The average time a shipment takes to reach the echelon from its supplier. |
2.0
|
demand
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The customer demand, in cases a week. |
4.0
|
demand_step
|
Annotated[float, ParameterSpec()]
|
The permanent change of the demand. |
4.0
|
step_time
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The week of the change of the demand. |
5.0
|
Examples:
>>> from skcomplex.models.economics.markets import RetailerElement
>>> RetailerElement('retailer').demand
4.0
Source code in src/skcomplex/models/economics/markets/_retailer.py
76 77 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 | |
ShopperElement(label, visual=None, *, wanted=0, visited=0, missed=0, spent=0.0)
Bases: Element
Shopper who visits one stall a step that it has not visited yet and buys what it wants there.
A shopper gives up the items that it has not found once it has visited every stall.
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
|
wanted
|
Annotated[float, StateSpec(domain=NN)]
|
The bit mask of the items on the shopping list. |
0
|
visited
|
Annotated[float, StateSpec(domain=NN)]
|
The bit mask of the stalls already visited. |
0
|
missed
|
Annotated[float, StateSpec(domain=NN)]
|
The bit mask of the items given up. |
0
|
spent
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The money spent. |
0.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import ShopperElement
>>> GroupElement('shoppers', element=ShopperElement, size=5, values={'wanted': 3}).size
5
Source code in src/skcomplex/models/economics/markets/_shopper.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |
shop(agent, model)
Visit a random stall not visited yet and buy every wanted item that it sells.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
ShopperView
|
The shopper. |
required |
model
|
ModelView
|
The model. |
required |
Source code in src/skcomplex/models/economics/markets/_shopper.py
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | |
StallElement(label, visual=None, *, stall=0, stock=0, markup=0.1)
Bases: Element
Market stall that sells some kinds of produce at the wholesale price plus its markup.
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
|
stall
|
Annotated[float, StateSpec(domain=NN)]
|
The index of the stall. |
0
|
stock
|
Annotated[float, StateSpec(domain=NN)]
|
The bit mask of the kinds of produce that the stall sells. |
0
|
markup
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The relative markup on the wholesale prices. |
0.1
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import StallElement
>>> GroupElement('stalls', element=StallElement, size=3, values={'stall': [0, 1, 2]}).size
3
Source code in src/skcomplex/models/economics/markets/_stall.py
44 45 46 47 48 49 50 51 52 53 54 55 56 | |
StoreElement(label, visual=VisualSpec('agents', {'color_by': 'price'}), *, price=10.0, ask=10.0, supply=0.0, sales=0.0, money=100.0, profit=0.0, direction=1.0, capacity=1000.0, unit_cost=1.0, fixed_cost=20.0, adjustment=0.05)
Bases: Element
Shop that offers its capacity at its price, searches for the price of the largest profit, and may close.
The shop searches for its price by trial and error: it moves the price by adjustment in the same direction as
long as its profit grows, and turns back when the profit falls, never below the unit cost. It pays the unit cost
of every unit sold and the fixed cost every step, and closes when its money runs out.
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': 'price'})
|
price
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The price of a unit. |
10.0
|
ask
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The price offered in the current step. |
10.0
|
supply
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The units still offered in the step. |
0.0
|
sales
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The units sold in the last step. |
0.0
|
money
|
Annotated[float, StateSpec()]
|
The money of the shop. |
100.0
|
profit
|
Annotated[float, StateSpec()]
|
The profit of the last step. |
0.0
|
direction
|
Annotated[float, StateSpec()]
|
The direction of the last change of the price, 1 up or -1 down. |
1.0
|
capacity
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The units the shop can sell in a step. |
1000.0
|
unit_cost
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The cost of a unit sold. |
1.0
|
fixed_cost
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The cost of running the shop for a step. |
20.0
|
adjustment
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The relative change of the price in a step. |
0.05
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import StoreElement
>>> GroupElement('shops', element=StoreElement, size=4, values={'price': 10.0}).size
4
Source code in src/skcomplex/models/economics/markets/_store.py
77 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 | |
get_opening()
staticmethod
Return the states a shop sets when it opens for the market, its capacity offered at its price.
Returns:
| Name | Type | Description |
|---|---|---|
opening |
tuple[tuple[str, Callable[[StoreView, ModelView], float]], ...]
|
The name of every state and the function of its value, of the shop and the model view. |
Source code in src/skcomplex/models/economics/markets/_store.py
126 127 128 129 130 131 132 133 134 135 136 137 138 | |
get_profit(agent)
staticmethod
Return the profit of the step, the margin on the units sold less the fixed cost.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
StoreView
|
The shop. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
profit |
float
|
The profit of the step. |
Source code in src/skcomplex/models/economics/markets/_store.py
112 113 114 115 116 117 118 119 120 121 122 123 124 | |
get_settlement()
staticmethod
Return the states a shop sets when it settles its accounts, in their order.
The shop turns its price back when its profit falls, records the profit, and pays its costs. The pricing of the model then steps the price by the sign of the direction.
Returns:
| Name | Type | Description |
|---|---|---|
settlement |
tuple[tuple[str, Callable[[StoreView, ModelView], float]], ...]
|
The name of every state and the function of its value, of the shop and the model view. |
Source code in src/skcomplex/models/economics/markets/_store.py
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | |
record_sale(match, model)
staticmethod
Count the units of a purchase in the sales of the shop.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
match
|
MatchSpec
|
The purchase of a shopper, the requester, from a shop, the provider. |
required |
model
|
ModelView
|
The model view of the market. |
required |
Source code in src/skcomplex/models/economics/markets/_store.py
158 159 160 161 162 163 164 165 166 167 168 169 170 171 | |
SugarPatchElement(label, visual=VisualSpec('agents', {'color_by': 'sugar', 'color_range': (0.0, 4.0)}), *, sugar=0.0, capacity=0.0, growback=1.0)
Bases: Element
Cell of the landscape whose sugar grows back by a fixed amount a step up to its capacity.
The growback is a RegrowthInteraction of the group of patches.
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': 'sugar', 'color_range': (0.0, 4.0)})
|
sugar
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The sugar on the patch. |
0.0
|
capacity
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The most sugar the patch holds. |
0.0
|
growback
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The sugar that grows back in a step. |
1.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import SugarPatchElement
>>> GroupElement('patches', element=SugarPatchElement, size=4, values={'capacity': 2.0}).size
4
Source code in src/skcomplex/models/economics/markets/_sugar_patch.py
44 45 46 47 48 49 50 51 52 53 54 55 56 | |
SupplyLinkInteraction(label, *, downstream, upstream)
Bases: TransferInteraction
Link of a supply chain, which ships beer from the upstream echelon to the downstream echelon.
The shipments and their arrivals, after a third-order delay of the shipping delay of the downstream echelon, are the legs of one transfer, from the inventory of the upstream echelon to the beer in transit to the downstream echelon and on to its inventory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the link. |
required |
downstream
|
Annotated[str, RoleSpec()]
|
The path of the echelon that orders. |
required |
upstream
|
Annotated[str, RoleSpec()]
|
The path of the echelon that ships. |
required |
Examples:
>>> from skcomplex.models.economics.markets import SupplyLinkInteraction
>>> SupplyLinkInteraction('link', downstream='retailer', upstream='wholesaler').upstream
'wholesaler'
Source code in src/skcomplex/models/economics/markets/_supply_link.py
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 | |
TillElement(label, visual=None, *, revenue=0.0, washes=0, valets=0, turned_away=0)
Bases: Element
Till of the car wash, which counts the revenue and the cars served and turned away.
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
|
revenue
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The money taken. |
0.0
|
washes
|
Annotated[float, StateSpec(domain=NN)]
|
The number of cars that left after a wash only. |
0
|
valets
|
Annotated[float, StateSpec(domain=NN)]
|
The number of cars that left after a valet. |
0
|
turned_away
|
Annotated[float, StateSpec(domain=NN)]
|
The number of drivers who did not turn in because of the queue. |
0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import TillElement
>>> GroupElement('till', element=TillElement, size=1).size
1
Source code in src/skcomplex/models/economics/markets/_till.py
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
WasherElement(label, visual=None)
Bases: Element
Worker who joins the front car of the wash or of the valet while it has fewer than two workers.
A worker who finds both areas staffed helps at a random one of them. One second of work removes one person-second from the car.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the agent or group. |
required |
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import WasherElement
>>> GroupElement('workers', element=WasherElement, size=4).size
4
Source code in src/skcomplex/core/elements/_base.py
70 71 72 | |
work(agent, model)
Work one second on the front car of an area.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
AgentView
|
The worker. |
required |
model
|
ModelView
|
The model. |
required |
Source code in src/skcomplex/models/economics/markets/_washer.py
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
ZeroIntelligenceBuyerElement(label, visual=None, *, value=100.0, bid=0.0, demand=1.0, profit=0.0, ceiling=200.0, constrained=1.0)
Bases: Element
Buyer of one unit per trading period who bids a random price, below its value under the budget constraint.
In every round of a trading period, a buyer that has not bought yet bids a price drawn uniformly from 0 to its value, or to the price ceiling without the constraint, the zero-intelligence traders of Gode and Sunder (1993).
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
|
value
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The value of the unit to the buyer, its redemption value. |
100.0
|
bid
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The current bid. |
0.0
|
demand
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The number of units still wanted in the trading period. |
1.0
|
profit
|
Annotated[float, StateSpec()]
|
The accumulated surplus of the buyer's trades. |
0.0
|
ceiling
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The highest price of the market. |
200.0
|
constrained
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
One when the buyer never bids above its value, zero otherwise. |
1.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import ZeroIntelligenceBuyerElement
>>> GroupElement('buyers', element=ZeroIntelligenceBuyerElement, size=5, values={'value': 100.0}).size
5
Source code in src/skcomplex/models/economics/markets/_zero_intelligence_buyer.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | |
get_bid(agent, model)
staticmethod
Return a bid drawn uniformly from 0 to the value, or to the price ceiling without the constraint.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
ZeroIntelligenceBuyerView
|
The buyer. |
required |
model
|
ModelView
|
The model view of the quotes. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bid |
float
|
The bid of the round. |
Source code in src/skcomplex/models/economics/markets/_zero_intelligence_buyer.py
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | |
ZeroIntelligenceSellerElement(label, visual=None, *, value=100.0, ask=200.0, supply=1.0, profit=0.0, ceiling=200.0, constrained=1.0)
Bases: Element
Seller of one unit per trading period who asks a random price, above its cost under the budget constraint.
In every round of a trading period, a seller that has not sold yet asks a price drawn uniformly from its cost, or from 0 without the constraint, to the price ceiling.
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
|
value
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The cost of the unit to the seller. |
100.0
|
ask
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The current ask. |
200.0
|
supply
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The number of units still offered in the trading period. |
1.0
|
profit
|
Annotated[float, StateSpec()]
|
The accumulated surplus of the seller's trades. |
0.0
|
ceiling
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The highest price of the market. |
200.0
|
constrained
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
One when the seller never asks below its cost, zero otherwise. |
1.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.markets import ZeroIntelligenceSellerElement
>>> GroupElement('sellers', element=ZeroIntelligenceSellerElement, size=5, values={'value': 50.0}).size
5
Source code in src/skcomplex/models/economics/markets/_zero_intelligence_seller.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | |
get_ask(agent, model)
staticmethod
Return an ask drawn uniformly from the cost, or from 0 without the constraint, to the price ceiling.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
ZeroIntelligenceSellerView
|
The seller. |
required |
model
|
ModelView
|
The model view of the quotes. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
ask |
float
|
The ask of the round. |
Source code in src/skcomplex/models/economics/markets/_zero_intelligence_seller.py
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | |
barter(n_barterers=2, *, chocolate=(9.0, 1.0), cigarettes=(2.0, 8.0), weights=(0.6, 0.3), quantity=0.02, random_state=0)
Return barter of chocolate and cigarettes, in an Edgeworth box of two barterers or among many prisoners.
Every step the barterers are paired at random, and every pair trades small quantities of one good for the other at the geometric mean of their marginal rates of substitution while both gain, so the totals of both goods are unchanged. Two barterers with the given endowments and weights of chocolate trade within the Edgeworth box until no trade improves both, which is a point of the contract curve, where their marginal rates of substitution are equal. More barterers are prisoners of war who receive random Red Cross parcels and random tastes, and their trades settle on a common price, as Radford (1945) observed (Hamill and Gilbert 2016 ch. 5).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_barterers
|
int
|
The number of barterers, 2 for the Edgeworth box. |
2
|
chocolate
|
tuple[float, float]
|
The chocolate of the two barterers of the Edgeworth box, and the range of the parcels of more barterers. |
(9.0, 1.0)
|
cigarettes
|
tuple[float, float]
|
The cigarettes of the two barterers of the Edgeworth box, and the range of the parcels of more barterers. |
(2.0, 8.0)
|
weights
|
tuple[float, float]
|
The weights of chocolate of the two barterers of the Edgeworth box, and the range of the weights of more barterers. |
(0.6, 0.3)
|
quantity
|
float
|
The quantity of the bought good in every trade. |
0.02
|
random_state
|
int | Generator | None
|
The seed or generator of the parcels and the weights of more than two barterers. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the group |
Raises:
| Type | Description |
|---|---|
ValueError
|
There are fewer than two barterers. |
Examples:
>>> from skcomplex.models.economics.markets import barter
>>> barter().elements[0].check().prepare().size_
2
Source code in src/skcomplex/models/economics/markets/_barter.py
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 220 221 222 223 224 225 226 227 228 229 230 231 232 | |
beer_game(inventory=12.0, *, demand=4.0, demand_step=4.0, step_time=5.0, theta=0.36, alpha=0.26, beta=0.34, dispatch_time=1.0, mail_delay=2.0, shipping_delay=2.0, production_delay=3.0)
Return Sterman's beer distribution game, a supply chain whose orders swing wider at every echelon upstream.
A retailer, a wholesaler, a distributor, and a factory each hold an inventory of beer and a backlog of orders
waiting to ship. Each ships its backlog over the dispatch time, limited by its inventory, and the beer reaches the
next echelon downstream after the shipping delay. Orders reach the next echelon upstream after the mail delay, and
the factory brews its orders over the production delay. Customer demand steps from 4 to 8 cases a week in week 5.
Every echelon orders by Sterman's anchoring and adjustment rule, its expected demand plus alpha times the gap
between its desired stock S' and its effective inventory, the inventory less the backlog, plus beta times its
supply line, the beer it ordered and has not received. The expected demand adapts to incoming orders at the rate
theta. The defaults of theta, alpha, and beta are the median estimates of Sterman 1989, and S' is set so
the chain starts in equilibrium at 4 cases a week. The game is weekly and its delays are fixed, while this model is
a continuous approximation in which third-order delays stand in for the fixed ones. The amplitude of the orders
grows from the retailer to the factory, the bullwhip effect.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inventory
|
float
|
The initial inventory of every echelon, in cases. |
12.0
|
demand
|
float
|
The customer demand, in cases a week. |
4.0
|
demand_step
|
float
|
The permanent change of the customer demand. |
4.0
|
step_time
|
float
|
The week of the change of the customer demand. |
5.0
|
theta
|
float
|
The rate at which the expected demand adapts to incoming orders. |
0.36
|
alpha
|
float
|
The fraction of the stock gap ordered per week. |
0.26
|
beta
|
float
|
The weight of the supply line in the stock gap. |
0.34
|
dispatch_time
|
float
|
The time over which an echelon ships its backlog. |
1.0
|
mail_delay
|
float
|
The average time an order takes to reach the next echelon upstream. |
2.0
|
shipping_delay
|
float
|
The average time a shipment takes to reach the next echelon downstream. |
2.0
|
production_delay
|
float
|
The average time the factory takes to brew its orders. |
3.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the stocks |
Examples:
>>> from skcomplex.models.economics.markets import beer_game
>>> [element.label for element in beer_game().elements]
['retailer', 'wholesaler', 'distributor', 'factory']
Source code in src/skcomplex/models/economics/markets/_supply_chains.py
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 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 | |
brock_hommes(n_traders=1000, *, intensity=1.0, rate=1.1, strength=1.2, cost=1.0, risk=1.0, noise=0.01, initial=0.1)
Return Brock and Hommes' asset market with traders switching between fundamentalists and trend chasers.
Every step the traders score every heuristic by its last realised fitness and choose a heuristic by a logit choice
of intensity beta on its last realised fitness, and the market maker clears the deviation of the price from the
fundamental at R x_t = sum_h n_h f_h. The fundamental steady state is stable while the share of trend chasers
there, 1 / (1 + exp(-beta C)), is below R / g, and beyond the critical intensity beta* = ln(R / (g - R)) / C
the price fluctuates persistently around the fundamental.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_traders
|
int
|
The number of traders. |
1000
|
intensity
|
float
|
The intensity of choice |
1.0
|
rate
|
float
|
The gross return |
1.1
|
strength
|
float
|
The extrapolation |
1.2
|
cost
|
float
|
The cost |
1.0
|
risk
|
float
|
The risk aversion times the variance of returns, |
1.0
|
noise
|
float
|
The standard deviation of the noise of the price. |
0.01
|
initial
|
float
|
The initial deviation of the price from its fundamental value. |
0.1
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the group |
Examples:
>>> from skcomplex.models.economics.markets import brock_hommes
>>> brock_hommes(100).elements[0].check().prepare().size_
100
Source code in src/skcomplex/models/economics/markets/_brock_hommes.py
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 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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | |
car_dealer(inventory=200.0, *, demand=20.0, demand_step=2.0, step_time=25.0, coverage=10.0, perception_delay=5.0, response_delay=3.0, delivery_delay=5.0)
Return Meadows' car dealership, whose inventory oscillates after a step in demand because of its delays.
The inventory is a stock of cars that deliveries from the factory fill and sales to customers drain. Sales are the
customer demand, limited by the cars on the lot. The dealer smooths sales over the perception delay, wants an
inventory of coverage days of perceived sales, and orders the perceived sales plus the gap to that inventory
divided by the response delay. Orders arrive through a third-order material delay, a continuous stand-in for
Meadows' fixed delivery delay. Lengthening the response delay damps the oscillation, while shortening the
perception delay makes the dealer react faster to the new demand and slightly enlarges it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inventory
|
float
|
The initial number of cars on the lot. |
200.0
|
demand
|
float
|
The customer demand in cars per day. |
20.0
|
demand_step
|
float
|
The permanent change of the demand. |
2.0
|
step_time
|
float
|
The day of the change of the demand. |
25.0
|
coverage
|
float
|
The days of perceived sales the dealer wants on the lot. |
10.0
|
perception_delay
|
float
|
The time over which the dealer averages sales. |
5.0
|
response_delay
|
float
|
The time over which the dealer closes the inventory gap. |
3.0
|
delivery_delay
|
float
|
The average time between an order and its delivery. |
5.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the cars on the lot |
Examples:
>>> from skcomplex.models.economics.markets import car_dealer
>>> car_dealer(response_delay=6.0).elements[0].response_delay
6.0
Source code in src/skcomplex/models/economics/markets/_inventory.py
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 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 | |
car_wash(n_workers=4, n_cars=1, *, p_pass=0.33, p_enter=0.005, p_valet=0.5, wash_work=525.0, valet_work=1750.0, wash_price=4.0, valet_price=10.0, balk=3)
Return Chesney's Clean and Wax hand car wash, a shadow account of the revenue of its workers' labour.
Every step is one second. Passing cars turn in with a probability and queue for the wash, washed cars may queue for a valet, and the workers serve the front car of each area, two at a time if they can. The wash opens with cars already queuing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_workers
|
int
|
The number of workers. |
4
|
n_cars
|
int
|
The number of cars queuing for the wash at the start, at least one. |
1
|
p_pass
|
float
|
The probability that a car passes in a second. |
0.33
|
p_enter
|
float
|
The probability that a passing car turns in. |
0.005
|
p_valet
|
float
|
The probability that a washed car stays for a valet. |
0.5
|
wash_work
|
float
|
The person-seconds of a wash. |
525.0
|
valet_work
|
float
|
The person-seconds of a valet. |
1750.0
|
wash_price
|
float
|
The price of a wash. |
4.0
|
valet_price
|
float
|
The price of a wash with a valet. |
10.0
|
balk
|
int
|
The length of the wash queue at which drivers no longer turn in. |
3
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the groups |
Examples:
>>> from skcomplex.models.economics.markets import car_wash
>>> car_wash(5).elements[0].check().prepare().size_
5
Source code in src/skcomplex/models/economics/markets/_queues.py
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 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 95 96 97 98 99 100 101 | |
cobb_douglas(agent, goods, weights)
Return the logarithm of the Cobb-Douglas utility of an agent, sum_i a_i log x_i.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
object
|
The agent, with a state for the holding of every good and for the weight of every good. |
required |
goods
|
Sequence[str]
|
The names of the states that hold the goods. |
required |
weights
|
Sequence[str]
|
The names of the states that hold the weights of the goods, in the order of |
required |
Returns:
| Name | Type | Description |
|---|---|---|
utility |
float
|
The logarithm of the utility, minus infinity when a weighted good runs out. |
Examples:
>>> from types import SimpleNamespace
>>> from skcomplex.models.economics.markets import cobb_douglas
>>> agent = SimpleNamespace(x=4.0, y=1.0, a=0.5, b=0.5)
>>> round(cobb_douglas(agent, ('x', 'y'), ('a', 'b')), 6)
0.693147
Source code in src/skcomplex/models/economics/markets/_exchange.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 45 | |
cobweb(price=1.0, *, a=10.0, b=2.0, c=1.0, d=1.0)
Return a market whose price converges to or oscillates around equilibrium as supply lags the price.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
price
|
float
|
The initial price. |
1.0
|
a
|
float
|
The demand intercept. |
10.0
|
b
|
float
|
The demand slope. |
2.0
|
c
|
float
|
The supply intercept. |
1.0
|
d
|
float
|
The supply slope. |
1.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the market |
Examples:
>>> from skcomplex.models.economics.markets import cobweb
>>> cobweb(price=2.0).elements[0].price
2.0
Source code in src/skcomplex/models/economics/markets/_cobweb.py
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 | |
commodity_cycle(inventory=25.0, capacity=100.0, *, demand=100.0, demand_step=10.0, step_time=2.0, desired_coverage=0.25, reference_price=1.0, supply_elasticity=0.1, demand_elasticity=0.25, expectation_time=1.0, construction_delay=3.0, lifetime=15.0)
Return a commodity market whose price and capacity cycle because new capacity arrives after a delay.
The inventory is a stock of the commodity that production fills and consumption drains. The price is a falling table function of the inventory coverage, the years of demand the inventory holds, relative to the desired coverage. A high price raises the utilization of capacity and lowers consumption with constant elasticities. Producers form an expected price by smoothing the price, and order new capacity at the rate of retirements multiplied by a rising table function of the expected price. Orders become capacity through a third-order delay. After a step in demand the market overshoots, so the price and the capacity oscillate, the commodity cycle of Bala et al. Section 4.11.4. The book was not at hand, so the tables and the parameters are a documented reconstruction of that structure, in years and in units of the reference demand and price. The market starts in equilibrium.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inventory
|
float
|
The initial inventory of the commodity. |
25.0
|
capacity
|
float
|
The initial production capacity per year. |
100.0
|
demand
|
float
|
The demand per year at the reference price. |
100.0
|
demand_step
|
float
|
The permanent change of the demand. |
10.0
|
step_time
|
float
|
The year of the change of the demand. |
2.0
|
desired_coverage
|
float
|
The years of demand producers want the inventory to hold. |
0.25
|
reference_price
|
float
|
The price at the desired coverage. |
1.0
|
supply_elasticity
|
float
|
The elasticity of the utilization of capacity with respect to the price. |
0.1
|
demand_elasticity
|
float
|
The elasticity of consumption with respect to the price, as a positive number. |
0.25
|
expectation_time
|
float
|
The time over which producers smooth the price into their expected price. |
1.0
|
construction_delay
|
float
|
The average time between an order of capacity and its completion. |
3.0
|
lifetime
|
float
|
The average lifetime of capacity. |
15.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the inventory |
Examples:
>>> from skcomplex.models.economics.markets import commodity_cycle
>>> commodity_cycle(construction_delay=5.0).elements[0].construction_delay
5.0
Source code in src/skcomplex/models/economics/markets/_commodities.py
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 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 286 | |
contract_curve(chocolate, first_weight, second_weight, total_chocolate, total_cigarettes)
Return the cigarettes of the first of two barterers on the contract curve, given its chocolate.
On the contract curve of two Cobb-Douglas barterers the marginal rates of substitution are equal,
a y / ((1 - a) x) = b (Y - y) / ((1 - b) (X - x)), where a and b are the weights of chocolate, x and y
the chocolate and cigarettes of the first barterer, and X and Y the totals.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chocolate
|
ArrayLike
|
The chocolate of the first barterer. |
required |
first_weight
|
float
|
The weight of chocolate of the first barterer. |
required |
second_weight
|
float
|
The weight of chocolate of the second barterer. |
required |
total_chocolate
|
float
|
The total chocolate of both. |
required |
total_cigarettes
|
float
|
The total cigarettes of both. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
cigarettes |
NDArray[float64]
|
The cigarettes of the first barterer on the contract curve. |
Examples:
>>> from skcomplex.models.economics.markets import contract_curve
>>> float(contract_curve(5.0, 0.5, 0.5, 10.0, 10.0))
5.0
Source code in src/skcomplex/models/economics/markets/_barter.py
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 70 71 72 73 74 75 76 77 78 79 80 81 82 | |
cournot_duopoly(outputs=(100.0, 100.0), costs=(0.0, 0.0), *, a=1500.0, b=10.0, error=0.0)
Return two Cournot duopolists that adjust their output to their beliefs about each other.
Without errors the outputs converge to the Nash equilibrium, q_i = (a - 2 c_i + c_j) / (3 b), which is 50 units
each for the defaults. Errors in the beliefs keep the total output fluctuating around it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
outputs
|
Sequence[float]
|
The initial outputs of the two firms. |
(100.0, 100.0)
|
costs
|
Sequence[float]
|
The marginal costs of the two firms. |
(0.0, 0.0)
|
a
|
float
|
The intercept of the inverse demand. |
1500.0
|
b
|
float
|
The slope of the inverse demand. |
10.0
|
error
|
float
|
The largest relative error of a firm's belief about the rival's output. |
0.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the group |
Examples:
>>> from skcomplex.models.economics.markets import cournot_duopoly
>>> cournot_duopoly(error=0.01).interactions[0].error
0.01
Source code in src/skcomplex/models/economics/markets/_duopoly.py
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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | |
double_auction(n_buyers=50, n_sellers=50, *, protocol='order_book', rounds=20, constrained=True, ceiling=200.0, random_state=0)
Return Gode and Sunder's double auction of zero-intelligence traders, a step per trading period.
Every buyer values one unit and every seller can produce one unit at a cost, both drawn uniformly below the price ceiling. During a trading period of several rounds, every trader that has not traded yet quotes a random price and the market matches the quotes, continuously in a limit order book or at one uniform price in a call auction. With the budget constraint (ZI-C) no trader accepts a loss, and the market alone reaches nearly the whole competitive surplus; without it (ZI-U), traders make losing trades and the efficiency drops.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_buyers
|
int
|
The number of buyers. |
50
|
n_sellers
|
int
|
The number of sellers. |
50
|
protocol
|
str
|
The protocol of the market, |
'order_book'
|
rounds
|
int
|
The number of quoting rounds of a trading period. |
20
|
constrained
|
bool
|
Whether traders never quote at a loss. |
True
|
ceiling
|
float
|
The highest price of the market. |
200.0
|
random_state
|
int | Generator | None
|
The seed or generator of the values and the costs. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the groups |
Raises:
| Type | Description |
|---|---|
ValueError
|
The protocol is unknown. |
Examples:
>>> from skcomplex.models.economics.markets import double_auction
>>> [group.size for group in double_auction(10, 8).elements]
[10, 8]
Source code in src/skcomplex/models/economics/markets/_double_auction.py
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 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 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 | |
fair_food(width=20, height=20, *, premium=0.3, ethics_weight=2.0, price_weight=5.0, social_weight=2.0, intensity=1.0, low_budget=1.0, high_budget=3.0, random_state=0)
Return Chesney's choice between fair-trade and regular food of consumers who influence their neighbours.
Every consumer, of uniform ethical concern and budget, sits on a cell of a grid and every step buys fair or regular food, all at once from the choices of their neighbours in the last step, as in the choice of Ajani. The share of fair food rises with the weight of ethics and falls with the premium, and social influence raises it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
width
|
int
|
The number of columns of the grid. |
20
|
height
|
int
|
The number of rows of the grid. |
20
|
premium
|
float
|
The extra price of fair food over regular food, which costs one. |
0.3
|
ethics_weight
|
float
|
The weight of ethical concern in the utility of fair food. |
2.0
|
price_weight
|
float
|
The weight of the premium relative to the budget. |
5.0
|
social_weight
|
float
|
The weight of the share of neighbours who buy fair food. |
2.0
|
intensity
|
float
|
The intensity of the logit choice. |
1.0
|
low_budget
|
float
|
The lowest budget. |
1.0
|
high_budget
|
float
|
The highest budget. |
3.0
|
random_state
|
int | Generator | None
|
The seed or generator of the ethics and the budgets. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the group |
Examples:
>>> from skcomplex.models.economics.markets import fair_food
>>> fair_food(5, 4).elements[0].check().prepare().size_
20
Source code in src/skcomplex/models/economics/markets/_fair_food.py
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 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 | |
goods_traders(n_traders=200, *, goods=3, width=20, height=20, quantity=0.1, mobility=0.5, low=1.0, high=20.0, random_state=0)
Return traders who wander a grid and barter two or three goods with their neighbours.
Every trader holds random amounts of the goods and values them with random Cobb-Douglas weights. Every step the traders wander to a random neighbouring cell, then every trader is paired with a neighbour, and the pairs barter while both gain, at the geometric mean of their marginal rates of substitution. Trades only move goods between the traders, so the total of every good is unchanged, while the mean utility rises and the prices of different trades converge, so the dispersion of the logarithm of the price falls, the toy and three-goods traders of Gooding (2019).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_traders
|
int
|
The number of traders. |
200
|
goods
|
int
|
The number of goods, 2 for sugar and spice or 3 with salt. |
3
|
width
|
int
|
The number of columns of the grid. |
20
|
height
|
int
|
The number of rows of the grid. |
20
|
quantity
|
float
|
The quantity of the bought good in every trade. |
0.1
|
mobility
|
float
|
The probability that a trader moves in a step. |
0.5
|
low
|
float
|
The smallest initial holding of a good. |
1.0
|
high
|
float
|
The largest initial holding of a good. |
20.0
|
random_state
|
int | Generator | None
|
The seed or generator of the cells, holdings, and weights. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the group |
Raises:
| Type | Description |
|---|---|
ValueError
|
The number of goods is not 2 or 3. |
Examples:
>>> from skcomplex.models.economics.markets import goods_traders
>>> goods_traders(20, goods=2).elements[0].check().prepare().size_
20
Source code in src/skcomplex/models/economics/markets/_goods_traders.py
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 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 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 | |
hire(trade, model)
Record the employer, the wage, and the steps of the hire and of its offer on the hired worker.
The hired worker keeps its search flag supply until the next step, which the market lowered when it cleared, so
the observable searching counts every worker who searched in the step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trade
|
MatchSpec
|
The match of a firm, the requester of labour, with a worker, its provider. |
required |
model
|
ModelView
|
The model view of the market. |
required |
Source code in src/skcomplex/models/economics/markets/_labour.py
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | |
labour_market(n_workers=200, n_firms=40, *, separation=0.05, vacancy_rate=0.3, reservation=1.0, decline=0.1, low_wage=0.5, high_wage=1.0, unemployment=0.5, random_state=0)
Return Hamill and Gilbert's labour market of firms posting wage offers and unemployed workers searching.
In the phase of offers, jobs are destroyed at the separation rate s, every firm posts a vacancy with a uniform
wage offer at the vacancy rate, and unemployed workers set reservation wages that fall with the duration of their
search. In the phase of matching, a deferred-acceptance market pairs vacancies with workers whose reservation wage
they cover, every worker getting the best offer of a stable matching. The unemployment rate settles at the
flow-balance value s / (s + f), with f the share of searching workers hired in a step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_workers
|
int
|
The number of workers. |
200
|
n_firms
|
int
|
The number of firms, each with at most one vacancy per step. |
40
|
separation
|
float
|
The probability |
0.05
|
vacancy_rate
|
float
|
The probability that a firm posts a vacancy in a step. |
0.3
|
reservation
|
float
|
The reservation wage at the start of a search. |
1.0
|
decline
|
float
|
The relative fall of the reservation wage per step of search. |
0.1
|
low_wage
|
float
|
The lowest wage offer. |
0.5
|
high_wage
|
float
|
The highest wage offer. |
1.0
|
unemployment
|
float
|
The initial share of unemployed workers. |
0.5
|
random_state
|
int | Generator | None
|
The seed or generator of the initial employment. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the groups |
Examples:
>>> from skcomplex.models.economics.markets import labour_market
>>> [group.size for group in labour_market(20, 5).elements]
[5, 20]
Source code in src/skcomplex/models/economics/markets/_labour.py
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 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 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 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 | |
marginal_rate(agent, good, numeraire, weights)
Return the marginal rate of substitution of a good for a numeraire, the units of numeraire one unit is worth.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
object
|
The agent. |
required |
good
|
str
|
The name of the state that holds the good. |
required |
numeraire
|
str
|
The name of the state that holds the numeraire. |
required |
weights
|
tuple[str, str]
|
The names of the states that hold the weights of the good and of the numeraire. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
rate |
float
|
The ratio of the marginal utilities, |
Examples:
>>> from types import SimpleNamespace
>>> from skcomplex.models.economics.markets import marginal_rate
>>> agent = SimpleNamespace(x=2.0, y=6.0, a=0.5, b=0.5)
>>> marginal_rate(agent, 'x', 'y', ('a', 'b'))
3.0
Source code in src/skcomplex/models/economics/markets/_exchange.py
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
maximum_surplus(values, costs)
Return the largest total surplus of single units, the competitive surplus of the supply and demand schedules.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
values
|
ndarray
|
The value of a unit to every buyer. |
required |
costs
|
ndarray
|
The cost of a unit to every seller. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
surplus |
float
|
The sum of the positive differences between the highest values and the lowest costs. |
Examples:
>>> import numpy as np
>>> from skcomplex.models.economics.markets import maximum_surplus
>>> maximum_surplus(np.array([10.0, 6.0, 2.0]), np.array([1.0, 4.0, 8.0]))
11.0
Source code in src/skcomplex/models/economics/markets/_auction_ledger.py
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | |
oligopoly_equilibria(n_firms=2, *, alpha=0.25, n_prices=21, demand=10.0, c_i=1.0, c_j=2.0, lambda_i=0.0, lambda_j=0.0, dynamics='static')
Return the equilibria of a Cournot duopoly and of a pricing game of firms with loyal customers and switchers.
The static model solves the Cournot best responses (Forrest 2018 Eqs. 21.5-21.6) and, on a grid of prices, the
symmetric mixed equilibrium of m firms of loyal share alpha and switchers beta = 1 - m alpha, whose price
distribution makes a firm indifferent among its prices, at the profit alpha (Lemma 20.1). With
dynamics='fictitious-play', two firms learn to price on the grid instead: every round each plays a best response
to the prices of its rival so far, and the prices they charge are distributed near the mixed equilibrium.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_firms
|
int
|
The number of firms of the pricing game, two under fictitious play. |
2
|
alpha
|
float
|
The loyal share of every firm. |
0.25
|
n_prices
|
int
|
The number of prices of the grid from |
21
|
demand
|
float
|
The intercept of the inverse demand of the Cournot duopoly. |
10.0
|
c_i
|
float
|
The unit cost of the first Cournot firm. |
1.0
|
c_j
|
float
|
The unit cost of the second Cournot firm. |
2.0
|
lambda_i
|
float
|
The cross holding of the first Cournot firm. |
0.0
|
lambda_j
|
float
|
The cross holding of the second Cournot firm. |
0.0
|
dynamics
|
str
|
|
'static'
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The static model, with the states |
Raises:
| Type | Description |
|---|---|
ValidationError
|
The dynamics are unknown, or fictitious play has other than two firms. |
Examples:
>>> from skcomplex.engine.runtime import Simulation
>>> from skcomplex.models.economics.markets import oligopoly_equilibria
>>> trajectory = Simulation(oligopoly_equilibria()).check().prepare().run(1.0).trajectory_
>>> round(float(trajectory.values('cournot.q_i')[0]), 6)
3.333333
Source code in src/skcomplex/models/economics/markets/_oligopoly.py
71 72 73 74 75 76 77 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 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | |
perishable_goods_duopoly(customers=200, *, stock=0.5, T=0.1, alpha=0.9, tau_a=1.0, random_state=0)
Return customers who choose between two shops of perishable goods, preferring the one that sold fresher goods.
Each shop holds stock products per customer, and every sale replaces a product with a fresh one, so the shop
with more customers sells fresher goods and attracts more customers. With the control parameter
R = 2 stock / tau_a, the symmetric state m = p_1 - p_2 = 0 loses its stability below the temperature
T_c = R / (1 + R)^2, and one shop takes most customers. The transition is continuous for R > sqrt(3) - 1 and
discontinuous below. One unit of time is N visits by customers drawn with replacement. A visited customer
chooses a shop with the probability 1 / (1 + exp(-(S_1 - S_2) / T)) for the first one, moves to it, buys a random
product of age tau, of freshness h = exp(-tau / tau_a), which the shop replaces with a fresh one, and updates
its satisfaction with that shop alone to alpha S + (1 - alpha) h. The shops are the two nodes of a network on
which their products stand.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
customers
|
int
|
The number of customers |
200
|
stock
|
float
|
The number of products of each shop per customer. |
0.5
|
T
|
float
|
The temperature of the choice, the randomness of the customers. |
0.1
|
alpha
|
float
|
The memory of the satisfaction, between 0 and 1. |
0.9
|
tau_a
|
float
|
The time over which the products age. |
1.0
|
random_state
|
int | Generator | None
|
The seed or generator of the initial satisfactions, which scatter by 0.01 around 0.5. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the groups |
Examples:
>>> from skcomplex.models.economics.markets import perishable_goods_duopoly
>>> perishable_goods_duopoly(20).elements[0].check().prepare().size_
20
Source code in src/skcomplex/models/economics/markets/_perishables.py
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 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 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 144 145 146 147 148 149 150 | |
produce_market(n_shoppers=50, n_stalls=9, *, n_items_stocked=6, random_state=0)
Return Hamill and Gilbert's produce market, where shoppers with lists of produce visit stalls at random.
There are twelve kinds of fruit and vegetables. Every stall sells a random selection of them at its own markup of 1 to 30 percent on the wholesale prices, and every shopper wants between one and eight of them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_shoppers
|
int
|
The number of shoppers. |
50
|
n_stalls
|
int
|
The number of stalls. |
9
|
n_items_stocked
|
int
|
The number of kinds of produce that every stall sells. |
6
|
random_state
|
int | Generator | None
|
The seed or generator of the stocks, the markups, and the shopping lists. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the groups |
Examples:
>>> from skcomplex.models.economics.markets import produce_market
>>> [group.size for group in produce_market(10, 3).elements]
[3, 10]
Source code in src/skcomplex/models/economics/markets/_produce.py
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 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 | |
riccati_prices(price=1.0, *, k=1.0, beta=10.0, lam=1.0, delta=1.0, alpha=2.0, gamma=-0.1)
Return a price that moves with excess demand under linear demand and saturating quadratic supply.
The price follows the Riccati equation dP/dt = k (D - S) with demand D = beta - lam P and supply
S = delta + alpha P + gamma P^2. When (lam + alpha)^2 > 4 gamma (delta - beta) there are two equilibrium prices,
and prices below the larger one converge to the smaller one. Otherwise the price blows up in finite time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
price
|
float
|
The initial price. |
1.0
|
k
|
float
|
The speed of the price adjustment. |
1.0
|
beta
|
float
|
The demand at price zero. |
10.0
|
lam
|
float
|
The slope of the demand. |
1.0
|
delta
|
float
|
The supply at price zero. |
1.0
|
alpha
|
float
|
The linear intensity of the supply. |
2.0
|
gamma
|
float
|
The quadratic intensity of the supply, negative for saturation. |
-0.1
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the price |
Examples:
>>> from skcomplex.models.economics.markets import riccati_prices
>>> riccati_prices(gamma=-0.2).elements[0].gamma
-0.2
Source code in src/skcomplex/models/economics/markets/_prices.py
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 144 145 146 147 148 149 150 151 | |
shops(n_shops=16, *, width=20, height=20, online=0.0, distance_cost=1.0, capacity=1000.0, fixed_cost=20.0, value=20.0, random_state=0)
Return shops on a grid that compete for the shoppers on every cell, in person or in a digital market.
Every step every shopper wants one unit and shops online with probability online, and in person otherwise, when it
pays a travel cost for the distance to the shop. The shoppers choose in random order the shops they prefer by price
plus travel cost, within the shops' capacities, a greedy matching that pays the shop's ask for a unit. Shops search
for the price of the largest profit by trial and error, pay a fixed cost every step, and close when their money runs
out. Distance gives every shop a local market, so many shops survive with high prices. In the digital market the
cheapest shop takes every shopper, the others undercut it, prices fall toward the unit cost, and most shops close
(Hamill and Gilbert 2016 sec. 6.3-6.4).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_shops
|
int
|
The initial number of shops. |
16
|
width
|
int
|
The number of columns of the grid, with one shopper per cell. |
20
|
height
|
int
|
The number of rows of the grid. |
20
|
online
|
float
|
The probability that a shopper shops online in a step. |
0.0
|
distance_cost
|
float
|
The travel cost per cell of shopping in person. |
1.0
|
capacity
|
float
|
The units every shop can sell in a step. |
1000.0
|
fixed_cost
|
float
|
The cost of running a shop for a step. |
20.0
|
value
|
float
|
The highest price a shopper pays. |
20.0
|
random_state
|
int | Generator | None
|
The seed or generator of the cells and initial prices of the shops. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the groups |
Examples:
>>> from skcomplex.models.economics.markets import shops
>>> [group.size for group in shops(4, width=5, height=5).elements]
[25, 4]
Source code in src/skcomplex/models/economics/markets/_shops.py
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 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 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 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 | |
sugarscape(width=50, height=50, *, n_foragers=400, max_vision=6, max_metabolism=4.0, low_sugar=5.0, high_sugar=25.0, growback=1.0, random_state=0)
Return the Sugarscape of Epstein and Axtell, foragers of random vision and metabolism on two sugar peaks.
Every step the foragers, in random order, move to the richest free cell in sight, harvest it, and burn their metabolism, and those whose wealth falls below zero die. Then the sugar grows back. Foragers of poor vision or high metabolism starve, so the population falls to the carrying capacity of the landscape, and the wealth of the survivors becomes skewed, with a Gini coefficient that rises from its initial value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
width
|
int
|
The number of columns. |
50
|
height
|
int
|
The number of rows. |
50
|
n_foragers
|
int
|
The initial number of foragers. |
400
|
max_vision
|
int
|
The largest vision, every forager seeing from 1 to |
6
|
max_metabolism
|
float
|
The largest metabolism, every forager burning from 1 to |
4.0
|
low_sugar
|
float
|
The lowest initial wealth. |
5.0
|
high_sugar
|
float
|
The highest initial wealth. |
25.0
|
growback
|
float
|
The sugar that grows back on every patch in a step. |
1.0
|
random_state
|
int | Generator | None
|
The seed or generator of the foragers' cells, visions, metabolisms, and wealth. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the groups |
Examples:
>>> from skcomplex.models.economics.markets import sugarscape
>>> [group.size for group in sugarscape(10, 10, n_foragers=20).elements]
[100, 20]
Source code in src/skcomplex/models/economics/markets/_sugarscape.py
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 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 | |
trade_goods(first, second, goods, weights, *, quantity=0.1, limit=1000)
Barter small quantities of goods between two agents while both gain, and return the trades.
For every pair of goods in turn, the agent that values the first good more in units of the second buys quantity
of it from the other at the geometric mean of their marginal rates of substitution, as in the Sugarscape trade of
Epstein and Axtell (1996). A trade happens only when it raises the Cobb-Douglas utility of both agents, and every
trade is two transfers, so the total of every good is unchanged. The agents trade until a round over all pairs of
goods makes no trade, or until limit trades.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
first
|
object
|
The first agent, with a state for the holding and for the weight of every good. |
required |
second
|
object
|
The second agent. |
required |
goods
|
Sequence[str]
|
The names of the states that hold the goods. |
required |
weights
|
Sequence[str]
|
The names of the states that hold the weights of the goods, in the order of |
required |
quantity
|
float
|
The quantity of the bought good in every trade. |
0.1
|
limit
|
int
|
The largest number of trades. |
1000
|
Returns:
| Name | Type | Description |
|---|---|---|
trades |
list[tuple[int, int, float]]
|
The index of the bought good, the index of the good paid with, and the price of every trade. |
Examples:
>>> from types import SimpleNamespace
>>> from skcomplex.models.economics.markets import trade_goods
>>> first = SimpleNamespace(x=9.0, y=1.0, a=0.5, b=0.5)
>>> second = SimpleNamespace(x=1.0, y=9.0, a=0.5, b=0.5)
>>> trades = trade_goods(first, second, ('x', 'y'), ('a', 'b'), quantity=0.5)
>>> first.x + second.x, len(trades) > 0
(10.0, True)
Source code in src/skcomplex/models/economics/markets/_exchange.py
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 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 | |
wilhite_trade_networks(n_agents=500, *, topology='small_world', n_groups=10, shortcuts=5, endowment=100.0, units=100, random_state=0)
Return Wilhite's bilateral barter of two goods among traders on one of four trade networks.
Traders start with random bundles of two goods and the utility good1 good2. Every step, each trader searches
its neighbours and trades with the one whose marginal rate of substitution differs the most, single units at a
price between their rates, while both gain. Trade drives the rates of every connected set of traders towards one
price. On the complete network every trader searches every other, so it needs the most searches, and traders crowd
onto the most extreme partners, so prices converge slowly. Isolated groups settle on different prices. Groups
chained by shared end traders, or a small world with some long links, bring the prices together with far fewer
searches.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_agents
|
int
|
The number of traders. |
500
|
topology
|
str
|
|
'small_world'
|
n_groups
|
int
|
The number of groups of the isolated, linked, and small-world networks. |
10
|
shortcuts
|
int
|
The number of random long links between groups of the small world. |
5
|
endowment
|
float
|
The largest initial holding of each good, drawn uniformly from 1 to it. |
100.0
|
units
|
int
|
The most units one pair trades in a step. |
100
|
random_state
|
int | Generator | None
|
The seed or generator of the bundles and the long links. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the group |
Raises:
| Type | Description |
|---|---|
ValueError
|
The topology is unknown. |
Examples:
>>> from skcomplex.models.economics.markets import wilhite_trade_networks
>>> system = wilhite_trade_networks(40, topology='isolated', n_groups=4)
>>> system.elements[0].check().prepare().size_
40
Source code in src/skcomplex/models/economics/markets/_barter_networks.py
64 65 66 67 68 69 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 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 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 | |