Clear FIXED and MULTI_STEP market bids in VirtualBidDispatch and SpreadBid - #299
Merged
Merged
Conversation
…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.
…already includes #1783
…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
self-requested a review
September 14, 2026 20:40
jd-lara
approved these changes
Sep 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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) andcurve_multistep(SINGLE_STEP / MULTI_STEP). No new formulation:VirtualBidDispatchpartitions its variables by style and links periods by the multi-step flag plus the curves themselves.VirtualBidDispatch
ActivePowerOutVariable/ActivePowerInVariablethat 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.BlockBidCommitmentVariablefor each direction the participant offers in, tied to the award byBlockBidQuantityConstraint(p = Q z) and priced onzfrom 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.BlockBidLinkConstraintrowsp[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
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.
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 throughIncrementalBidOffer(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'smb/gtcs-part2line pins this branch in place ofmb/ptp-fix.Dependencies
PowerSystems #1784 and SiennaSchemas #40 are merged; PowerOpenAPIModels #13 was closed and its
rh/update_enumsbranch is the only pushed set of models carryingcurve_multistep. Thepsy6andIS4heads moved to OpenAPI 1.x on 2026-09-10 against OpenAPI model packages that are not pushed yet, so until that alignment landsProject.tomlandtest/Project.tomlpin PowerSystems to the #1784 merge commit, InfrastructureSystems to its last commit before the move, and the PowerOpenAPIModels subpackages torh/update_enums, all marked temporary. Downstream checkouts should clear the PowerSystemCaseBuilderserialized_systemcaches after the PowerSystems change.🤖 Generated with Claude Code
https://claude.ai/code/session_01XgUkJVy9F23R3G5F8XFaLj