battery_optimizer_app.orderbook_bucketing#

Functions

block_best_orderbook_buckets(orderbook, ...)

Block best-priced orderbook buckets per timepoint according to blocked capacities. Handles both buy and sell volumes for each blocked capacity. Works with orderbooks that have 'buyOrders' and 'sellOrders' columns. Logs if there are not enough orders to block the requested volume. Key insight: optimizer blocked sell capacities need to be removed from market/orderbook buy orders, and vice versa - When optimizer BOUGHT (volume_bought_MW): optimizer matched against market SELL orders → block sellOrders - When optimizer SOLD (volume_sold_MW): optimizer matched against market BUY orders → block buyOrders.

block_orders(orders, volume_to_block, ...)

Block volume from a list of orders, sorted by best price first.

convert_orderbook_to_dataframe(...)

The unzipped orderbook is transformed to a pd.DataFrame.

convert_to_timestamp(ts)

Convert timestamp (string, ...) to Pandas timestamps

decompress_orderbook(gzipped_orderbook)

Takes the base64 encoded and gzipped orderbook and returns a json-style string

fill_in_untraded_buckets(dict_of_buckets, ...)

Fill in max_volume of buckets that lie outside the traded time window with the maximal power of the asset.

filter_EPEX_orderbook(orderbook[, product, ...])

Filter the dataframe EPEX orderbook to get only the ones with a certain delivery length.

filter_orderbook(orderbook, delivery_length)

Filter the dataframe VATP orderbook to get only the ones with a certain delivery length.

get_EPEX_orderbook_in_buckets(...[, ...])

Returns price buckets considering the given parameters based on the passed orderbook in EPEX format.

get_all_orders_per_delivery_time(rows, ...)

The passed order book is filtered such that the returned orders are offering enough energy to fulfill the requested max energy.

get_max_prices_per_bucket(rows, market_side, ...)

The maximum price of a bucket is always the maximum/minimum price that is needed to fulfill the bucket plus the buckets before.

get_orderbook_in_buckets(gzipped_orderbook, ...)

Returns price buckets considering the given parameters based on the passed orderbook in VATP format.

get_vwap_per_bucket(rows, market_side, ...)

The vwap of a bucket is the vwap of all prices that are needed to fulfill energy needed in the bucket.

read_gzipped_orderbook(file_path)

Read a gzipped orderbook from a file path

Classes

BucketingApproach(*values)

Here we define the possible bucketing approaches.

class battery_optimizer_app.orderbook_bucketing.BucketingApproach(*values)#

Bases: StrEnum

Here we define the possible bucketing approaches.

Args:

StrEnum (_type_): One of whole, vwap, max

max = 'max'#
vwap = 'vwap'#
whole = 'whole'#
battery_optimizer_app.orderbook_bucketing.block_best_orderbook_buckets(orderbook, blocked_capacities, request_id=None)#

Block best-priced orderbook buckets per timepoint according to blocked capacities. Handles both buy and sell volumes for each blocked capacity. Works with orderbooks that have ‘buyOrders’ and ‘sellOrders’ columns. Logs if there are not enough orders to block the requested volume. Key insight: optimizer blocked sell capacities need to be removed from market/orderbook buy orders, and vice versa

  • When optimizer BOUGHT (volume_bought_MW): optimizer matched against market SELL orders → block sellOrders

  • When optimizer SOLD (volume_sold_MW): optimizer matched against market BUY orders → block buyOrders

Args:
orderbook: DataFrame with orderbook data. Each row represents a unique delivery period.

Example structure: exchange deliveryArea deliveryStartTime … type buyOrders sellOrders EPEX TTG 2025-08-04 14:45 … QuarterHour [list of dicts] [list of dicts] EPEX TTG 2025-08-04 15:00 … QuarterHour [list of dicts] [list of dicts] Note: deliveryStartTime values are unique (one row per timestamp)

blocked_capacities: List of EnergyMarketContinuousPositions with blocked volumes request_id: Optional request ID for logging

battery_optimizer_app.orderbook_bucketing.block_orders(orders, volume_to_block, is_buy, request_id, timestamp, side)#

