Fixed losses and multiple other things
This commit is contained in:
114
src/utils/imbalance_price_calculator.py
Normal file
114
src/utils/imbalance_price_calculator.py
Normal file
@@ -0,0 +1,114 @@
|
||||
from datetime import datetime
|
||||
import plotly.graph_objects as go
|
||||
import numpy as np
|
||||
|
||||
|
||||
class ImbalancePriceCalculator:
|
||||
def __init__(self, bids) -> None:
|
||||
self.bids = bids
|
||||
self.bid_ladder = self.generate_bid_ladder()
|
||||
|
||||
def generate_bid_ladder(self):
|
||||
# Sort bids by Product (3th column of tuple, use order defined above) and then by price (second column of tuple)
|
||||
# first sort on activaation order, then on bid price
|
||||
bids = sorted(self.bids, key=lambda x: (x[3], x[1]))
|
||||
|
||||
# Calculate cummulative bids
|
||||
cummulative_volume = 0
|
||||
cummulative_bids = []
|
||||
max_price = 0
|
||||
for volume, price, _, order in bids:
|
||||
cummulative_volume += volume
|
||||
if price > max_price:
|
||||
max_price = price
|
||||
cummulative_bids.append((cummulative_volume, max_price, price, order))
|
||||
print((cummulative_volume, max_price, price, order))
|
||||
|
||||
cummulative_bids = [(vol, price) for vol, price, _, _ in cummulative_bids]
|
||||
|
||||
return cummulative_bids
|
||||
|
||||
def get_imbalance_price(self, volume):
|
||||
for bid in self.bid_ladder:
|
||||
if bid[0] > volume:
|
||||
return bid[1]
|
||||
return self.bid_ladder[-1][1]
|
||||
|
||||
def plot(self):
|
||||
# Prepare data for plot
|
||||
x_interpolated = [vol for i in range(len(self.bid_ladder) - 1) for vol in [self.bid_ladder[i][0], self.bid_ladder[i+1][0]]]
|
||||
y_interpolated = [price for cum_vol, price in self.bid_ladder for _ in (0, 1)]
|
||||
|
||||
# Create and show the plot make sure hovering works in between the steps
|
||||
fig = go.Figure()
|
||||
fig.add_trace(go.Scatter(x=x_interpolated, y=y_interpolated, mode='lines+markers'))
|
||||
fig.update_layout(
|
||||
title='Bid ladder',
|
||||
xaxis_title='Volume',
|
||||
yaxis_title='Price',
|
||||
hovermode='x unified'
|
||||
)
|
||||
fig.show()
|
||||
|
||||
# also print the prices needed for 100MW, 200MW, 300MW, 400MW, 500MW, 600MW, 700MW, 800MW, 900MW, 1000MW
|
||||
for i in range(1, 11):
|
||||
# get first cummulative_bid i where i*100 > cummulative_volume of i and smaller than i+1
|
||||
|
||||
mw = 100
|
||||
|
||||
for bid in self.bid_ladder:
|
||||
if bid[0] > mw*i:
|
||||
print(f"{mw*i}MW: {bid[1]}")
|
||||
break
|
||||
|
||||
print(f"Max: {self.bid_ladder[-1][1]}")
|
||||
|
||||
def get_imbalance_price_2023(self, NRV_PREV, NRV):
|
||||
pass
|
||||
|
||||
|
||||
# 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
|
||||
|
||||
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
|
||||
|
||||
|
||||
alpha = 0
|
||||
if abs(SI) > 150:
|
||||
alpha = (a + b/(1+np.exp((c-x)/d))) * cp
|
||||
|
||||
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
|
||||
|
||||
# return alpha, imbalance price
|
||||
return alpha, imbalance_price
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user