Skip to content

Cobweb

A market whose price converges to or oscillates around equilibrium as supply lags the price.

  • Name: cobweb
  • Field: economics/markets
  • Formalism: discrete map
  • References: Ezekiel 1938

Factory

@register_model(
    field='economics/markets',
    tags=('market', 'discrete map'),
    references=('Ezekiel 1938',),
    defaults={'until': 30, 'dt': 1},
)
def cobweb(price: float = 1.0, *, a: float = 10.0, b: float = 2.0, c: float = 1.0, d: float = 1.0) -> System:
    """Return a market whose price converges to or oscillates around equilibrium as supply lags the price.

    Args:
        price:
            The initial price.

        a:
            The demand intercept.

        b:
            The demand slope.

        c:
            The supply intercept.

        d:
            The supply slope.

    Returns:
        system:
            The model, with the market `market`.

    Examples:
        >>> from skcomplex.models.economics.markets import cobweb
        >>> cobweb(price=2.0).elements[0].price
        2.0
    """
    return System(
        elements=[MarketElement('market', price=price)],
        interactions=[CobwebInteraction('cobweb', target='market', a=a, b=b, c=c, d=d)],
    )

Components

class MarketElement(Element):
    """Market of one good described by its price.

    Args:
        label:
            The label of the market.

        visual:
            How the element is drawn, or `None` for `default_visual_`.

        price:
            The initial price.

    Examples:
        >>> from skcomplex.models.economics.markets import MarketElement
        >>> MarketElement('wheat', price=2.0).price
        2.0
    """

    def __init__(
        self,
        label: str,
        visual: VisualSpec | None = None,
        *,
        price: Annotated[float, StateSpec()] = 1.0,
    ) -> None:
        super().__init__(label, visual=visual)
        self.price = price

class CobwebInteraction(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.

    Args:
        label:
            The label of the interaction.

        target:
            The path of the market.

        a:
            The demand intercept.

        b:
            The demand slope.

        c:
            The supply intercept.

        d:
            The supply slope.

    Examples:
        >>> from skcomplex.models.economics.markets import CobwebInteraction
        >>> CobwebInteraction('cobweb', target='wheat', a=10, b=2, c=1, d=1).b
        2
    """

    def __init__(
        self,
        label: str,
        *,
        target: Annotated[str, RoleSpec()],
        a: Annotated[float, ParameterSpec()] = 10.0,
        b: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 2.0,
        c: Annotated[float, ParameterSpec()] = 1.0,
        d: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.0,
    ) -> None:
        super().__init__(label, target=target, state='price', function=self._get_price)
        self.a = a
        self.b = b
        self.c = c
        self.d = d

    @staticmethod
    def _get_price(s: SimpleNamespace) -> Expression:
        """Return the next price `(a - c - d * price) / b`, at which demand buys the supply of the last price."""
        return (s.a - s.c - s.d * s.target.price) / s.b

Equations

market.price: price_market(t + 1) == -(d_cobweb*price_market(t) - a_cobweb + c_cobweb)/b_cobweb