Block volume from a list of orders, sorted by best price first. Returns updated orders and remaining volume to block.

Args:

orders: List of order dicts with ‘price’ and ‘quantity’ keys volume_to_block: Amount of volume to block (MW) is_buy: True if blocking buy orders (highest price first), False for sell orders (lowest price first) request_id: Request ID for logging timestamp: Timestamp for logging side: “buy” or “sell” for logging

Returns:

Tuple of (updated_orders, remaining_volume_to_block)

battery_optimizer_app.orderbook_bucketing.convert_orderbook_to_dataframe(unzipped_orderbook)#

The unzipped orderbook is transformed to a pd.DataFrame. Each row of the dataframe contains the information for one delivery period. The columns “buyOrders” and “sellOrders” contain the infos for all the orders for the specific delivery period. The placed orders are stored in a list of dicts.

Args:

unzipped_orderbook (str): the unzipped orderbook as a json-style string

Returns:

pd.Dataframe: the orderbook as a dataframe

Parameters:

unzipped_orderbook (str)

Return type:

DataFrame

battery_optimizer_app.orderbook_bucketing.convert_to_timestamp(ts)#

Convert timestamp (string, …) to Pandas timestamps

Args:

ts (pd.Series): Timestamps to convert

Returns:

pd.Series: Pandas timestamps

Parameters:

ts (Series)

Return type:

Series

battery_optimizer_app.orderbook_bucketing.decompress_orderbook(gzipped_orderbook)#

Takes the base64 encoded and gzipped orderbook and returns a json-style string

Args:

gzipped_orderbook (bytes): base64 encoded and gzipped orderbook

Returns:

str: orderbook as json-style string

Parameters:

gzipped_orderbook (bytes)

Return type:

str

battery_optimizer_app.orderbook_bucketing.fill_in_untraded_buckets(dict_of_buckets, last_intraday_traded_timestamp, max_power_MW)#

Fill in max_volume of buckets that lie outside the traded time window with the maximal power of the asset.

Parameters:
  • dict_of_buckets (dict)

  • last_intraday_traded_timestamp (Timestamp)

  • max_power_MW (float)

Return type:

dict

battery_optimizer_app.orderbook_bucketing.filter_EPEX_orderbook(orderbook, product=None, delivery_start=None)#

Filter the dataframe EPEX orderbook to get only the ones with a certain delivery length. Optionally filter in addition for a certain delivery start.

Args:

orderbook (pd.Dataframe): The EPEX orderbook already in a dataframe product (str): EPEX product (equivalent to delivery length in VATP). Defaults to None. delivery_start (pd.Timestamp, optional): The start of the delivery period. Defaults to None.

Returns:

pd.DataFrame: _description_

Parameters:
  • orderbook (DataFrame)

  • product (str)

  • delivery_start (Timestamp)

Return type:

DataFrame

battery_optimizer_app.orderbook_bucketing.filter_orderbook(orderbook, delivery_length, delivery_start=None, delivery_end=None, only_one_period=True)#

Filter the dataframe VATP orderbook to get only the ones with a certain delivery length. Optionally filter in addition for a certain delivery start.

Args:

orderbook (pd.Dataframe): The VATP orderbook already in a dataframe delivery_length (str): Length of the delivery period delivery_start (pd.Timestamp, optional): The start of the delivery period. Defaults to None. delivery_end (pd.Timestamp, optional): The end of the delivery period. Defaults to None. only_one_period (bool, optional): whether or not only one period should get returned. Defaults to True.

Returns:

pd.DataFrame: _description_

Parameters:
  • orderbook (DataFrame)

  • delivery_length (str)

  • delivery_start (Timestamp)

  • delivery_end (Timestamp)

  • only_one_period (bool)

Return type:

DataFrame

battery_optimizer_app.orderbook_bucketing.get_EPEX_orderbook_in_buckets(filtered_EPEX_orderbook, bucketing_approach, max_power_MW, bucket_size=None, product=None, delivery_start=None, groupby_prices=True)#

