Added trainer for Diffusion model
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user