You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
227 lines
5.6 KiB
Python
227 lines
5.6 KiB
Python
import numpy as np
|
|
import pandas as pd
|
|
import warnings
|
|
from tqdm.notebook import tqdm
|
|
|
|
from .prices import get_tennet_data, get_balansdelta_nl
|
|
from .forecasts import Forecast
|
|
|
|
# TODO: This whole thing needs serious refactoring /MK
|
|
|
|
|
|
def generate_intelligent_baseline(startdate, enddate):
|
|
bd = get_balansdelta_nl(start=startdate, end=enddate)
|
|
bd.drop(
|
|
columns=[
|
|
"datum",
|
|
"volgnr",
|
|
"tijd",
|
|
"IGCCBijdrage_op",
|
|
"IGCCBijdrage_af",
|
|
"opregelen_reserve",
|
|
"afregelen_reserve",
|
|
],
|
|
inplace=True,
|
|
)
|
|
net_regelvolume = bd["opregelen"] - bd["Afregelen"]
|
|
bd.insert(2, "net_regelvolume", net_regelvolume)
|
|
vol_delta = bd["net_regelvolume"].diff(periods=1)
|
|
bd.insert(3, "vol_delta", vol_delta)
|
|
|
|
pc = get_tennet_data(
|
|
exporttype="verrekenprijzen", start=startdate, end=enddate
|
|
).reindex(index=bd.index, method="ffill")[["prikkelcomponent"]]
|
|
|
|
if len(pc) == 0:
|
|
pc = pd.Series(0, index=bd.index)
|
|
|
|
prices = Forecast("marketprices_nl.csv", start=startdate, end=enddate)
|
|
prices.reindex_to_freq("1T")
|
|
prices = prices.data
|
|
|
|
inputdata = pd.concat([prices, bd, pc], axis=1)
|
|
|
|
Qhs = len(inputdata) / 15
|
|
|
|
if Qhs % 1 > 0:
|
|
raise Exception(
|
|
"A dataset with incomplete quarter-hours was passed in, please insert new dataset!"
|
|
)
|
|
|
|
data = np.array([inputdata[col].to_numpy() for col in inputdata.columns])
|
|
|
|
lstoutput = []
|
|
|
|
for q in tqdm(range(int(Qhs))):
|
|
q_data = [col[q * 15 : (q + 1) * 15] for col in data]
|
|
q_output = apply_imbalance_logic_for_quarter_hour(q_data)
|
|
|
|
if lstoutput:
|
|
for (ix, col) in enumerate(lstoutput):
|
|
lstoutput[ix] += q_output[ix]
|
|
else:
|
|
lstoutput = q_output
|
|
|
|
ib = pd.DataFrame(
|
|
lstoutput,
|
|
index=[
|
|
"DAM",
|
|
"POS",
|
|
"NEG",
|
|
"regulation state",
|
|
"ib_inv",
|
|
"ib_afn",
|
|
"ib_rt",
|
|
"nv_op",
|
|
"nv_af",
|
|
"opgeregeld",
|
|
"afgeregeld",
|
|
],
|
|
).T
|
|
|
|
ib.index = inputdata.index
|
|
return ib
|
|
|
|
|
|
def apply_imbalance_logic_for_quarter_hour(q_data):
|
|
[nv_op, nv_af, opgeregeld, afgeregeld] = [False] * 4
|
|
|
|
lst_inv = [np.NaN] * 15
|
|
lst_afn = [np.NaN] * 15
|
|
lst_rt = [np.NaN] * 15
|
|
|
|
lst_nv_op = [np.NaN] * 15
|
|
lst_nv_af = [np.NaN] * 15
|
|
lst_afr = [np.NaN] * 15
|
|
lst_opr = [np.NaN] * 15
|
|
|
|
mins = iter(range(15))
|
|
|
|
for m in mins:
|
|
[
|
|
DAM,
|
|
POS,
|
|
NEG,
|
|
rt,
|
|
vol_op,
|
|
vol_af,
|
|
net_vol,
|
|
delta_vol,
|
|
nood_op,
|
|
nood_af,
|
|
prijs_hoog,
|
|
prijs_mid,
|
|
prijs_laag,
|
|
prikkelc,
|
|
] = [col[0 : m + 1] for col in q_data]
|
|
|
|
delta_vol[0] = 0
|
|
|
|
if nood_op.sum() > 0:
|
|
nv_op = True
|
|
|
|
if nood_af.sum() > 0:
|
|
nv_af = True
|
|
|
|
if pd.notna(prijs_hoog).any() > 0:
|
|
opgeregeld = True
|
|
|
|
if pd.notna(prijs_laag).any() > 0:
|
|
afgeregeld = True
|
|
|
|
if (opgeregeld == True) and (afgeregeld == False):
|
|
regeltoestand = 1
|
|
|
|
elif (opgeregeld == False) and (afgeregeld == True):
|
|
regeltoestand = -1
|
|
|
|
elif (opgeregeld == False) and (afgeregeld == False):
|
|
if nv_op == True:
|
|
regeltoestand = 1
|
|
if nv_af == True:
|
|
regeltoestand = -1
|
|
else:
|
|
regeltoestand = 0
|
|
|
|
else:
|
|
# Zowel opregeld als afregeld > kijk naar trend
|
|
# Continue niet-dalend: RT1
|
|
# Continue dalend: RT -1
|
|
# Geen continue trend: RT 2
|
|
|
|
if all(i >= 0 for i in delta_vol):
|
|
regeltoestand = 1
|
|
elif all(i <= 0 for i in delta_vol):
|
|
regeltoestand = -1
|
|
else:
|
|
regeltoestand = 2
|
|
|
|
# Bepaal de verwachte onbalansprijzen
|
|
dam = DAM[0]
|
|
pc = prikkelc[0]
|
|
|
|
with warnings.catch_warnings():
|
|
warnings.simplefilter("ignore")
|
|
|
|
hoogste_prijs = np.nanmax(prijs_hoog)
|
|
mid_prijs = prijs_mid[-1]
|
|
laagste_prijs = np.nanmin(prijs_laag)
|
|
|
|
if regeltoestand == 0:
|
|
prijs_inv = mid_prijs
|
|
prijs_afn = mid_prijs
|
|
|
|
elif regeltoestand == -1:
|
|
if nv_af:
|
|
prijs_afn = np.nanmin((dam - 200, laagste_prijs))
|
|
|
|
else:
|
|
prijs_afn = laagste_prijs
|
|
|
|
prijs_inv = prijs_afn
|
|
|
|
elif regeltoestand == 1:
|
|
if nv_op:
|
|
prijs_inv = np.nanmax((dam + 200, hoogste_prijs))
|
|
|
|
else:
|
|
prijs_inv = hoogste_prijs
|
|
|
|
prijs_afn = prijs_inv
|
|
|
|
elif regeltoestand == 2:
|
|
if nv_op:
|
|
prijs_afn = np.nanmax((dam + 200, hoogste_prijs, mid_prijs))
|
|
else:
|
|
prijs_afn = np.nanmax((mid_prijs, hoogste_prijs))
|
|
|
|
if nv_af:
|
|
prijs_inv = np.nanmin((dam - 200, laagste_prijs, mid_prijs))
|
|
else:
|
|
prijs_inv = np.nanmin((mid_prijs, laagste_prijs))
|
|
|
|
prijs_inv -= pc
|
|
prijs_afn += pc
|
|
|
|
lst_inv[m] = prijs_inv
|
|
lst_afn[m] = prijs_afn
|
|
lst_rt[m] = regeltoestand
|
|
lst_nv_op[m] = nv_op
|
|
lst_nv_af[m] = nv_af
|
|
lst_opr[m] = opgeregeld
|
|
lst_afr[m] = afgeregeld
|
|
|
|
return [
|
|
list(DAM),
|
|
list(POS),
|
|
list(NEG),
|
|
list(rt),
|
|
lst_inv,
|
|
lst_afn,
|
|
lst_rt,
|
|
lst_nv_op,
|
|
lst_nv_af,
|
|
lst_opr,
|
|
lst_afr,
|
|
]
|