battery_optimizer.request#

Functions

Classes

Asset(*[, asset_id, price_buckets, ...])

AssetState(*, start, soe_target[, ...])

BaseModel()

BatteryAvailability(*, start, availability)

BatteryCommercials(*, start[, ...])

BatteryInitialConditions(*, initial_soe[, ...])

BatteryMarketed(*, start, ...)

BatteryParameters(*, min_soe, max_soe[, ...])

CapacityKWh(*, start, capacity_kwh)

CommercialObjective(*[, commercial_columns])

FeatureFlags(*[, return_pickled_optimizer])

Imbalance(*[, imbalance_cost_per_MWh, ...])

IntradayResultAggregation(*[, name, no_buckets])

IntradayStrategy(*, name, delivery_length[, ...])

MaxAbsoluteSoE(*, start, max_soe_kwh)

MaxChargingPowerKW(*, start, ...)

MaxDailyCycle(*, date, max_daily_cycle)

MaxDischargingPowerKW(*, start, ...)

MaxSoE(*, start, max_soe)

MinAbsoluteSoE(*, start, min_soe_kwh)

MinSoE(*, start, min_soe)

Objective(*[, name])

OptimizationHorizon(*, start, end)

PriceBucket(*, max_volume_MW, price_per_MWh)

PriceBuckets(*, intraday_sell, intraday_buy)

PriceForecast(*, start[, intraday, ...])

RampRates(*[, type, ...])

Request(*, request_id, country, user_id, ...)

SolverSettings(*[, gapRel])

StrategyOptimization(*, frequency_min, horizon)

UpperBoundRiskIncrement(*, sell, buy)

class battery_optimizer.request.Asset(*, asset_id='Unique ID of the asset', battery_parameters, battery_initial_conditions, battery_marketed, battery_availabilities, price_forecast, price_buckets=None, strategy_optimization, asset_states=[], skipped_validations={'ensure_battery_marketed_respects_battery_parameters'}, battery_commercials=Empty DataFrame Columns: [] Index: [])#

Bases: BaseModel, ABC

Parameters:
property all_markets: list#
asset_id: str | int#
asset_states: list[AssetState] | DataFrame | None#
battery_availabilities: list[BatteryAvailability] | DataFrame#
battery_commercials: list[BatteryCommercials] | DataFrame | None#
battery_initial_conditions: BatteryInitialConditions#
battery_marketed: list[BatteryMarketed] | DataFrame#
battery_parameters: BatteryParameters#
property constant_markets: list#
property day_ahead_products: list#
property energy_products: list#
ensure_asset_state_settlement_periods_are_sensible()#
classmethod ensure_asset_states_is_list(asset_states)#
ensure_battery_marketed_respects_battery_parameters()#
ensure_max_daily_cycles_in_optimization_horizon()#
ensure_sensible_asset_state_soe_target_kwh()#
ensure_sensible_initial_soe_kwh()#
property frequency_markets: list#
abstractmethod handle_country_specific_market_already_auctioned(market)#
Parameters:

market (str)

property initial_markets_requested: set#
property is_constant_markets: bool#
property markets_already_auctioned: DataFrame#
property markets_already_auctioned_as_dict: dict#
property markets_inactive: DataFrame#
property markets_requested: DataFrame#
property markets_requested_or_already_auctioned: DataFrame#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

property power_variables#
price_buckets: Dict[datetime, PriceBuckets] | None#
property price_buckets_max_price: float | None#

Return the highest price_per_MWh across all provided price buckets.

Iterates over all timestamps in price_buckets and considers both intraday sell and buy bucket lists. Returns None when:

  • price_buckets is None

  • price_buckets is an empty dict

  • No bucket prices found (defensive fallback)

# Rationale: Convenience accessor for downstream logic needing an # upper bound / sanity check on bucket prices without re-scanning # the nested structure each time.