Returns price buckets considering the given parameters based on the passed orderbook in EPEX format. The orderbook should already be filtered for the correct trading time and active orders. The price sides for export is inverted to the market side as we have to take the viewpoint of the optimizer: buying implies costs, selling generates revenues.

Args:

filtered_EPEX_orderbook (pd.DataFrame): the EPEX orderbook prefiltered for trading time and active orders. bucketing_approach (BucketingApproach): either the whole orderbook, the max price per bucket or the vwap per bucket. max_power_MW (float): The amount of energy (either volume or quantity) that should get bought/sold. bucket_size (float, optional): The size the buckets should have in the same unit as max_energy. Defaults to None. delivery_length (str, optional): The delivery length of the products that should be considered. Defaults to None. delivery_start (pd.Timestamp, optional): The delivery start of the prodcut to be considered. Defaults to None. groupby_prices (bool, optional): If buckets with the same price should be combined into one bucket. Defaults to True.

Returns:

dict: A dict of dicts of the format {delivery start timestamp, sell buckets as list of dicts, buy buckets as list of dicts}

Parameters:
  • filtered_EPEX_orderbook (DataFrame)

  • bucketing_approach (BucketingApproach)

  • max_power_MW (float)

  • bucket_size (float)

  • product (str)

  • delivery_start (Timestamp)

  • groupby_prices (bool)

Return type:

dict

battery_optimizer_app.orderbook_bucketing.get_all_orders_per_delivery_time(rows, market_side, max_energy, price_col='price', energy_col='quantity', time_col='timestamp')#

The passed order book is filtered such that the returned orders are offering enough energy to fulfill the requested max energy.

Args:

rows (pd.DataFrame): The orders for one price side for one delivery period at a given trading timestamp. market_side (str): The market side as seen on a trading screen. ‘BUY’ or ‘SELL’ max_energy (float): The amount of energy (either volume or quantity) that should get bought/sold. price_col (str, optional): Name of the column containing the prices of the orders. Defaults to ‘price’. energy_col (str, optional): Name of the column containing the energy of the orders. Defaults to ‘quantity’. time_col (str, optional): Name of the column containing the transaction time of the orders. Defaults to ‘timestamp’.

Returns:

pd.DataFrame: all orders needed to fulfill the requested energy based on the passed orderbook

Parameters:
  • rows (DataFrame)

  • market_side (str)

  • max_energy (float)

  • price_col (str)

  • energy_col (str)

  • time_col (str)

Return type:

DataFrame

battery_optimizer_app.orderbook_bucketing.get_max_prices_per_bucket(rows, market_side, max_energy, bucket_size, price_col='price', energy_col='quantity', time_col='timestamp')#

The maximum price of a bucket is always the maximum/minimum price that is needed to fulfill the bucket plus the buckets before. Example: market_side = SELL, bucket_size = 1 MW, max_energy = 5 MW orderbook = {1.5 MW, 50 €/MWh}, {0.7 MW, 55 €/MWh}, {2 MW, 60 €/MWh}, {1.2 MW, 65 €/MWh} bucketed orderbook = {1 MW, 50 €/MWh}, {1 MW, 55 €/MWh}, {1 MW, 60 €/MWh}, {1 MW, 60 €/MWh}, {1 MW, 65 €/MWh}

Args:

rows (pd.DataFrame): The orders for one price side for one delivery period at a given trading timestamp. market_side (str): The market side as seen on a trading screen. ‘BUY’ or ‘SELL’ max_energy (float): The amount of energy (either volume or quantity) that should get bought/sold. bucket_size (float): The size the buckets should have in the same unit as max_energy. price_col (str, optional): Name of the column containing the prices of the orders. Defaults to ‘price’. energy_col (str, optional): Name of the column containing the energy of the orders. Defaults to ‘quantity’. time_col (str, optional): Name of the column containing the transaction time of the orders. Defaults to ‘timestamp’.

Returns:

pd.DataFrame: the size of the bucket and the corresponding maximal price in the bucket.

