# Coupled Simulation This page explains the working of the coupled simulation. ## Bids `Annular` performs a simulation based on the principles of the [EPEX] day-ahead market. A satellite model expresses its (flexible) demand by submitting bids to the market. These bids can be expressed as a table with the following structure: | exclusive_group_id | profile_block_id | sense | timestamp | quantity | acceptance_ratio | price | |--------------------|------------------|-------|-----------|----------|------------------|-------| | ... | ... | ... | ... | ... | ... | | The column names are accessible through [`ALL_BID_COLUMNS`]. Where - `sense` indicates demand or supply bids. See the documentation for [`Sense`]. - `quantity` is the amount requested to supply or demand. Needs to be non-negative. - `acceptance_ratio` is the minimum acceptance ratio, and needs to be 1 in current versions. - `price` is the supply or demand price. Block bids are defined by `(exclusive_group_id, profile_block_id, sense)`. Within block bid, `price` and `acceptance_ratio` need to be the same for all rows. For more information on the `exclusive_group_id` and `profile_block_id` columns, see the sections on Profile Block and Exclusive Group bid types below. ### Bid types `Annular` currently supports the following bid types, as introduced on the [EPEX] website: (profile-blocks)= #### Profile Blocks > **Classic block orders** encompass several hours at the same price with flexible volume profiles > and are executed at the same ratio on all its hours. Each row in the bids table only specifies a bid for a single timestamp. Since bids for single timestamps are independent by default, such bids do not support any behavior with temporal dependencies. Profile blocks are a solution to this: a multi-timestamp **profile** of demand or supply bids can be submitted to be executed in an All-or-None manner. All bid rows that share a `profile_block_id` will be treated as a single profile and will therefore be executed together. ```{important} A profile may only contain one bid per timestamp per sense. ``` ```{note} Reusing Profile block IDs When using an exclusive group, all IDs for the Profile blocks are only used within that exclusive group. This means that the same `profile_block_id` can be used multiple times, as long as they are in different exclusive groups. ``` (exclusive-groups)= #### Exclusive Groups > **Exclusive blocks**: group of blocks within which a maximum of one block can be executed, so your > electricity is traded at the most profitable moment An exclusive group of blocks is specified when bids in the table share the same `exclusive_group_id`. Within an exclusive group, at most one profile will be accepted. By itself, an exclusive group gives no guarantee that any of its profile blocks are actually accepted. (looped-blocks)= #### Looped Blocks > **Loop blocks**: families of two blocks which are executed or rejected together. They allow to > bundle buy and sell blocks to reflect storage activities. In `annular`, only demand and supply bids/blocks can be 'looped' together. To do so, they must share the same `profile_block_id` and `exclusive_group_id`. ```{note} Acceptance guarantees A demand bid/block at ceiling price that is looped with a supply bid/block is no longer guaranteed to be accepted. Since both the demand and supply side must be executed simultaneously, if the supply side cannot be executed, it will prevent the demand side from being executed too. ``` #### Curtailable Blocks > **Curtailable blocks**: set of blocks which can be either entirely executed or entirely rejected > (All-or-None); or executed above a minimum acceptance ratio defined by traders. Although the bids table specification already includes a column `acceptance_ratio`, curtailable blocks are not yet supported. All bids must use a value of `1` in the `acceptance_ratio` column, and will be executed on an All-or-None basis. #### Not Implemented **Linked Blocks** and **Exclusive Links** are currently not supported by `annular`. ### Example This example illustrates a valid bid: | exclusive_group_id | profile_block_id | sense | timestamp | quantity | acceptance_ratio | price | |--------------------|------------------|-------|-----------|----------|------------------|-------| | 1 | 1 | 1 | 0 | 30 | 1 | 30 | | 1 | 1 | 1 | 1 | 10 | 1 | 30 | | 1 | 1 | 1 | 2 | 50 | 1 | 30 | | 1 | 1 | -1 | 5 | 9 | 1 | 14 | | 1 | 1 | -1 | 6 | 8 | 1 | 14 | There are two profiles, a demand profile for the first 3 hours at a price of 30, and a supply profile at hours 5 and 6 for a price of 14. Because they have the same `profile_block_id`, they are either rejected or accepted together. [`Sense`]: #annular.utils.Sense [`ALL_BID_COLUMNS`]: #annular.market_model.ALL_BID_COLUMNS [EPEX]: https://www.epexspot.com/en/tradingproducts#day-ahead-trading