price_forecast: list[PriceForecast] | DataFrame#
round_prices_to_2_decimal_places()#
skipped_validations: set[str]#
strategy_optimization: StrategyOptimization#
class battery_optimizer.request.AssetState(*, start, soe_target, soe_target_kwh=None, soe_target_best_effort=True)#

Bases: BaseModel

Parameters:
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

soe_target: float#
soe_target_best_effort: bool#
soe_target_kwh: float | None#
start: datetime#
class battery_optimizer.request.BaseModel#

Bases: BaseModel

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class battery_optimizer.request.BatteryAvailability(*, start, availability)#

Bases: BaseModel

Parameters:
availability: bool#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

start: datetime#
class battery_optimizer.request.BatteryCommercials(*, start, min_revenue_per_intraday_sell=0.01)#

Bases: BaseModel

Parameters:
min_revenue_per_intraday_sell: float#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

start: datetime#
class battery_optimizer.request.BatteryInitialConditions(*, initial_soe, initial_soe_kwh=None, perform_initial_soe_checks=False)#

Bases: BaseModel

Parameters:
initial_soe: float#
initial_soe_kwh: float | None#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

perform_initial_soe_checks: bool#
class battery_optimizer.request.BatteryMarketed(*, start, bought_intraday_kw, sold_intraday_kw)#

Bases: BaseModel

Parameters:
bought_intraday_kw: float#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

sold_intraday_kw: float#
start: datetime#
class battery_optimizer.request.BatteryParameters(*, min_soe, max_soe, min_soe_kwh=None, max_soe_kwh=None, charging_efficiency, discharging_efficiency, max_charging_power_kw, max_discharging_power_kw, capacity_kwh, capacity_nominal_kwh=None, max_daily_cycle, daily_cycle_limit_applies=True, daily_cycle_limit_penalty=False, grid_connection_export_kw, grid_connection_import_kw, ramp_rates=RampRates(type=<RampingLogicName.performance_related: 'performance_related'>, charging_perf_related_kw_per_second=None, discharging_perf_related_kw_per_second=None, charging_tech_limited_kw_per_second=None, discharging_tech_limited_kw_per_second=None))#

Bases: BaseModel

Parameters:
capacity_kwh: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0)])] | list[CapacityKWh] | Series#
capacity_nominal_kwh: float | None#
charging_efficiency: float#
daily_cycle_limit_applies: bool | None#
daily_cycle_limit_penalty: bool#
default_capacity_nominal_to_single_capacity()#
discharging_efficiency: float#
ensure_capacity_nominal_is_passed_when_capacity_passed_as_schedule()#
grid_connection_export_kw: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0)])]#
grid_connection_import_kw: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0)])]#
max_charging_power_kw: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0)])] | list[MaxChargingPowerKW] | Series#
max_daily_cycle: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0)])] | list[MaxDailyCycle] | Series#
max_discharging_power_kw: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0)])] | list[MaxDischargingPowerKW] | Series#
max_soe: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0), Le(le=1.0)])] | list[MaxSoE] | Series#
max_soe_kwh: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0)])] | list[MaxAbsoluteSoE] | Series | None#
min_soe: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0), Le(le=1.0)])] | list[MinSoE] | Series#
min_soe_kwh: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0)])] | list[MinAbsoluteSoE] | Series | None#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

ramp_rates: RampRates | None#
classmethod validate_max_charging_power_kw(value)#

Ensure max_charging_power_kw is either a float, a list of MaxChargingPowerKW, or a pd.Series. Convert lists to pd.Series for internal consistency.

classmethod validate_max_discharging_power_kw(value)#

Ensure max_discharging_power_kw is either a float, a list of MaxDischargingPowerKW, or a pd.Series. Convert lists to pd.Series for internal consistency.

class battery_optimizer.request.CapacityKWh(*, start, capacity_kwh)#

Bases: BaseModel

Parameters:
capacity_kwh: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0)])]#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

start: datetime#
class battery_optimizer.request.CommercialObjective(*, commercial_columns=['commodity_revenue', 'commodity_cost'])#

Bases: BaseModel

