Skip to content

odys.domain.entities.market

Energy market for buying and selling power. Supports buy-only, sell-only, or bidirectional trading, with optional stage-fixed variables.

See EnergyMarket in the User Guide.

Energy market definitions for energy system models.

AllowedTradeDirection

Bases: StrEnum

Allowed trading direction for an energy market.

Determines whether a market permits buying energy, selling energy, or both. For BUY_AND_SELL markets, buying and selling are mutually exclusive within each timestep.

Source code in src/odys/domain/entities/market.py
11
12
13
14
15
16
17
18
19
20
21
class AllowedTradeDirection(StrEnum):
    """Allowed trading direction for an energy market.

    Determines whether a market permits buying energy, selling energy,
    or both. For ``BUY_AND_SELL`` markets, buying and selling are mutually
    exclusive within each timestep.
    """

    BUY_ONLY = "buy"
    SELL_ONLY = "sell"
    BUY_AND_SELL = "buy_and_sell"

EnergyMarket

Bases: EnergyEntity

An electricity market where the portfolio can buy or sell energy.

An energy market enables the optimizer to procure or sell energy at scenario-specific prices defined in the scenario. The optimizer decides how much to buy or sell in each timestep, subject to volume limits and the permitted trading direction. Markets participate in the power balance constraint and contribute to the objective through trading revenue or cost.

When stage_fixed is True, trading decisions are locked before uncertainty is resolved; the same volumes apply across all stochastic scenarios. This models day-ahead or forward markets where commitments are made without knowing the realized future. Markets with stage_fixed False can react to each scenario independently.

Attributes:

Name Type Description
name str

Unique name of the energy market. Each scenario gives its prices in a PriceProfile that references the market.

max_trading_volume_per_step float

Maximum power (in MW) that can be traded in a single optimization timestep. The traded energy is this power times the timestep length.

allowed_trade_direction AllowedTradeDirection

Allowed trading direction for the market.

stage_fixed bool

If True, trading volumes are fixed across all stochastic scenarios (non-anticipativity constraint).

Source code in src/odys/domain/entities/market.py
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
class EnergyMarket(EnergyEntity):
    """An electricity market where the portfolio can buy or sell energy.

    An energy market enables the optimizer to procure or sell energy at
    scenario-specific prices defined in the scenario. The optimizer decides
    how much to buy or sell in each timestep, subject to volume limits and
    the permitted trading direction. Markets participate in the power balance
    constraint and contribute to the objective through trading revenue or cost.

    When ``stage_fixed`` is ``True``, trading decisions are locked before
    uncertainty is resolved; the same volumes apply across all stochastic
    scenarios. This models day-ahead or forward markets where commitments
    are made without knowing the realized future. Markets with
    ``stage_fixed`` ``False`` can react to each scenario independently.

    Attributes:
        name: Unique name of the energy market. Each scenario gives its prices
            in a ``PriceProfile`` that references the market.
        max_trading_volume_per_step: Maximum power (in MW) that can be traded
            in a single optimization timestep. The traded energy is this power
            times the timestep length.
        allowed_trade_direction: Allowed trading direction for the market.
        stage_fixed: If ``True``, trading volumes are fixed across all stochastic
            scenarios (non-anticipativity constraint).
    """

    name: str
    max_trading_volume_per_step: float = Field(gt=0)
    allowed_trade_direction: AllowedTradeDirection = AllowedTradeDirection.BUY_AND_SELL
    stage_fixed: bool = Field(
        default=False,
        description="If true, the associated variables are fixed across scenarios.",
    )

    def max_supply(self, conditions: OperatingConditions) -> tuple[float, ...]:
        """Return the maximum trading volume at each timestep, in MW."""
        return (self.max_trading_volume_per_step,) * conditions.horizon.number_of_steps

max_supply(conditions)

Return the maximum trading volume at each timestep, in MW.

Source code in src/odys/domain/entities/market.py
58
59
60
def max_supply(self, conditions: OperatingConditions) -> tuple[float, ...]:
    """Return the maximum trading volume at each timestep, in MW."""
    return (self.max_trading_volume_per_step,) * conditions.horizon.number_of_steps