Added functions to compare policies

This commit is contained in:
Victor Mylle
2023-12-19 16:22:13 +00:00
parent fee948cc09
commit d0fa815b68
5 changed files with 715 additions and 88 deletions

File diff suppressed because one or more lines are too long

View File

@@ -57,7 +57,8 @@ class Battery:
self.charge_cycles = 0
class BaselinePolicy():
def __init__(self, battery: Battery):
def __init__(self, battery: Battery, data_path: str = ""):
self.data_path = data_path
self.battery = battery
self.train_data = self.load_imbalance_prices(train=True)
self.test_data = self.load_imbalance_prices(train=False)
@@ -67,7 +68,7 @@ class BaselinePolicy():
print(f"Test range: {self.test_data.iloc[0]['DateTime'].strftime('%d-%m-%Y')} - {self.test_data.iloc[-1]['DateTime'].strftime('%d-%m-%Y')}")
def load_imbalance_prices(self, train: bool = True):
imbalance_prices = pd.read_csv('data/imbalance_prices.csv', parse_dates=True, sep=";")
imbalance_prices = pd.read_csv(self.data_path + 'data/imbalance_prices.csv', parse_dates=True, sep=";")
imbalance_prices = imbalance_prices[['DateTime', 'Positive imbalance price']]
imbalance_prices['DateTime'] = pd.to_datetime(imbalance_prices['DateTime'], utc=True)
if train:
@@ -78,15 +79,15 @@ class BaselinePolicy():
imbalance_prices = imbalance_prices.sort_values(by=['DateTime'], ascending=True)
return imbalance_prices
def get_train_score(self, charge_treshold, discharge_treshold):
return self.get_score(self.train_data, charge_treshold, discharge_treshold)
def get_train_score(self, charge_threshold, discharge_threshold):
return self.get_score(self.train_data, charge_threshold, discharge_threshold)
def get_test_score(self, charge_treshold, discharge_treshold):
return self.get_score(self.test_data, charge_treshold, discharge_treshold)
def get_test_score(self, charge_threshold, discharge_threshold):
return self.get_score(self.test_data, charge_threshold, discharge_threshold)
# if price is below charging treshold (cheap charging) -> charge battery: total_profit -= charge * price
# if price is above treshold -> discharge battery: total_profit += discharge * price
def get_score(self, df, charge_treshold, discharge_treshold):
# if price is below charging threshold (cheap charging) -> charge battery: total_profit -= charge * price
# if price is above threshold -> discharge battery: total_profit += discharge * price
def get_score(self, df, charge_threshold, discharge_threshold):
self.battery.reset()
total_charging_cost = 0
total_discharging_profit = 0
@@ -96,41 +97,141 @@ class BaselinePolicy():
number_of_discharges = 0
for index, row in df.iterrows():
if row['Positive imbalance price'] < charge_treshold:
if row['Positive imbalance price'] < charge_threshold:
total_charging_cost += self.battery.charge() * row['Positive imbalance price']
mean_charging_price += row['Positive imbalance price']
number_of_charges += 1
elif row['Positive imbalance price'] > discharge_treshold:
elif row['Positive imbalance price'] > discharge_threshold:
total_discharging_profit += self.battery.discharge() * row['Positive imbalance price']
mean_discharging_price += row['Positive imbalance price']
number_of_discharges += 1
return total_charging_cost, total_discharging_profit, self.battery.charge_cycles, mean_charging_price / number_of_charges, mean_discharging_price / number_of_discharges
def treshold_scores(self, charge_tresholds, discharge_tresholds):
df = pd.DataFrame(columns=["Charge treshold", "Discharge treshold", "Charging Cost", "Discharging Profit", "Total Profit", "Charge cycles", "Mean charging price", "Mean discharging price"])
df_test = pd.DataFrame(columns=["Charge treshold", "Discharge treshold", "Charging Cost", "Discharging Profit", "Total Profit", "Charge cycles", "Mean charging price", "Mean discharging price"])
for charge_treshold, discharge_treshold in tqdm(itertools.product(charge_tresholds, discharge_tresholds)):
total_charging_cost, total_discharge_profit, charge_cycles, mean_charging_price, mean_discharging_price = self.get_train_score(charge_treshold, discharge_treshold)
df = pd.concat([df, pd.DataFrame([[charge_treshold, discharge_treshold, total_charging_cost, total_discharge_profit, total_discharge_profit - total_charging_cost, charge_cycles, mean_charging_price, mean_discharging_price]], columns=["Charge treshold", "Discharge treshold", "Charging Cost", "Discharging Profit", "Total Profit", "Charge cycles", "Mean charging price", "Mean discharging price"])])
def threshold_scores(self, charge_thresholds, discharge_thresholds):
df = pd.DataFrame(columns=["Charge threshold", "Discharge threshold", "Charging Cost", "Discharging Profit", "Total Profit", "Charge cycles", "Mean charging price", "Mean discharging price"])
df_test = pd.DataFrame(columns=["Charge threshold", "Discharge threshold", "Charging Cost", "Discharging Profit", "Total Profit", "Charge cycles", "Mean charging price", "Mean discharging price"])
total_charging_cost, total_discharge_profit, charge_cycles, mean_charging_price, mean_discharging_price = self.get_test_score(charge_treshold, discharge_treshold)
df_test = pd.concat([df_test, pd.DataFrame([[charge_treshold, discharge_treshold, total_charging_cost, total_discharge_profit, total_discharge_profit - total_charging_cost, charge_cycles, mean_charging_price, mean_discharging_price]], columns=["Charge treshold", "Discharge treshold", "Charging Cost", "Discharging Profit", "Total Profit", "Charge cycles", "Mean charging price", "Mean discharging price"])])
threshold_pairs = itertools.product(charge_thresholds, discharge_thresholds)
threshold_pairs = filter(lambda x: x[0] < x[1], threshold_pairs)
for charge_threshold, discharge_threshold in tqdm(threshold_pairs):
total_charging_cost, total_discharge_profit, charge_cycles, mean_charging_price, mean_discharging_price = self.get_train_score(charge_threshold, discharge_threshold)
df = pd.concat([df, pd.DataFrame([[charge_threshold, discharge_threshold, total_charging_cost, total_discharge_profit, total_discharge_profit - total_charging_cost, charge_cycles, mean_charging_price, mean_discharging_price]], columns=["Charge threshold", "Discharge threshold", "Charging Cost", "Discharging Profit", "Total Profit", "Charge cycles", "Mean charging price", "Mean discharging price"])])
total_charging_cost, total_discharge_profit, charge_cycles, mean_charging_price, mean_discharging_price = self.get_test_score(charge_threshold, discharge_threshold)
df_test = pd.concat([df_test, pd.DataFrame([[charge_threshold, discharge_threshold, total_charging_cost, total_discharge_profit, total_discharge_profit - total_charging_cost, charge_cycles, mean_charging_price, mean_discharging_price]], columns=["Charge threshold", "Discharge threshold", "Charging Cost", "Discharging Profit", "Total Profit", "Charge cycles", "Mean charging price", "Mean discharging price"])])
df = df.sort_values(by=['Total Profit'], ascending=False)
return df, df_test
def get_optimal_thresholds(self, imbalance_prices, charge_thresholds, discharge_thresholds, tqdm=True):
df = None
threshold_pairs = itertools.product(charge_thresholds, discharge_thresholds)
threshold_pairs = filter(lambda x: x[0] < x[1], threshold_pairs)
# disable tqdm if necessary
if tqdm:
threshold_pairs = tqdm(threshold_pairs)
for charge_threshold, discharge_threshold in threshold_pairs:
self.battery.reset()
total_charging_cost = 0
total_discharging_profit = 0
number_of_charges = 0
number_of_discharges = 0
mean_charging_price = 0
mean_discharging_price = 0
for index, price in enumerate(imbalance_prices):
if price < charge_threshold:
total_charging_cost += self.battery.charge() * price
mean_charging_price += price
number_of_charges += 1
elif price > discharge_threshold:
total_discharging_profit += self.battery.discharge() * price
mean_discharging_price += price
number_of_discharges += 1
if number_of_charges == 0:
mean_charging_price = 0
else:
mean_charging_price /= number_of_charges
if number_of_discharges == 0:
mean_discharging_price = 0
else:
mean_discharging_price /= number_of_discharges
new_df = pd.DataFrame([[charge_threshold, discharge_threshold, total_charging_cost, total_discharging_profit, total_discharging_profit - total_charging_cost, self.battery.charge_cycles, mean_charging_price, mean_discharging_price]], columns=["Charge threshold", "Discharge threshold", "Charging Cost", "Discharging Profit", "Total Profit", "Charge cycles", "Mean charging price", "Mean discharging price"])
if df is None:
df = new_df
else:
df = pd.concat([df, new_df])
df = df.sort_values(by=['Total Profit'], ascending=False)
return df
def simulate(self, imbalance_prices, charge_threshold, discharge_threshold):
self.battery.reset()
total_charging_cost = 0
total_discharging_profit = 0
number_of_charges = 0
number_of_discharges = 0
mean_charging_price = 0
mean_discharging_price = 0
# for each timestep also print what is happening
for i, price in enumerate(imbalance_prices):
if price < charge_threshold:
charge = self.battery.charge()
total_charging_cost += charge * price
mean_charging_price += price
number_of_charges += 1
# print(f"{i}: Charging battery with {charge}MWh at {price}€/MWh")
elif price > discharge_threshold:
discharge = self.battery.discharge()
total_discharging_profit += discharge * price
mean_discharging_price += price
number_of_discharges += 1
# print(f"{i}: Discharging battery with {discharge}MWh at {price}€/MWh")
if number_of_charges == 0:
mean_charging_price = 0
else:
mean_charging_price /= number_of_charges
if number_of_discharges == 0:
mean_discharging_price = 0
else:
mean_discharging_price /= number_of_discharges
# print(f"Total charging cost: {total_charging_cost}")
# print(f"Total discharging profit: {total_discharging_profit}")
# print(f"Total profit: {total_discharging_profit - total_charging_cost}")
# print(f"Charge cycles: {self.battery.charge_cycles}")
# print(f"Mean charging price: {mean_charging_price}")
# print(f"Mean discharging price: {mean_discharging_price}")
return total_discharging_profit - total_charging_cost, self.battery.charge_cycles
battery = Battery(2, 1)
policy = BaselinePolicy(battery)
# battery = Battery(2, 1)
# policy = BaselinePolicy(battery)
charge_tresholds = np.arange(-100, 250, 50)
discharge_tresholds = np.arange(-100, 250, 50)
df, df_test = policy.treshold_scores(charge_tresholds, discharge_tresholds)
print(df.to_markdown())
# charge_thresholds = np.arange(-100, 250, 25)
# discharge_thresholds = np.arange(-100, 250, 25)
print(df_test.to_markdown())
# df, df_test = policy.threshold_scores(charge_thresholds, discharge_thresholds)
# print(df.to_markdown())
# print(policy.get_test_score(150, 100))
# print(df_test.to_markdown())
# # print(policy.get_test_score(150, 100))