Parameters:

commercial_columns (list[str])

commercial_columns: list[str]#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class battery_optimizer.request.FeatureFlags(*, return_pickled_optimizer=False)#

Bases: BaseModel

Parameters:

return_pickled_optimizer (bool)

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

return_pickled_optimizer: bool#
class battery_optimizer.request.Imbalance(*, imbalance_cost_per_MWh=1000000.0, min_imbalance_cost_per_MWh=None, imbalance_cost_shaping=True)#

Bases: BaseModel

Parameters:
  • imbalance_cost_per_MWh (float)

  • min_imbalance_cost_per_MWh (float | None)

  • imbalance_cost_shaping (bool)

ensure_min_imbalance_cost_per_MWh()#
imbalance_cost_per_MWh: float#
imbalance_cost_shaping: bool#
min_imbalance_cost_per_MWh: float | None#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class battery_optimizer.request.IntradayResultAggregation(*, name=IntradayResultAggregationName.minmax, no_buckets=1)#

Bases: BaseModel

Parameters:
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: IntradayResultAggregationName#
no_buckets: int#
class battery_optimizer.request.IntradayStrategy(*, name, delivery_length, tradeable_time_window_minutes=None)#

Bases: BaseModel

Parameters:
delivery_length: IntradayDeliveryLength#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: IntradayStrategyName#
tradeable_time_window_minutes: int | str | Timedelta | None#
class battery_optimizer.request.MaxAbsoluteSoE(*, start, max_soe_kwh)#

Bases: BaseModel

Parameters:
max_soe_kwh: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0)])]#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

start: datetime#
class battery_optimizer.request.MaxChargingPowerKW(*, start, max_charging_power_kw)#

Bases: BaseModel

Parameters:
max_charging_power_kw: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0)])]#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

start: datetime#
class battery_optimizer.request.MaxDailyCycle(*, date, max_daily_cycle)#

Bases: BaseModel

Parameters:
date: date#
max_daily_cycle: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0)])]#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class battery_optimizer.request.MaxDischargingPowerKW(*, start, max_discharging_power_kw)#

Bases: BaseModel

Parameters:
max_discharging_power_kw: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0)])]#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

start: datetime#
class battery_optimizer.request.MaxSoE(*, start, max_soe)#

Bases: BaseModel

Parameters:
max_soe: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0), Le(le=1.0)])]#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

start: datetime#
class battery_optimizer.request.MinAbsoluteSoE(*, start, min_soe_kwh)#

Bases: BaseModel

Parameters:
min_soe_kwh: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0)])]#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

start: datetime#
class battery_optimizer.request.MinSoE(*, start, min_soe)#

Bases: BaseModel

Parameters:
min_soe: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=0.0), Le(le=1.0)])]#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

start: datetime#
class battery_optimizer.request.Objective(*, name=ObjectiveName.pnl)#

Bases: BaseModel

Parameters:

name (ObjectiveName)

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: ObjectiveName#
class battery_optimizer.request.OptimizationHorizon(*, start, end)#

Bases: BaseModel

Parameters:
end: datetime#
classmethod end_greater_than_start(end, values)#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

start: datetime#
class battery_optimizer.request.PriceBucket(*, max_volume_MW, price_per_MWh)#

Bases: BaseModel

Parameters:
max_volume_MW: float#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

price_per_MWh: float#
class battery_optimizer.request.PriceBuckets(*, intraday_sell, intraday_buy)#

Bases: BaseModel

Parameters:
intraday_buy: Annotated[list[PriceBucket], Len(min_length=1, max_length=None)]#
intraday_sell: Annotated[list[PriceBucket], Len(min_length=1, max_length=None)]#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class battery_optimizer.request.PriceForecast(*, start, intraday=None, intraday_sell=None, intraday_buy=None)#

Bases: BaseModel

Parameters:
intraday: float | None#
intraday_buy: float | None#
intraday_sell: float | None#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

