Implemented imbalance price reconstruction
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -1,71 +1,100 @@
|
||||
from datetime import datetime
|
||||
import plotly.graph_objects as go
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
incremental_bids = "../../data/incremental_bids.csv"
|
||||
decremental_bids = "../../data/decremental_bids.csv"
|
||||
|
||||
class ImbalancePriceCalculator:
|
||||
def __init__(self, bids) -> None:
|
||||
self.bids = bids
|
||||
self.bid_ladder = self.generate_bid_ladder()
|
||||
def __init__(self, method: int = 1) -> None:
|
||||
self.method = method
|
||||
self.load_bids()
|
||||
|
||||
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 load_bids(self):
|
||||
df = pd.read_csv(incremental_bids, sep=";")
|
||||
df["Datetime"] = pd.to_datetime(df["Datetime"], utc=True)
|
||||
|
||||
def get_imbalance_price(self, volume):
|
||||
for bid in self.bid_ladder:
|
||||
# sort by Datetime, Activation Order, Bid Price
|
||||
df = df.sort_values(by=["Datetime", "Activation Order", "Bid Price"])
|
||||
|
||||
# next we need to calculate the cummulative bids for every datetime
|
||||
incremental_cum_df = df.groupby(["Datetime"]).apply(self.generate_bid_ladder)
|
||||
|
||||
df = pd.read_csv(decremental_bids, sep=";")
|
||||
df["Datetime"] = pd.to_datetime(df["Datetime"], utc=True)
|
||||
decremental_cum_df = df.groupby(["Datetime"]).apply(self.generate_bid_ladder, incremental=False)
|
||||
|
||||
# merge the two dataframes on the Datetime
|
||||
self.bid_ladder = pd.merge(incremental_cum_df, decremental_cum_df, on="Datetime", how="inner", suffixes=("_inc", "_dec"))
|
||||
self.bid_ladder = self.bid_ladder.sort_values(by=["Datetime"])
|
||||
|
||||
def generate_bid_ladder(self, bids, incremental: bool = True):
|
||||
if self.method == 1:
|
||||
bids_df = bids.sort_values(by=["Bid Price"], ascending=[incremental])
|
||||
elif self.method == 2:
|
||||
bids_df = bids.sort_values(by=["Activation Order", "Bid Price"], ascending=[True, incremental])
|
||||
bids_df['cumulative_volume'] = bids_df['Bid Volume'].cumsum()
|
||||
if incremental:
|
||||
bids_df['max_price'] = bids_df['Bid Price'].cummax()
|
||||
else:
|
||||
bids_df['max_price'] = bids_df['Bid Price'].cummin()
|
||||
bid_ladder = list(zip(bids_df['cumulative_volume'], bids_df['max_price']))
|
||||
bid_ladder_df = pd.DataFrame([[bid_ladder]], columns=['bid_ladder'])
|
||||
|
||||
return bid_ladder_df
|
||||
|
||||
def check_datetime(self, datetime):
|
||||
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]
|
||||
|
||||
for bid in bid_ladder:
|
||||
if bid[0] > volume:
|
||||
return bid[1]
|
||||
return self.bid_ladder[-1][1]
|
||||
|
||||
def plot(self):
|
||||
return bid_ladder[-1][1]
|
||||
|
||||
|
||||
def plot(self, datetime):
|
||||
row = self.bid_ladder.loc[self.bid_ladder.index == datetime]
|
||||
dec_bids = row["bid_ladder_dec"].values[0]
|
||||
inc_bids = row["bid_ladder_inc"].values[0]
|
||||
|
||||
|
||||
|
||||
# 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)]
|
||||
x_inc_interpolated = [vol for i in range(len(inc_bids) - 1) for vol in [inc_bids[i][0], inc_bids[i+1][0]]]
|
||||
y_inc_interpolated = [price for cum_vol, price in inc_bids for _ in (0, 1)]
|
||||
|
||||
x_dec_interpolated = [-vol for i in range(len(dec_bids) - 1) for vol in [dec_bids[i][0], dec_bids[i+1][0]]]
|
||||
y_dec_interpolated = [price for cum_vol, price in dec_bids 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.add_trace(go.Scatter(x=x_inc_interpolated, y=y_inc_interpolated, mode='lines+markers', name="inc"))
|
||||
|
||||
|
||||
fig.add_trace(go.Scatter(x=x_dec_interpolated, y=y_dec_interpolated, mode='lines+markers', name="dec"))
|
||||
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
|
||||
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))
|
||||
|
||||
return calculate_imbalance_price_2023(-NRV_PREV, -NRV, MIP, MDP)
|
||||
|
||||
# SI = -NRV
|
||||
def calculate_imbalance_price_2023(SI_PREV: float, SI: float, MIP: float, MDP: float):
|
||||
@@ -107,8 +136,4 @@ def calculate_imbalance_price_2023(SI_PREV: float, SI: float, MIP: float, MDP: f
|
||||
imbalance_price = (pos_imbalance_price + neg_imbalance_price) / 2
|
||||
|
||||
# return alpha, imbalance price
|
||||
return alpha, imbalance_price
|
||||
|
||||
|
||||
|
||||
|
||||
return alpha, imbalance_price
|
||||
Reference in New Issue
Block a user