From f762d7d16d2ca717d8fb75c32a1b63f16bb61d54 Mon Sep 17 00:00:00 2001 From: Nick Harder Date: Mon, 16 Dec 2024 13:40:00 +0100 Subject: [PATCH] adjust storage strategy fix tests --- assume/strategies/learning_advanced_orders.py | 15 +--- assume/strategies/learning_strategies.py | 82 ++++--------------- tests/test_drl_storage_strategy.py | 3 + 3 files changed, 24 insertions(+), 76 deletions(-) diff --git a/assume/strategies/learning_advanced_orders.py b/assume/strategies/learning_advanced_orders.py index f5d86f33..385c019c 100644 --- a/assume/strategies/learning_advanced_orders.py +++ b/assume/strategies/learning_advanced_orders.py @@ -9,7 +9,7 @@ from assume.common.base import SupportsMinMax from assume.common.market_objects import MarketConfig, Orderbook, Product -from assume.common.utils import get_products_index, min_max_scale +from assume.common.utils import get_products_index from assume.strategies.learning_strategies import RLStrategy @@ -306,19 +306,10 @@ def create_observation( # scale unit outputs # if unit is not running, total dispatch is 0 - scaled_total_dispatch = min_max_scale( - current_volume, - 0, - unit.max_power, - ) + scaled_total_dispatch = current_volume / unit.max_power # marginal cost - # Could theoretically be negative (eg. subsidies), but assumed to be always positive in the simulation - scaled_marginal_cost = min_max_scale( - current_costs, - 0, - self.max_bid_price, - ) + scaled_marginal_cost = current_costs / self.max_bid_price # calculate the time the unit has to continue to run or be down op_time = unit.get_operation_time(start) diff --git a/assume/strategies/learning_strategies.py b/assume/strategies/learning_strategies.py index 2429c240..93635187 100644 --- a/assume/strategies/learning_strategies.py +++ b/assume/strategies/learning_strategies.py @@ -458,18 +458,10 @@ def create_observation( # scale unit outputs # if unit is not running, total dispatch is 0 - scaled_total_dispatch = min_max_scale( - current_volume, - 0, - unit.max_power, - ) + scaled_total_dispatch = current_volume / unit.max_power + # marginal cost - # Could theoretically be negative (eg. subsidies), but assumed to be always positive in the simulation - scaled_marginal_cost = min_max_scale( - current_costs, - 0, - self.max_bid_price, - ) + scaled_marginal_cost = current_costs / self.max_bid_price # concat all obsverations into one array observation = np.concatenate( @@ -1012,83 +1004,45 @@ def create_observation( # ============================================================================= # 1.1 Get the Observations, which are the basis of the action decision # ============================================================================= - # defines bounds of observation space - # stays here as it is unit specific, and different forecasts might apply for different units - # different handling would require an extra unit loop at learning role intiliazation and unit specific max/min values - # further forecasts might change during the simulation if advanced forecasting is used - self.max_market_price = max(unit.forecaster[f"price_{market_id}"]) - self.min_market_price = min(unit.forecaster[f"price_{market_id}"]) - self.max_residual = max(unit.forecaster[f"residualy_load_{market_id}"]) - self.min_residual = min(unit.forecaster[f"residual_load_{market_id}"]) - - upper_scaling_factor_res_load = self.max_residual - lower_scaling_factor_res_load = self.min_residual - upper_scaling_factor_price = self.max_market_price - lower_scaling_factor_price = self.min_market_price - - upper_scaling_factor_energy_cost = self.max_bid_price - lower_scaling_factor_energy_cost = 0 # checks if we are at end of simulation horizon, since we need to change the forecast then # for residual load and price forecast and scale them - if ( - end_excl + forecast_len - > unit.forecaster[f"residual_load_{market_id}"].index[-1] - ): - scaled_res_load_forecast = min_max_scale( - unit.forecaster[f"residual_load_{market_id}"].loc[start:], - lower_scaling_factor_res_load, - upper_scaling_factor_res_load, - ) + if end_excl + forecast_len > self.scaled_res_load_obs.index[-1]: + scaled_res_load_forecast = self.scaled_res_load_obs.loc[start:] + scaled_res_load_forecast = np.concatenate( [ scaled_res_load_forecast, - unit.forecaster[f"residual_load_{market_id}"].iloc[ + self.scaled_res_load_obs.iloc[ : self.foresight - len(scaled_res_load_forecast) ], ] ) else: - scaled_res_load_forecast = min_max_scale( - unit.forecaster[f"residual_load_{market_id}"].loc[ - start : end_excl + forecast_len - ], - lower_scaling_factor_res_load, - upper_scaling_factor_res_load, - ) + scaled_res_load_forecast = self.scaled_res_load_obs.loc[ + start : end_excl + forecast_len + ] - if end_excl + forecast_len > unit.forecaster[f"price_{market_id}"].index[-1]: - scaled_price_forecast = min_max_scale( - unit.forecaster[f"price_{market_id}"].loc[start:], - lower_scaling_factor_price, - upper_scaling_factor_price, - ) + if end_excl + forecast_len > self.scaled_pices_obs.index[-1]: + scaled_price_forecast = self.scaled_pices_obs.loc[start:] scaled_price_forecast = np.concatenate( [ scaled_price_forecast, - unit.forecaster[f"price_{market_id}"].iloc[ + self.scaled_pices_obs.iloc[ : self.foresight - len(scaled_price_forecast) ], ] ) else: - scaled_price_forecast = min_max_scale( - unit.forecaster[f"price_{market_id}"].loc[ - start : end_excl + forecast_len - ], - lower_scaling_factor_price, - upper_scaling_factor_price, - ) + scaled_price_forecast = self.scaled_pices_obs.loc[ + start : end_excl + forecast_len + ] # get the current soc value - soc_scaled = min_max_scale(unit.outputs["soc"].at[start], 0, unit.max_soc) - energy_cost_scaled = min_max_scale( - unit.outputs["energy_cost"].at[start], - lower_scaling_factor_energy_cost, - upper_scaling_factor_energy_cost, - ) + soc_scaled = unit.outputs["soc"].at[start] / unit.max_soc + energy_cost_scaled = unit.outputs["energy_cost"].at[start] / self.max_bid_price # concat all obsverations into one array observation = np.concatenate( diff --git a/tests/test_drl_storage_strategy.py b/tests/test_drl_storage_strategy.py index 53583fbb..c97637a3 100644 --- a/tests/test_drl_storage_strategy.py +++ b/tests/test_drl_storage_strategy.py @@ -86,6 +86,7 @@ def test_storage_rl_strategy_sell_bid(mock_market_config, storage_unit): # get the strategy strategy = storage_unit.bidding_strategies["EOM"] + strategy.prepare_observations(storage_unit, mc.market_id) # Define the 'sell' action: [0.2, 0.5] -> price=20, direction='sell' sell_action = [0.2, 0.5] @@ -181,6 +182,7 @@ def test_storage_rl_strategy_buy_bid(mock_market_config, storage_unit): # Instantiate the StorageRLStrategy strategy = storage_unit.bidding_strategies["EOM"] + strategy.prepare_observations(storage_unit, mc.market_id) # Define the 'buy' action: [0.3, -0.5] -> price=30, direction='buy' buy_action = [0.3, -0.5] @@ -274,6 +276,7 @@ def test_storage_rl_strategy_ignore_bid(mock_market_config, storage_unit): # Instantiate the StorageRLStrategy strategy = storage_unit.bidding_strategies["EOM"] + strategy.prepare_observations(storage_unit, mc.market_id) # Define the 'ignore' action: [0.0, 0.0] -> price=0, direction='ignore' ignore_action = [0.0, 0.0]