start: datetime#
class battery_optimizer.request.RampRates(*, type=RampingLogicName.performance_related, charging_perf_related_kw_per_second=None, discharging_perf_related_kw_per_second=None, charging_tech_limited_kw_per_second=None, discharging_tech_limited_kw_per_second=None)#

Bases: BaseModel

Parameters:
  • type (Literal[RampingLogicName.performance_related])

  • charging_perf_related_kw_per_second (Annotated[float | None, Gt(gt=0.0)])

  • discharging_perf_related_kw_per_second (Annotated[float | None, Gt(gt=0.0)])

  • charging_tech_limited_kw_per_second (Annotated[float | None, Gt(gt=0.0)])

  • discharging_tech_limited_kw_per_second (Annotated[float | None, Gt(gt=0.0)])

charging_tech_limited_kw_per_second: float | None#
discharging_tech_limited_kw_per_second: float | None#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

type: Literal[RampingLogicName.performance_related]#
class battery_optimizer.request.Request(*, request_id, country, user_id, request_creation_time, elastic_filter=False, already_auctioned_as_constants=True, asset, verbose=False, epsilon=1e-06, commercial_objective=CommercialObjective(commercial_columns=['commodity_revenue', 'commodity_cost']), multiplier_buy_sell_exceed_limit=10.0, upper_bound_risk_increment=None, imbalance=Imbalance(imbalance_cost_per_MWh=1000000.0, min_imbalance_cost_per_MWh=100000.0, imbalance_cost_shaping=True), solve_optimization_problem_max_seconds=90.0, intraday_strategy, intraday_result_aggregation=IntradayResultAggregation(name=<IntradayResultAggregationName.minmax: 'minmax'>, no_buckets=1), objective=Objective(name=<ObjectiveName.pnl: 'pnl'>), solver_settings=SolverSettings(gapRel=0.01), do_input_for_intraday_bucketing_correct_bucket=True, elastic_soe_constraints=False, global_max_charging_power_kw=None, global_max_discharging_power_kw=None, feature_flags=FeatureFlags(return_pickled_optimizer=False))#

Bases: BaseModel, ABC

Parameters:
property all_markets#
already_auctioned_as_constants: bool#
asset: Asset#
asset_time_series_input_matches_asset_strategy_optimization()#
property asset_time_series_input_matches_asset_strategy_optimization_names: list#
property capacity_product_variables: list#
property capacity_products: list#
property charging_multiplier#
property charging_tech_limited_multiplier#
commercial_objective: CommercialObjective#
compute_global_max_power_kw()#
property conversion_factor_power_in_settlement_period_to_energy#
convert_MW_to_MWh(power_MW)#
static convert_MW_to_kW(power_MW)#
convert_MWh_to_MW(energy_MWh)#
convert_MWh_to_kW(energy_MWh)#
convert_MWh_to_kWh(energy_MWh)#
convert_kW_to_MWh(power_kw)#
convert_kW_to_kWh(power_kw)#
convert_kW_to_normalized_charge(power_kw)#
convert_kW_to_normalized_discharge(power_kw)#
convert_kWh_to_MWh(energy_kWh)#
convert_kWh_to_kW(energy_kWh)#
static convert_kw_to_MW(power_kw)#
convert_normalized_charge_to_kW(normalized_charge)#
convert_normalized_discharge_to_kW(normalized_discharge)#
country: Country#
property discharging_multiplier#
property discharging_tech_limited_multiplier#
do_input_for_intraday_bucketing_correct_bucket: bool#
elastic_filter: bool#
elastic_soe_constraints: bool#
property energy_markets#
ensure_asset_state_absolute_target_sensible()#
ensure_asset_strategy_optimization_markets_is_sensible_time_series()#
ensure_battery_not_marketed_in_capacity_markets_for_when_battery_unavailable()#
ensure_initial_market_commitments_respect_initial_soe()#
ensure_initial_soe_is_sensible()#
ensure_intraday_strategy_tradeable_time_window_is_sensible()#
ensure_ramp_rates_are_physically_feasible()#

