Skip to content

Clear FIXED and MULTI_STEP market bids in VirtualBidDispatch and SpreadBid - #299

Merged
jd-lara merged 8 commits into
jd/market_models2from
rh/bid_styles_mbc
Sep 14, 2026
Merged

jd-lara merged 8 commits into
jd/market_models2from
rh/bid_styles_mbc

Conversation

@rodrigomha

@rodrigomha rodrigomha commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Ports the day-ahead block-bid clearing into the market formulations, driven only by the two scalars PowerSystems #1784 puts on the market bid costs: curve_style (VARIABLE / FIXED, CURVE collapsed into VARIABLE) and curve_multistep (SINGLE_STEP / MULTI_STEP). No new formulation: VirtualBidDispatch partitions its variables by style and links periods by the multi-step flag plus the curves themselves.

VirtualBidDispatch

  • Every participant gets a per-period ActivePowerOutVariable / ActivePowerInVariable that settles and carries the location writes. The shared JuMP object for VARIABLE and the envelope settlement for FIXED are removed, so FIXED participants now also write into their settlement location.
  • FIXED: a per-period BlockBidCommitmentVariable for each direction the participant offers in, tied to the award by BlockBidQuantityConstraint (p = Q z) and priced on z from the curve's value. Time-series curves are supported. The envelope-span validation is gone since the envelope no longer prices anything; a curve with more than one segment at an offered period fails the build with the device named; a nonzero VOM is still rejected.
  • MULTI_STEP (either style): BlockBidLinkConstraint rows p[t] = p[t+1] between consecutive periods whose curves are identical. A change of curve or an empty period ends the block; a time-invariant curve is one block over the window. Multi-segment VARIABLE curves link too.

SpreadBid

  • Rejects FIXED only, a spread bid being always divisible, and links MULTI_STEP blocks of identical spread curves. ERCOT PTP obligation bids carry the multi-hour flag: in June 2026, 53,293 blocks, 33,037 accepted, 1 awarded a non-uniform MW.

Tests

Block-bid testsets rewritten on an extended three-period helper: static and time-series curves, single and multi-step, empty periods, partial blocks, a two-segment VARIABLE block, a rejected two-segment FIXED curve, and the spread-bid link rows. Full suite: 129,851 pass.

Validation on ERCOT DAM 2026-06-01

13,874 virtual participants, Gurobi at a 1% gap.

Detected multi-hour blocks at one fraction Fixed bid-hours matching ERCOT's award Settlement lambda MAE vs awarded-MW-weighted SPP
328 of 328 86.1% of 8,049 2.58 $/MWh

Every accepted ERCOT multi-hour block in June 2026 was awarded the same MW in every hour (0 exceptions in 7,516 bid blocks, 0 in 3,625 offer blocks), which is what the link rows enforce.

Merged from mb/ptp-fix (2026-09-12)

m-bossart's spread-bid fix (7d1fe90) is merged in: the spread bid's objective term goes through IncrementalBidOffer (a benefit, negative sign) with the matching concavity check, and a bid with no priced hour inside a shortened horizon holds its transfer at zero instead of clearing freely. The MULTI_STEP link rows run on the priced bids only. ERCOTMarketParser's mb/gtcs-part2 line pins this branch in place of mb/ptp-fix.

Dependencies

PowerSystems #1784 and SiennaSchemas #40 are merged; PowerOpenAPIModels #13 was closed and its rh/update_enums branch is the only pushed set of models carrying curve_multistep. The psy6 and IS4 heads moved to OpenAPI 1.x on 2026-09-10 against OpenAPI model packages that are not pushed yet, so until that alignment lands Project.toml and test/Project.toml pin PowerSystems to the #1784 merge commit, InfrastructureSystems to its last commit before the move, and the PowerOpenAPIModels subpackages to rh/update_enums, all marked temporary. Downstream checkouts should clear the PowerSystemCaseBuilder serialized_system caches after the PowerSystems change.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XgUkJVy9F23R3G5F8XFaLj

rodrigomha and others added 8 commits September 10, 2026 14:54
…adBid

