Market Lite¶
Public API for the storage-arbitrage market envs. Both focus on price-physics coupling rather than a full ISO market stack. For physics, see Physics → Markets. For the exact bid-based SCED solver, see API → Market SCED. For the GenCos competitive market, see API → Market MARL.
CostBasedMarketEnv¶
from powerzoojax.envs import (
CostBasedMarketEnv,
CostMarketState,
CostMarketParams,
make_cost_market_params,
)
Generator dispatch comes from dc_opf using true marginal costs. Reward is storage revenue sum(LMP * P * dt). The core CMDP vector is costs = (cost_thermal_overload,), with static name ("thermal_overload",). info["cost_sum"] is the aggregate diagnostic.
powerzoojax.envs.market.cost_based_market.CostBasedMarketEnv
¶
Bases: Environment
Cost-based LMP arbitrage environment for battery storage.
The agent controls batteries (via attached bundles) on the grid.
Generator dispatch comes from grid/dc_opf.dc_opf (ADMM). Nodal LMP
follows dc_opf._compute_lmp_alm — not clearing._compute_lmp_kkt_ed.
Action: concatenated bundle actions (see each ResourceBundle).
Observation: [lmp_norm, time_sin, time_cos, demand_norm,
powerzoojax.envs.market.cost_based_market.CostMarketState
¶
powerzoojax.envs.market.cost_based_market.CostMarketParams
¶
powerzoojax.envs.market.cost_based_market.make_cost_market_params(case, load_profiles=None, resources=(), lmp_scale=100.0, max_steps=48, delta_t_hours=0.5, steps_per_day=48, cost_thermal_weight=1.0)
¶
Create CostMarketParams from a CaseData.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
case
|
CaseData
|
CaseData instance (must have PTDF, cost coefficients, etc.). |
required |
load_profiles
|
Array
|
(T, n_loads) load demand array [MW]. If None, flat mid-range profile is generated. |
None
|
resources
|
tuple
|
Tuple of ResourceBundle instances (e.g. BatteryBundle).
If empty, a default single-device battery at external bus id 1
is created via |
()
|
lmp_scale
|
float
|
LMP normalisation factor for observations. |
100.0
|
max_steps
|
int
|
Episode length. |
48
|
delta_t_hours
|
float
|
Time step duration [hours]. |
0.5
|
steps_per_day
|
int
|
Steps per day (for time encoding). |
48
|
cost_thermal_weight
|
float
|
Weight for thermal overload cost. |
1.0
|
Returns:
| Type | Description |
|---|---|
CostMarketParams
|
CostMarketParams. |
BidBasedMarketEnv¶
from powerzoojax.envs import (
BidBasedMarketEnv,
BidMarketState,
BidMarketParams,
make_bid_market_params,
)
Approximate (heuristic) piecewise ED clearing on offer curves. Recovered LMPs are KKT-style approximations on true marginal cost (not exact dual prices). For paper-quality LMPs use the exact PD-IPM solver in Market SCED.
powerzoojax.envs.market.bid_based_market.BidBasedMarketEnv
¶
Bases: Environment
Competitive electricity market with piecewise-linear offer curves.
Battery agent participates in a market where generators submit offers.
Clearing uses piecewise_ed (approximate piecewise ED, not exact SCED).
LMP is MC-based KKT recovery at dispatch point; not a strict offer-price dual.
Action: concatenated bundle actions.
Observation: [lmp_norm, sin, cos, demand_norm, mean_offer_norm,
powerzoojax.envs.market.bid_based_market.BidMarketState
¶
powerzoojax.envs.market.bid_based_market.BidMarketParams
¶
powerzoojax.envs.market.bid_based_market.make_bid_market_params(case, load_profiles=None, resources=(), lmp_scale=100.0, max_steps=48, delta_t_hours=0.5, steps_per_day=48, cost_thermal_weight=1.0, n_segments=5, markup_std=0.05)
¶
Create BidMarketParams from a CaseData.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
case
|
CaseData
|
CaseData instance. |
required |
load_profiles
|
Array
|
(T, n_loads) load demand [MW]. If None, flat mid-range. |
None
|
resources
|
tuple
|
ResourceBundle tuple. If empty, default BatteryBundle at external bus id 1 (legacy defaults). |
()
|
lmp_scale
|
float
|
LMP normalisation factor. |
100.0
|
max_steps
|
int
|
Episode length. |
48
|
delta_t_hours
|
float
|
Time step duration [hours]. |
0.5
|
steps_per_day
|
int
|
Steps per day. |
48
|
cost_thermal_weight
|
float
|
Weight for thermal overload cost. |
1.0
|
n_segments
|
int
|
Number of offer curve segments per generator. |
5
|
markup_std
|
float
|
Std dev of random markup (0 = truthful bidding). |
0.05
|
Returns:
| Type | Description |
|---|---|
BidMarketParams
|
BidMarketParams. |
Alias exports¶
SimpleLMPArbitrageEnv, LMPMarketState, LMPMarketParams, and make_lmp_market_params are aliases of the cost-based equivalents. Either import path refers to the same implementation.
Shared market state¶
powerzoojax.envs.market.base.MarketState
¶
Bases: EnvState
Market environment state.
Extends EnvState with last LMP, dispatch fields, and attached resource
bundle states (SOC, etc.) in resource_states.
powerzoojax.envs.market.base.MarketParams
¶
Bases: EnvParams
Market environment parameters.
Holds grid and market configuration. Battery / DER physics live in
resources (e.g. BatteryBundle), not as flat fields on this struct.
Array fields (PTDF, costs, etc.) are JAX leaves; scalar config
fields are pytree_node=False (static under JIT).
Approximate clearing helpers (heuristic piecewise ED)¶
from powerzoojax.envs import make_cost_segments, piecewise_ed
from powerzoojax.envs.market.clearing import (
prepare_piecewise_ed,
PiecewiseEDSetup,
PiecewiseEDResult,
)
powerzoojax.envs.market.clearing.make_cost_segments(case, n_segments=5)
¶
Build piecewise-linear offer segments from quadratic cost data.
For each generator with MC(P) = mc_a·P² + mc_b·P + mc_c, the operating range [p_min, p_max] is divided into n_segments equal-width blocks. Price of each block = MC evaluated at block midpoint.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
case
|
CaseData
|
CaseData with unit cost coefficients and power limits. |
required |
n_segments
|
int
|
Number of segments per generator. |
5
|
Returns:
| Type | Description |
|---|---|
CostSegments
|
CostSegments with seg_widths (n_units, K) and seg_prices (n_units, K). |
powerzoojax.envs.market.clearing.prepare_piecewise_ed(case, n_segments=5)
¶
Prepare PiecewiseEDSetup from CaseData.
Called once at setup time. All heavy matrix operations use NumPy. The result is a frozen pytree passed to JIT-compiled functions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
case
|
CaseData
|
CaseData instance. |
required |
n_segments
|
int
|
Number of offer-curve segments per generator. |
5
|
Returns:
| Type | Description |
|---|---|
PiecewiseEDSetup
|
PiecewiseEDSetup ready for |
powerzoojax.envs.market.clearing.piecewise_ed(setup, node_load_mw, offer_prices=None, max_iter=50, tol=0.001)
¶
Solve piecewise-linear economic dispatch with congestion management.
This is an approximate network-constrained economic dispatch, not an
exact LP/QP SCED. Dispatch uses merit-order + iterative PTDF penalty
(heuristic, not globally optimal). LMP is recovered via weighted
least-squares KKT stationarity, not from LP dual variables.
Convergence is not guaranteed for all cases; check result.converged
before using the result in downstream analysis.
Merit-order dispatch: segments are sorted by price, filled cheapest-first.
Congestion managed by iterative penalty on line violations (same approach
as dc_opf.py).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
setup
|
PiecewiseEDSetup
|
Precomputed PiecewiseEDSetup. |
required |
node_load_mw
|
Array
|
(n_nodes,) nodal load [MW]. |
required |
offer_prices
|
Array
|
(n_units, n_segments) $/MWh. If None, uses base prices. |
None
|
max_iter
|
int
|
Maximum iterations for congestion management. |
50
|
tol
|
float
|
Convergence tolerance [MW]. |
0.001
|
Returns:
| Type | Description |
|---|---|
PiecewiseEDResult
|
PiecewiseEDResult. |
powerzoojax.envs.market.clearing.PiecewiseEDSetup
¶
Precomputed data for piecewise-linear economic dispatch.
Created once at setup time (NumPy), used at runtime (JAX).
powerzoojax.envs.market.clearing.PiecewiseEDResult
¶
Output of piecewise-linear economic dispatch.