Ensure provided ramp rates are physically feasible, i.e. we expect to be able to ramp for zero power to max charging / max discharging power limits within a single settlement period. Setting None values for performance related ramp rates to 1e9.

ensure_requested_markets_are_sensible()#
ensure_sensible_absolute_soe_limits()#
ensure_time_dependent_battery_parameters()#
epsilon: float#
feature_flags: FeatureFlags#
fill_in_sell_and_buy_columns_with_mean_column()#
get_efa_blocks(optimization_time_range)#

EFA stands for Electricity Forward Agreement. Dynamic containment in the UK operates in EFA blocks, which in UK time are defined as follows: 23:00-03:00, 03:00-07:00, 07:00-11:00, 11:00-15:00, 15:00-19:00, 19:00-23:00

get_ramp_rate_multiplier(multiplier_name)#
global_max_charging_power_kw: float | None#
global_max_discharging_power_kw: float | None#
imbalance: Imbalance#
abstractmethod initialize_optional_time_series_input()#
input_for_intraday_bucketing_correct()#
input_for_intraday_bucketing_correct_bucket()#
input_for_intraday_bucketing_correct_vwap()#
intraday_result_aggregation: IntradayResultAggregation#
intraday_strategy: IntradayStrategy#
is_timestamp_inside_intraday_tradable_window(timestamp)#
property last_intraday_traded_timestamp#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

multiplier_buy_sell_exceed_limit: float#
property no_minutes_per_settlement_period#
objective: Objective#
property optimization_days#
property optimization_time_range#
preprocess_battery_availability()#

Preprocess battery availability by scaling power limits with availability values. Sets max_charging_power_kw and max_discharging_power_kw to 0 when availability is 0.

request_creation_time: datetime#
request_id: str#
set_efa_block_sp_name(efa_name_to_hours, blocks)#
set_upper_bound_risk_increment()#

When global max charging power and global max discharging power are different, one needs to set the upper bound risk increment such that closing of opened positions is possible on the market. The default size is to allow for closing all opened positions within one settlement period.

solve_optimization_problem_max_seconds: float#
solver_settings: SolverSettings#
property time_dependent_battery_parameters#
upper_bound_risk_increment: float | dict | UpperBoundRiskIncrement | None#
user_id: str | int#
verbose: bool#
class battery_optimizer.request.SolverSettings(*, gapRel=0.01)#

Bases: BaseModel

Parameters:

gapRel (float)

gapRel: float#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class battery_optimizer.request.StrategyOptimization(*, frequency_min, horizon, markets={}, optimization_id=None)#

Bases: BaseModel

Parameters:
frequency_min: int | str | Timedelta#
horizon: OptimizationHorizon#
markets: set[str] | Dict[datetime, set[str]]#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

optimization_id: str | None#
class battery_optimizer.request.UpperBoundRiskIncrement(*, sell, buy)#

Bases: BaseModel

Parameters:
buy: float#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'ignore', 'frozen': False, 'json_encoders': {<class 'datetime.datetime'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timedeltas.Timedelta'>: <function BaseModel.<lambda>>, <class 'pandas._libs.tslibs.timestamps.Timestamp'>: <function BaseModel.<lambda>>, <class 'pandas.core.frame.DataFrame'>: <function BaseModel.<lambda>>, <class 'pandas.core.series.Series'>: <function BaseModel.<lambda>>}, 'validate_default': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

sell: float#
battery_optimizer.request.cast_datetime_records_to_dataframe(field_name, datetime_column)#
Parameters:
  • field_name (str)

  • datetime_column (str)

battery_optimizer.request.cast_integer_timedelta_to_pandas_timedelta(field_name, unit)#
Parameters:

field_name (str)

battery_optimizer.request.datetime_records_to_dataframe(records, datetime_column='datetime')#
battery_optimizer.request.is_fraction(fraction)#
Parameters:

fraction (float)

Return type:

float

battery_optimizer.request.records_as_dataframe(cls, records)#