Parameters:
  • rows (DataFrame)

  • market_side (str)

  • max_energy (float)

  • bucket_size (float)

  • price_col (str)

  • energy_col (str)

  • time_col (str)

Return type:

DataFrame

battery_optimizer_app.orderbook_bucketing.get_orderbook_in_buckets(gzipped_orderbook, bucketing_approach, max_power_MW, bucket_size=None, delivery_length=None, delivery_start=None, delivery_end=None, groupby_prices=True, last_intraday_traded_timestamp=None, blocked_capacities=None, request_id=None)#

Returns price buckets considering the given parameters based on the passed orderbook in VATP format. The price sides for export is inverted to the market side as we have to take the viewpoint of the optimizer: buying implies costs, selling generates revenues.

Args:
gzipped_orderbook (bytes): the orderbook from the message. Base64 encoded and gzipped json.

VPP already sends the orderbook prefiltered for QuarterHour for DE and HalfHour for UK.

bucketing_approach (BucketingApproach): either the whole orderbook, the max price per bucket or the vwap per bucket. max_power_MW (float): The amount of energy (either volume or quantity) that should get bought/sold. bucket_size (float, optional): The size the buckets should have in the same unit as max_energy. Defaults to None. delivery_length (str, optional): The delivery length of the products that should be considered. Defaults to None. delivery_start (pd.Timestamp, optional): The delivery start of the prodcut to be considered. Defaults to None. groupby_prices (bool, optional): If buckets with the same price should be combined into one bucket. Defaults to True. last_intraday_traded_timestamp (pd.Timestamp, optional): The start timestamp of the last settlement period actually traded in the intraday market.

If set, the buckets after this timestamp will be filled with the max power of the asset.

blocked_capacities (Optional[List], optional): List of blocked capacities to consider when calculating the orderbook buckets. Defaults to None. request_id (str, optional): The request ID of the current request for logging purposes.

Returns:

dict: A dict of dicts of the format {delivery start timestamp, sell buckets as list of dicts, buy buckets as list of dicts}

Parameters:
Return type:

dict

battery_optimizer_app.orderbook_bucketing.get_vwap_per_bucket(rows, market_side, max_energy, bucket_size, price_col='price', energy_col='quantity', time_col='timestamp')#

The vwap of a bucket is the vwap of all prices that are needed to fulfill energy needed in the bucket. If an order is needed in two buckets, the order is split into two orders for which the energy is the sum of the original order and the price is the same. Example: market_side = SELL, bucket_size = 1 MW, max_energy = 5 MW orderbook = {1.5 MW, 50 €/MWh}, {0.7 MW, 55 €/MWh}, {2 MW, 60 €/MWh}, {1.2 MW, 65 €/MWh} bucketed orderbook = {1 MW, 50 €/MWh}, {1 MW, 52.5 €/MWh}, {1 MW, 59 €/MWh}, {1 MW, 60 €/MWh}, {1 MW, 64 €/MWh}

Args:

rows (pd.DataFrame): The orders for one price side for one delivery period at a given trading timestamp. market_side (str): The market side as seen on a trading screen. ‘BUY’ or ‘SELL’ max_energy (float): The amount of energy (either volume or quantity) that should get bought/sold. bucket_size (float): The size the buckets should have in the same unit as max_energy. price_col (str, optional): Name of the column containing the prices of the orders. Defaults to ‘price’. energy_col (str, optional): Name of the column containing the energy of the orders. Defaults to ‘quantity’. time_col (str, optional): Name of the column containing the transaction time of the orders. Defaults to ‘timestamp’.

Returns:

pd.DataFrame: the size of the bucket and the corresponding maximal price in the bucket.

Parameters:
  • rows (DataFrame)

  • market_side (str)

  • max_energy (float)

  • bucket_size (float)

  • price_col (str)

  • energy_col (str)

  • time_col (str)

Return type:

DataFrame

battery_optimizer_app.orderbook_bucketing.read_gzipped_orderbook(file_path)#

Read a gzipped orderbook from a file path

Args:

file_path (str): where the gzipped orderbook resides

Returns:

_type_: file object of the gzipped orderbook

Parameters:

file_path (str)