Added trainer for Diffusion model

This commit is contained in:
Victor Mylle
2023-12-28 16:07:33 +00:00
parent d0fa815b68
commit 3264b5ac53
9 changed files with 3127 additions and 195 deletions

View File

@@ -48,17 +48,30 @@ class ImbalancePriceCalculator:
return datetime in self.bid_ladder.index
def get_imbalance_price(self, datetime, volume):
if volume < 0:
volume = -volume
bid_ladder = self.bid_ladder.loc[self.bid_ladder.index == datetime]["bid_ladder_dec"].values[0]
else:
bid_ladder = self.bid_ladder.loc[self.bid_ladder.index == datetime]["bid_ladder_inc"].values[0]
def get_imbalance_price_vectorized(self, datetimes, volumes):
# Convert inputs to numpy arrays
datetimes = np.array(datetimes)
for bid in bid_ladder:
if bid[0] > volume:
return bid[1]
return bid_ladder[-1][1]
# Fetch bid ladders for each datetime and determine if it's inc or dec based on original volume sign
bid_ladders = np.where(np.array(volumes) < 0,
self.bid_ladder.loc[datetimes, "bid_ladder_dec"].values,
self.bid_ladder.loc[datetimes, "bid_ladder_inc"].values)
volumes = np.abs(np.array(volumes)) # Make all volumes positive
# Vectorized operation to get prices from bid ladders
prices = []
for i, bid_ladder in enumerate(bid_ladders):
volume = volumes[i]
for bid in bid_ladder:
if bid[0] > volume:
prices.append(bid[1])
break
else:
prices.append(bid_ladder[-1][1]) # Append last price if no break occurred
return np.array(prices)
def plot(self, datetime):
@@ -88,58 +101,70 @@ class ImbalancePriceCalculator:
fig.show()
def get_imbalance_prices_2023_for_date(self, date, NRV_predictions):
imbalance_prices = []
for i in range(1, len(NRV_predictions)):
datetime = date + pd.Timedelta(hours=i-1)
datetime = pytz.utc.localize(datetime)
imbalance_prices.append(self.get_imbalance_price_2023(datetime, NRV_predictions[i-1], NRV_predictions[i]))
return [x[1] for x in imbalance_prices]
def get_imbalance_prices_2023_for_date_vectorized(self, date, NRV_predictions_matrix):
# Initialize an empty list for the 2D results
all_imbalance_prices = []
def get_imbalance_price_2023(self, datetime, NRV_PREV, NRV):
MIP = self.get_imbalance_price(datetime, abs(NRV))
MDP = self.get_imbalance_price(datetime, -abs(NRV))
# Iterate over each row in the NRV_predictions matrix
for NRV_predictions in NRV_predictions_matrix:
# Create a range of datetimes for the entire day
hours = pd.TimedeltaIndex(range(len(NRV_predictions) - 1), 'H')
datetimes = date + hours
datetimes = datetimes.tz_localize(pytz.utc)
return calculate_imbalance_price_2023(-NRV_PREV, -NRV, MIP, MDP)
# Apply the vectorized imbalance price function to each row
imbalance_prices = self.get_imbalance_price_2023(datetimes, NRV_predictions[:-1], NRV_predictions[1:])
# Extract the imbalance prices and add to the 2D list
all_imbalance_prices.append(imbalance_prices[1])
return all_imbalance_prices
def get_imbalance_price_2023(self, datetimes, NRV_PREVS, NRVS):
# create numpy arrays
datetimes = np.array(datetimes)
NRV_PREVS = np.array(NRV_PREVS)
NRVS = np.array(NRVS)
MIPS = self.get_imbalance_price_vectorized(datetimes, np.abs(NRVS))
MDPS = self.get_imbalance_price_vectorized(datetimes, -np.abs(NRVS))
return calculate_imbalance_price(-NRV_PREVS, -NRVS, MIPS, MDPS)
def calculate_imbalance_price(SI_PREV, SI, MIP, MDP):
# Convert parameters to numpy arrays for vectorized operations
SI_PREV = np.array(SI_PREV)
SI = np.array(SI)
MIP = np.array(MIP)
MDP = np.array(MDP)
# parameters a, b, c, d
a = 0 # EUR/MWh
b = 200 # EUR/MWh
c = 450 # MW
d = 65 # MW
# SI = -NRV
def calculate_imbalance_price_2023(SI_PREV: float, SI: float, MIP: float, MDP: float):
# parameters a, b, c, d, x
a = 0 # EUR/MWh
b = 200 # EUR/MWh
c = 450 # MW
d = 65 # MW
# x = average abs(SI) and abs(SI_PREV)
x = (abs(SI_PREV) + abs(SI)) / 2
x = (np.abs(SI_PREV) + np.abs(SI)) / 2
cp = 0
if SI <= 0:
if MIP > 200 and MIP <= 400:
cp = (400-MIP)/200
else:
cp = 1
else:
if MDP >= 0:
cp = 1
elif MDP >= -200 and MDP < 0:
cp = (MDP+200)/200
# Calculate cp
cp = np.zeros_like(SI)
cp[(SI <= 0) & ((MIP > 200) & (MIP <= 400))] = (400 - MIP[(SI <= 0) & ((MIP > 200) & (MIP <= 400))]) / 200
cp[(SI <= 0) & ~((MIP > 200) & (MIP <= 400))] = 1
cp[(SI > 0) & (MDP >= 0)] = 1
cp[(SI > 0) & (MDP >= -200) & (MDP < 0)] = (MDP[(SI > 0) & (MDP >= -200) & (MDP < 0)] + 200) / 200
# Calculate alpha
alpha = np.zeros_like(SI)
alpha[np.abs(SI) > 150] = (a + b / (1 + np.exp((c - x[np.abs(SI) > 150]) / d))) * cp[np.abs(SI) > 150]
alpha = 0
if abs(SI) > 150:
alpha = (a + b/(1+np.exp((c-x)/d))) * cp
# Calculate imbalance prices
pos_imbalance_price = MIP + alpha
neg_imbalance_price = MDP - alpha
# imbalance_price based on SI
imbalance_price = 0
if SI < 0:
imbalance_price = pos_imbalance_price
elif SI > 0:
imbalance_price = neg_imbalance_price
else:
imbalance_price = (pos_imbalance_price + neg_imbalance_price) / 2
imbalance_price = np.zeros_like(SI)
imbalance_price[SI < 0] = pos_imbalance_price[SI < 0]
imbalance_price[SI > 0] = neg_imbalance_price[SI > 0]
imbalance_price[SI == 0] = (pos_imbalance_price[SI == 0] + neg_imbalance_price[SI == 0]) / 2
# return alpha, imbalance price
return alpha, imbalance_price