-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b3aa9c1
commit 9b457f0
Showing
2 changed files
with
294 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,291 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": { | ||
"id": "4JeBorbE6FYr" | ||
}, | ||
"source": [ | ||
"# 5. Bidding Strategy tutorial\n", | ||
"\n", | ||
"In this part of the tutorial, we formulate a rule-based bidding strategy for the Electrolyser unit. Rule-based strategies guide the unit's market participation by following a predefined set of rules and guidelines, enabling it to make market offers autonomously.\n", | ||
"\n", | ||
"\n", | ||
"A rule-based bidding strategy is a set of algorithmic guidelines that dictate how a unit should participate in the electricity market. This is particularly important for:\n", | ||
"\n", | ||
"- **Automated Decision-making**: Allows the unit to make bids autonomously, reducing the need for human intervention.\n", | ||
"- **Market Adaptability**: Enables the unit to adjust its bidding behavior in response to dynamic market conditions.\n", | ||
"\n", | ||
"**Key Components to consider to establish Rule-Based Bidding Strategy**\n", | ||
"\n", | ||
"1. **Product Type**: This sets the stage for the kind of products (e.g., energy, ancillary services) that the unit will bid for in the electricity market.\n", | ||
"2. **Bid Volume**: The quantity of the product that the unit offers in its bid.\n", | ||
"3. **Marginal Revenue**: Used to determine the price at which the unit should make its bid. This involves calculating the unit's incremental revenue for additional units of electricity sold or consumed.\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"#Some important imports\n", | ||
"from assume.common.base import BaseStrategy, SupportsMinMax\n", | ||
"from assume.common.market_objects import MarketConfig, Order, Orderbook, Product" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# install JDC that allows us defining functions of classes across different cells\n", | ||
"%pip install jdc" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## 1. Define `NaiveStrategyElectrolyser` Class\n", | ||
"The `NaiveStrategyElectrolyser` class inherits from the `BaseStrategy` class and implements the `calculate_bids` method, which is responsible for formulating the market bids." | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### 1.1. Key Methods and Parameters\n", | ||
"- `calculate_bids`: This method takes several arguments, including the unit to be dispatched (`unit`), the market configuration (`market_config`), and a list of products (`product_tuples`). It returns an `Orderbook` containing the bids.\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"class NaiveStrategyElectrolyser(BaseStrategy):\n", | ||
" \"\"\"\n", | ||
" A naive strategy that bids the marginal cost of the electrolyser on the market.\n", | ||
" \"\"\"\n", | ||
"\n", | ||
" def calculate_bids(\n", | ||
" self,\n", | ||
" unit: SupportsMinMax,\n", | ||
" market_config: MarketConfig,\n", | ||
" product_tuples: list[Product],\n", | ||
" **kwargs,\n", | ||
" ) -> Orderbook:\n", | ||
" \n", | ||
" \"\"\"\n", | ||
" Takes information from a unit that the unit operator manages and\n", | ||
" defines how it is dispatched to the market\n", | ||
" :param unit: the unit to be dispatched\n", | ||
" :type unit: SupportsMinMax\n", | ||
" :param market_config: the market configuration\n", | ||
" :type market_config: MarketConfig\n", | ||
" :param product_tuples: list of all products the unit can offer\n", | ||
" :type product_tuples: list[Product]\n", | ||
" :return: the bids\n", | ||
" :rtype: Orderbook\n", | ||
" \"\"\"" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"start = product_tuples[0][0] # start time of the first product" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### 1.1.1 Calculating Marginal Revenue: The Mathematical Equation\n", | ||
"\n", | ||
"Calculating marginal revenue is crucial for grasping the economics of the bidding strategy. The formula used in the code is as follows:\n", | ||
"\n", | ||
"\\[\n", | ||
"\\text{Marginal Revenue} = \\left( \\text{Hydrogen Price} - \\text{Fixed Cost} \\right) \\times \\frac{\\text{Hydrogen Production}}{\\text{Power}}\n", | ||
"\\]\n", | ||
"\n", | ||
"**Parameters Explained** \n", | ||
"\n", | ||
"- **Hydrogen Price**: The price of hydrogen at the specific time frame, fetched from the unit's forecaster.\n", | ||
"- **Fixed Cost**: The constant cost associated with the unit, not varying with the amount of power or hydrogen produced.\n", | ||
"- **Hydrogen Production**: The amount of hydrogen produced during the given time frame, calculated based on the hydrogen demand.\n", | ||
"- **Power**: The electrical power consumed by the Electrolyser unit to produce the given amount of hydrogen.\n", | ||
"\n", | ||
"**Why is This Formula Important?**\n", | ||
"\n", | ||
"1. **Economic Efficiency**: This formula helps in determining the most economically efficient way to bid in the electricity market.\n", | ||
"2. **Optimal Pricing**: Knowing your marginal revenue enables you to set your bid price optimally, maximizing profitability while maintaining competitiveness.\n", | ||
"3. **Demand-Side Management (DSM)**: Accurate calculation of marginal revenue is essential for effective DSM strategies, allowing the unit to respond appropriately to market signals.\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"bids = []\n", | ||
"for product in product_tuples:\n", | ||
" \"\"\"\n", | ||
" for each product, calculate the marginal revenue of the unit at the start time of the product\n", | ||
" and the volume of the product. Dispatch the order to the market.\n", | ||
" \"\"\"" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"**1. Fetch Start and End Times:** For each product, the loop fetches the start and end times." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"start = product[0]\n", | ||
"end = product[1]" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"**2. Retrieve Hydrogen Demand and Price:** The hydrogen demand and price are fetched from the unit's forecaster for the corresponding start time." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Calculate marginal cost using the adjusted efficiency\n", | ||
"hydrogen_demand = unit.forecaster[f\"{unit.id}_h2demand\"].loc[start]\n", | ||
"hydrogen_price = unit.forecaster[f\"{unit.id}_h2price\"].loc[start]" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"**3. Calculate Bid Volume:** The code calls unit.calculate_min_max_power to determine the bid volume based on the hydrogen demand." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"power, hydrogen_production = unit.calculate_min_max_power(\n", | ||
" start=start,\n", | ||
" end=end,\n", | ||
" hydrogen_demand=hydrogen_demand,\n", | ||
")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### 1.1.2 Calculate Marginal Revenue and Bid Price: Using the formula discussed in the previous section, the marginal revenue is calculated to determine the bid price" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"marginal_revenue = (hydrogen_price - unit.fixed_cost) * hydrogen_production / power" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"bid_price = marginal_revenue" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### 1.1.3 Creating Market Orders and Finalizing Bids\n", | ||
"\n", | ||
"In this segment of the tutorial, we shall explore how market orders are generated and added to the bids list. This step is crucial as it translates our calculated bid volume and price into actionable market orders.\n", | ||
"\n", | ||
"The `Order` dictionary object encapsulates all the necessary information for a single bid. It includes the following key-value pairs:\n", | ||
"\n", | ||
"- **`start_time` and `end_time`**: The time window for which the bid is valid.\n", | ||
"- **`volume`**: The bid volume, which is the power calculated based on hydrogen demand.\n", | ||
"- **`price`**: The bid price, determined by the marginal revenue." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"order: Order = {\n", | ||
" \"start_time\": product[0],\n", | ||
" \"end_time\": product[1],\n", | ||
" \"only_hours\": product[2],\n", | ||
" \"price\": bid_price,\n", | ||
" \"volume\": -power,\n", | ||
"}\n", | ||
"bids.append(order)" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"colab": { | ||
"include_colab_link": true, | ||
"provenance": [], | ||
"toc_visible": true | ||
}, | ||
"kernelspec": { | ||
"display_name": "Python 3.11.6 ('assume')", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.11.6" | ||
}, | ||
"nbsphinx": { | ||
"execute": "never" | ||
}, | ||
"vscode": { | ||
"interpreter": { | ||
"hash": "cfc2cf6567cc141267e866e462ba8c1a537952763adcaa946846522afc0034a3" | ||
} | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
SPDX-FileCopyrightText: ASSUME Developers | ||
|
||
SPDX-License-Identifier: AGPL-3.0-or-later |