PowerSystems #1784 collapses CurveStyles to VARIABLE / FIXED and adds
CurveMultiStep (curve_multistep) on both market bid costs. The market
formulations now read those two scalars and nothing else.

VirtualBidDispatch
- Every participant gets a per-period ActivePowerOut/InVariable that settles
  and carries the location writes; the shared JuMP object for VARIABLE and
  the envelope settlement for FIXED are gone.
- FIXED participants add a per-period BlockBidCommitmentVariable for each
  direction they offer in, tied to the award by BlockBidQuantityConstraint
  (p = Q z) and priced on z from the curve's value. Time-series curves are
  supported; the envelope-span validation is removed since the envelope no
  longer prices anything. A FIXED curve with more than one segment fails the
  build with the device named. Nonzero VOM on a FIXED bid is still rejected.
- MULTI_STEP participants of either style get BlockBidLinkConstraint rows
  p[t] = p[t+1] between consecutive periods whose curves are identical; a
  change of curve or an empty period ends the block. A time-invariant curve
  is one block over the window.
- An OfferWindow per (participant, direction) is read once per construct
  stage and shared by the commitment variables, quantity rows, objective
  terms and link rows.

SpreadBid
- Rejects FIXED only (a spread bid is always divisible) and links MULTI_STEP
  blocks of identical spread curves with BlockBidLinkConstraint rows.

Also: the _curve_style / _curve_multistep wrappers are replaced by PSY's
accessors; docstrings for BlockBidCommitmentVariable, VirtualBidDispatch and
SpreadBid describe the new behaviour.

Tests: the block-bid testsets are rewritten on an extended three-period
helper (static and time-series curves, single and multi-step, empty periods,
partial blocks, multi-segment VARIABLE blocks, rejected multi-segment FIXED),
plus a FIXED location-write test and a MULTI_STEP spread-bid test in the
nodal suite. Full suite: 129,851 pass.

Validation on ERCOT DAM 2026-06-01 (13,874 virtual participants, Gurobi,
1% gap): 328 detected multi-hour blocks all clear at one fraction, 86.1% of
8,049 Fixed bid-hours match ERCOT's award, settlement lambda MAE 2.58 $/MWh
against the awarded-MW-weighted SPP.

Co-development pins (temporary, revert once PowerSystems #1784 and its
SiennaSchemas / PowerOpenAPIModels companions merge): PowerSystems and the
PowerOpenAPIModels subpackages at rh/update_enums in Project.toml and
test/Project.toml.
…before its OpenAPI 1.x move

PowerSystems #1784 merged into psy6 and its rh/update_enums branch is gone, which broke
the previous pin. The psy6 and IS4 heads then moved to OpenAPI 1.x against OpenAPI model
packages that are not pushed yet, so neither head resolves from git. Until that alignment
lands: PowerSystems at the #1784 merge commit, InfrastructureSystems at its last commit
before the move, the PowerOpenAPIModels subpackages still at rh/update_enums. All marked
temporary in Project.toml and test/Project.toml.
…Systems and InfrastructureSystems pins

The docs build resolved InfrastructureOptimizationModels from jd/market_model, a branch
that no longer exists, and PowerSystems and InfrastructureSystems from heads that moved
to OpenAPI 1.x against unpushed model packages. The docs project now mirrors the root
Project.toml pins, marked temporary.
…e window

The OfferWindow struct and its cache memoized IOM._get_pwl_data so each consumer read a
curve once per construct stage. The saving was not measurable next to building the JuMP
containers, so the quantity rows, objective terms, segment check and block detection now
call the accessor at the period they need, which also removes four helpers. The one
behavioural piece stays: a time-invariant curve is one block over the window with no
per-period comparison, decided from the curve's own time variance.
Brings the spread-bid sign fix (IncrementalBidOffer: the bid is a benefit, not a cost),
the concavity check on its curve, and the zero-held transfer for bids with no priced hour
in the horizon; the multi-step link rows now run on the priced bids.
@jd-lara
jd-lara self-requested a review September 14, 2026 20:40
@jd-lara
jd-lara merged commit bc6a01d into jd/market_models2 Sep 14, 2026
1 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants