annular.satellite_model

Submodules

Attributes

strategies

Classes

MultiProfileBiddingStrategy

A 24-hour bidding strategy to bid using multiple profiles based on multiple scenarios.

ReadingBidsStrategy

Bidding strategy that reads bids from a CSV file.

SatelliteModel

Base class for satellite models.

Package Contents

class annular.satellite_model.MultiProfileBiddingStrategy(demands: pandas.DataFrame, base_forecast: pandas.DataFrame, carrier_prices: pandas.DataFrame, cronian_config: dict, tariff_folder: pathlib.Path | str | None = None, tariff_categories: dict[str, str | numbers.Real] | None = None, floor_price: int = 0, horizon_size: int = 48, cronian_storage_model: str = 'simple', forecast_scaling_factor: float = 1.5, **kwargs)[source]

Bases: annular.satellite_model.satellite_model.SatelliteModel

A 24-hour bidding strategy to bid using multiple profiles based on multiple scenarios.

See also

annular.tariffs.TariffManager

Parameters:
  • demands – Demand values per timestamp, with different flexibility as separate columns named ‘flex+N’.

  • base_forecast – Electricity price forecast based on which multiple forecast scenarios will be generated by adjusting with the forecast_scaling_factor.

  • carrier_prices – Price timeseries for any energy carrier other than electricity such as methane, hydrogen, etc.

  • cronian_config – Cronian configuration describing the prosumer’s demand and assets for building its optimization model.

  • tariff_folder – Path to the folder with tariff data; passed to a TariffManager.

  • tariff_categories – Dictionary that indicates the tariff category the satellite is subject to. Keys are categories, and values are the levels in that category.

  • floor_price – Minimum price to bid at, defaults to 0. Used as price for supply bids.

  • horizon_size – Full length of the horizon to use for an optimization iteration, i.e., bidding window + look ahead period, in number of snapshots.

  • forecast_scaling_factor – Factor to scale up/down the electricity price forecast from the base scenario to create multiple forecast scenarios.

  • cronian_storage_model – Type of storage model (simple or complex) to use in the optimization model if prosumer has storage assets.

  • kwargs – Any other keyword arguments are passed to the initialization of the base class.

base_forecast
demands
carrier_prices
cronian_config
floor_price = 0
horizon_size = 48
forecast_scaling_factor = 1.5
storage_model = 'simple'
cur_timestamp_idx = 0
manager
max_electricity_withdrawal_so_far = 0.0
classmethod from_data_files(demands_path: pathlib.Path | str, forecasts_path: pathlib.Path | str, carrier_prices_path: pathlib.Path | str, cronian_config_path: pathlib.Path | str, *args, **kwargs)[source]

Initialize a MultiProfileBiddingStrategy by loading data and configuration from files.

Parameters:
  • demands_path – Path to csv file with demand values per timestamp, with different flexibility as separate columns named ‘flex+N’.

  • forecasts_path – Path to csv file containing the electricity price forecast based on which multiple forecast scenarios will be generated by adjusting with the forecast_scaling_factor.

  • carrier_prices_path – Path to csv file containing price timeseries for any energy carrier other than electricity such as methane, hydrogen, etc.

  • cronian_config_path – Path to the Cronian configuration describing the prosumer’s demand and assets for building its optimization model.

  • *args – All further arguments are passed as-is to MultiProfileBiddingStrategy.__init__()

  • **kwargs – All further keyword arguments are passed as-is to MultiProfileBiddingStrategy.__init__()

property bidding_window: pandas.Index

Returns current bidding window as a pandas Index of timestamps.

determine_bids(select_scenarios: collections.abc.Container[int] | None = None) pandas.DataFrame[source]

Determine bids based on multiple forecast price scenarios.

Different forecast price scenarios are made as variation of the given electricity_price_forecast. An optimization is run based on each of these scenarios, to determine the corresponding demand profile.

The set of these profiles is submitted in a single exclusive group, all bid for at ceiling price.

Returns:

A collection of bids covering the current bidding window.

meet_demand(market_price: numpy.ndarray | None, demand_met: numpy.ndarray | None) None[source]

Process the amount of demand that was met.

Solve the cronian model again, now with the electric power fixed to the values given from the central market. Record dispatch of assets and update the state of charge for any storage assets.

Parameters:
  • market_price – Price of electricity as provided per timestep.

  • demand_met – Amount of demand that was met at the market price per timestep.

_update_internal_state(horizon: pandas.Index) None[source]

Store intermediate values to carry over to the next rolling horizon.

Specifically, these values are the energy levels of storage assets if any.

Parameters:

horizon – Current optimization horizon.

_get_horizon(length: int | None = None) pandas.Index[source]

Select the relevant horizon index values at the current timestamp index.

Parameters:

length – length of the desired horizon in number of timestamps. Uses self.horizon_size when None is given.

Returns:

Pandas Index object of the selected horizon values.

static make_forecast_scenarios(base_forecast: pandas.DataFrame, forecast_scaling_factor: float, select: collections.abc.Container[int] | None = None) dict[str, pandas.DataFrame][source]

Create different scenarios from a base forecast.

The different scenarios are created by either scaling the base forecast according to some profile, or by scaling a fixed profile according to a numerical property of the base forecast.

The following scenarios are created:
  • scale_up: base_forecast_values * forecast_scaling_factor

  • scale_down: base_forecast_values / forecast_scaling_factor

  • scale_up_increasing: base_forecast_values * linear_increase

  • scale_down_increasing: base_forecast_values * linear_decrease

  • peak_mid: base_forecast_values * peak_shape_scaling

  • valley_mid: base_forecast_values * valley_shape_scaling

  • day_period_boost: base_forecast_values * boost_day_period

  • morning_evening_boost: base_forecast_values * boost_morning_evening

  • base_min_day_period_boost: base_forecast_min * boost_day_period

  • base_min_morning_evening_boost: base_forecast_min * boost_morning_evening

  • base_max_day_period_boost: base_forecast_max * boost_day_period

  • base_max_morning_evening_boost: base_forecast_max * boost_morning_evening

Parameters:
  • base_forecast – Electricity price forecast used as a base for generating different scenarios of electricity price variations.

  • forecast_scaling_factor – Factor to scale the base forecast to create different scenarios.

  • select – optional collection of index integers for which scenarios to select from the provided collection.

Returns:

Electricity price forecast scenarios.

Raises:

ValueError – If the length of the forecast is not 24.

static plot_forecast_scenarios(forecast_scenarios: dict[str, pandas.DataFrame], output_path) None[source]

Plot the electricity price forecast scenarios.

Parameters:
  • forecast_scenarios – Dictionary of forecast scenarios.

  • output_path – Path where the plot will be saved.

determine_power_profile(scenario_forecast: pandas.DataFrame, no_supply_to_grid: bool = False) list[float][source]

Determine electricity consumption/generation profile based on a given scenario.

Parameters:
  • scenario_forecast – DataFrame containing forecasted electricity prices.

  • no_supply_to_grid – Boolean to enforce a demand-only connection to the grid.

Returns:

Optimized electricity power profile for the given forecast price.

_get_tariff_initialization() dict[str, dict][source]

Prepare initialization for tariff-related parameters and constraints.

Returns:

Nested dictionary with initialization information for Pyomo model with tariff-related parameters and constraints. Only contains the information for tariffs that are present in the TariffManager.

_make_bids(profiles: dict[str, list[float]]) pandas.DataFrame[source]

Create a bids table to submit given profiles as an exclusive group.

Actual bid entries are only made for timestamps with non-zero demand.

Parameters:

profiles – dictionary of lists of demand values for each timestamp.

Returns:

pd.DataFrame table of the constructed bids.

_create_model(horizon: pandas.Index) pyomo.environ.AbstractModel[source]

Create a model instance using cronian.

Parameters:

horizon – Timestamps spanning the optimization horizon currently of interest.

Returns:

Abstract model for this satellite in the current optimization horizon.

_add_cost_objective(model: pyomo.environ.AbstractModel) pyomo.environ.AbstractModel[source]

Create a cost minimization or revenue maximization objective.

Depending on the sign of the electric_power variable, the objective minimizes electricity consumption cost or maximizes revenues from electricity generated locally. It also minimizes the cost of consuming other externally priced energy carriers such as methane, biomass, etc.

Parameters:

model – Pyomo model to add the cost objective to.

Returns:

The given model object, now with cost_objective added.

_define_max_electricity_withdrawal(model: pyomo.environ.AbstractModel) pyomo.environ.AbstractModel[source]

Define maximum electricity withdrawal for modeling capacity tariffs.

This function defines the maximum electricity withdrawal in the current optimization horizon to which a capacity tariff charge is applied. Directly computing max withdrawal as max (withdrawals in current horizon, previous maximum withdrawal) will lead to a nonlinear optimization problem due to the max() operator. We linearize this by introducing a variable representing the maximum power withdrawal and enforcing the following constraints on it: (1) It must be greater than or equal to the instantaneous withdrawals in the current horizon. (2) It must be greater than or equal to the recorded maximum withdrawal from previous horizons.

Parameters:

model – Pyomo model to add the constraint to.

Returns:

The given model object, now with capacity_tariff_constraint added.

_add_contracted_capacity_limit_constraint(model: pyomo.environ.AbstractModel) pyomo.environ.AbstractModel[source]

Constrain max electricity withdrawal based on contracted transport limit.

NOTE: We assume that the unit of the contracted_transport_limit is MW.

Parameters:

model – Pyomo model to add the constraint to.

Returns:

The given model object, now with max_withdrawal_in_previous_constraint added.

class annular.satellite_model.ReadingBidsStrategy(bids: pandas.DataFrame, **kwargs)[source]

Bases: annular.satellite_model.satellite_model.SatelliteModel

Bidding strategy that reads bids from a CSV file.

This strategy loads bids from a CSV file once during initialization. When its determine_bids method is called, it identifies the next set of timestamps to provide bids for, shifting by rolling_horizon_step timestamps every iteration. It then reads bids for this set of timestamps from the loaded bids.

When it reaches the end of the data, it cycles back to the beginning and starts serving the same bids again, but with the timestamps adjusted forward by however many time increments have passed.

The data in the CSV does not need to span a perfect multiple of e.g. 24 hours. If the data ends at a shorter time (e.g., 11:00:00), the strategy will only serve the available bids and then reset to the beginning for the next cycle.

The strategy expects the CSV file to have the following columns:

exclusive_group_id

profile_block_id

timestamp

quantity

price

Parameters:
  • bids – Dataframe containing the bids.

  • rolling_horizon_step – How many snapshots to advance at every iteration, ie, for how many snapshots bids need to be made.

  • **kwargs – Additional keyword arguments, which are currently ignored.

bids
timestamps
LAST_TIMESTAMP
increment
num_cycles = 0
cycle_length
classmethod from_data_files(bids_csv_path: pathlib.Path | str, *args, **kwargs)[source]

Load from data files.

Parameters:
  • bids_csv_path – Path to the CSV file containing the bids.

  • *args – passed through to ReadingBidsStrategy.__init__().

  • **kwargs – passed through to ReadingBidsStrategy.__init__().

determine_bids() pandas.DataFrame[source]

Returns the bids from next timestamp.

meet_demand(market_price: numpy.ndarray | None, demand_met: numpy.ndarray | None) None[source]

No model for processing the demand_met, but forwards internal current timestep by 24 hours.

_get_horizon() pandas.Index[source]

Select the relevant horizon index values at the current timestep.

Returns:

Pandas Index object of the selected horizon values.

_reset_cycle() None[source]

Starting a new cycle.

adjust_timestamps(bids_table: pandas.DataFrame) pandas.DataFrame[source]

Adjusts the timestamps in the bids table based on the current cycle.

Parameters:

bids_table – DataFrame containing the bids with timestamps to adjust.

Returns:

DataFrame containing the bids with adjusted timestamps.

static read_multi_index_csv_with_utc_timestamps(bids_csv_path) pandas.DataFrame[source]

Reads a multi-index CSV file with UTC timestamps.

class annular.satellite_model.SatelliteModel(rolling_horizon_step: int, ceiling_price: float, start_hour: float, num_hours: int, output_path: str | None = None, **kwargs)[source]

Bases: abc.ABC

Base class for satellite models.

Create a satellite model that can bid for demand between floor and ceiling price.

Parameters:
  • rolling_horizon_step – How many snapshots to advance at every iteration, ie, for how many snapshots bids need to be made.

  • ceiling_price – Maximum price to bid at, at which demand will always be satisfied.

  • start_hour – The starting time of the simulation.

  • num_hours – The length of the simulation time horizon.

  • output_path – Path to the directory to store intermediate values such as bids and dispatch. If given, a target directory is created.

  • **kwargs – Any other keyword arguments are ignored.

static expand_config(configuration: dict) dict[str, dict][source]

Expand a potential meta-configuration to a collection of concrete configurations.

Basic case: no config ‘expansion’ is supported, so the configuration is returned in a list for datastructure consistency.

Parameters:

configuration – A configuration dictionary.

Returns:

The configuration wrapped in a dictionary with empty string as a key.

Return type:

configurations

classmethod from_yaml(config_file: pathlib.Path, **common_settings: dict) T[source]

Initialize a strategy from a yaml file.

Parameters:
  • config_file – Path to configuration file.

  • common_settings – A dictionary with additional keyword arguments. Arguments specified in config_file take precedence over arguments specified in common settings.

Any values given under keys ending in _path will be treated as relative to the given configuration file: they will be explicitly replaced with <config_file.parent>/<value>. As a result, absolute paths are not supported when initializing from a configuration file.

If the config file or the common settings include a key results_folder, a setting key output_path is created as concatenation of the value of results_folder and the name of the config file. The results_folder key is deleted from the settings.

classmethod from_data_files(*args, **kwargs) T[source]
Abstractmethod:

Instantiate a bidding strategy by loading data from files.

rolling_horizon_step
ceiling_price
start_hour
num_hours
output_path
abstractmethod meet_demand(market_price: numpy.ndarray | None, demand_met: numpy.ndarray | None) None[source]

Update internal state according to the amount of demand met and record market price.

abstractmethod determine_bids() pandas.DataFrame[source]

Determine the next set of bids based on the current internal state.

annular.satellite_model.strategies[source]