eptr2 1.1.1.dev0__tar.gz → 1.1.2.dev1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/PKG-INFO +1 -1
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/composite/__init__.py +1 -1
- eptr2-1.1.2.dev1/eptr2/composite/dabi_idm.py +305 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/util/time.py +55 -1
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/pyproject.toml +1 -1
- eptr2-1.1.1.dev0/eptr2/composite/dabi.py +0 -156
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/LICENSE +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/README.md +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/__init__.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/composite/bpm.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/composite/consumption.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/composite/idm_log.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/composite/mms.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/composite/price_and_cost.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/composite/production.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/main.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/mapping/__init__.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/mapping/checks.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/mapping/help.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/mapping/parameters.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/mapping/path.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/mapping/processing.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/processing/__init__.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/processing/postprocess/__init__.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/processing/postprocess/items.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/processing/preprocess/__init__.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/processing/preprocess/calls.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/processing/preprocess/params.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/tutorials/__init__.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/tutorials/calc.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/tutorials/demo.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/tutorials/main.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/util/__init__.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/util/certificate.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/util/costs.py +0 -0
- {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/util/evaluation.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from eptr2.composite.consumption import *
|
|
2
2
|
from eptr2.composite.price_and_cost import *
|
|
3
3
|
from eptr2.composite.production import *
|
|
4
|
-
from eptr2.composite.
|
|
4
|
+
from eptr2.composite.dabi_idm import *
|
|
5
5
|
from eptr2.composite.bpm import *
|
|
6
6
|
from eptr2.composite.idm_log import *
|
|
7
7
|
from eptr2.composite.mms import *
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
from eptr2 import EPTR2
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from eptr2.util.time import (
|
|
4
|
+
iso_to_contract,
|
|
5
|
+
get_previous_day,
|
|
6
|
+
get_start_end_dates_period,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def process_idm_data(
|
|
11
|
+
eptr: EPTR2, start_date: str, end_date: str, org_id: str, **kwargs
|
|
12
|
+
) -> pd.DataFrame:
|
|
13
|
+
"""
|
|
14
|
+
This function processes IDM data and includes it in the DataFrame.
|
|
15
|
+
It fetches day ahead and bilateral matches, and merges them with IDM data.
|
|
16
|
+
"""
|
|
17
|
+
lives = kwargs.get("lives", 2)
|
|
18
|
+
while lives > 0:
|
|
19
|
+
try:
|
|
20
|
+
df = eptr.call(
|
|
21
|
+
"idm-qty",
|
|
22
|
+
start_date=get_previous_day(start_date),
|
|
23
|
+
end_date=end_date,
|
|
24
|
+
org_id=org_id,
|
|
25
|
+
request_kwargs={"timeout": 5},
|
|
26
|
+
)
|
|
27
|
+
break
|
|
28
|
+
except Exception as e:
|
|
29
|
+
print("Error fetching IDM data:", e)
|
|
30
|
+
lives -= 1
|
|
31
|
+
if lives <= 0:
|
|
32
|
+
raise Exception("Max lives reached. Exiting.")
|
|
33
|
+
continue
|
|
34
|
+
|
|
35
|
+
### Due to naming confusion by EPIAS, ask is mapped to buy and bid is mapped to sell.
|
|
36
|
+
|
|
37
|
+
if df.empty:
|
|
38
|
+
df = pd.DataFrame(columns=["contract", "idm_long", "idm_short"])
|
|
39
|
+
else:
|
|
40
|
+
df = df.drop("kontratTuru", axis=1).rename(
|
|
41
|
+
{
|
|
42
|
+
"kontratAdi": "contract",
|
|
43
|
+
"clearingQuantityAsk": "idm_long",
|
|
44
|
+
"clearingQuantityBid": "idm_short",
|
|
45
|
+
},
|
|
46
|
+
axis=1,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
return df
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def get_day_ahead_and_bilateral_matches(
|
|
53
|
+
eptr: EPTR2,
|
|
54
|
+
start_date: str,
|
|
55
|
+
end_date: str,
|
|
56
|
+
include_contract_symbol: bool = False,
|
|
57
|
+
org_id: str = None,
|
|
58
|
+
include_idm_data: bool = False,
|
|
59
|
+
include_org_id: bool = False,
|
|
60
|
+
verbose: bool = False,
|
|
61
|
+
**kwargs,
|
|
62
|
+
):
|
|
63
|
+
"""
|
|
64
|
+
This composite function gets day ahead and bilateral matches for the whole market or for a single organization. You can also include IDM data if you provide an org_id.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
if verbose:
|
|
68
|
+
print("Getting day ahead matches...")
|
|
69
|
+
|
|
70
|
+
lives = kwargs.get("lives", 2)
|
|
71
|
+
while lives > 0:
|
|
72
|
+
try:
|
|
73
|
+
df_da = eptr.call(
|
|
74
|
+
"dam-clearing",
|
|
75
|
+
start_date=start_date,
|
|
76
|
+
end_date=end_date,
|
|
77
|
+
org_id=org_id,
|
|
78
|
+
request_kwargs={"timeout": 5},
|
|
79
|
+
)
|
|
80
|
+
break
|
|
81
|
+
except Exception as e:
|
|
82
|
+
print("Error fetching day ahead matches:", e)
|
|
83
|
+
lives -= 1
|
|
84
|
+
if lives <= 0:
|
|
85
|
+
raise Exception("Max lives reached. Exiting.")
|
|
86
|
+
|
|
87
|
+
continue
|
|
88
|
+
|
|
89
|
+
df = df_da.rename(
|
|
90
|
+
{"matchedBids": "da_long", "matchedOffers": "da_short"}, axis=1
|
|
91
|
+
).drop("hour", axis=1)
|
|
92
|
+
|
|
93
|
+
for cc in ["bi-long", "bi-short"]:
|
|
94
|
+
if verbose:
|
|
95
|
+
print(f"Getting bilateral {cc} matches...")
|
|
96
|
+
|
|
97
|
+
lives = kwargs.get("lives", 2)
|
|
98
|
+
while lives > 0:
|
|
99
|
+
try:
|
|
100
|
+
df_bi = eptr.call(
|
|
101
|
+
cc,
|
|
102
|
+
start_date=start_date,
|
|
103
|
+
end_date=end_date,
|
|
104
|
+
org_id=org_id,
|
|
105
|
+
request_kwargs={"timeout": 5},
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
df = df.merge(
|
|
109
|
+
df_bi.rename({"quantity": cc.replace("-", "_")}, axis=1).drop(
|
|
110
|
+
"hour", axis=1
|
|
111
|
+
),
|
|
112
|
+
on="date",
|
|
113
|
+
how="left",
|
|
114
|
+
)
|
|
115
|
+
break
|
|
116
|
+
except Exception as e:
|
|
117
|
+
print("Error fetching bilateral long matches:", e)
|
|
118
|
+
lives -= 1
|
|
119
|
+
if lives <= 0:
|
|
120
|
+
raise Exception("Max lives reached. Exiting.")
|
|
121
|
+
continue
|
|
122
|
+
|
|
123
|
+
# if verbose:
|
|
124
|
+
# print("Getting bilateral short matches...")
|
|
125
|
+
|
|
126
|
+
# df_bi_short = eptr.call(
|
|
127
|
+
# "bi-short",
|
|
128
|
+
# start_date=start_date,
|
|
129
|
+
# end_date=end_date,
|
|
130
|
+
# org_id=org_id,
|
|
131
|
+
# request_kwargs={"timeout": 5},
|
|
132
|
+
# )
|
|
133
|
+
|
|
134
|
+
# df = df.merge(
|
|
135
|
+
# df_bi_short.rename({"quantity": "bi_short"}, axis=1).drop("hour", axis=1),
|
|
136
|
+
# on="date",
|
|
137
|
+
# how="left",
|
|
138
|
+
# )
|
|
139
|
+
|
|
140
|
+
df["dabi_net"] = df["da_long"] - df["da_short"] + df["bi_long"] - df["bi_short"]
|
|
141
|
+
|
|
142
|
+
if include_idm_data:
|
|
143
|
+
include_contract_symbol = True
|
|
144
|
+
|
|
145
|
+
if include_contract_symbol:
|
|
146
|
+
try:
|
|
147
|
+
df["contract"] = df["date"].apply(lambda x: iso_to_contract(x))
|
|
148
|
+
except Exception as e:
|
|
149
|
+
print("Contract information could not be added. Error:", e)
|
|
150
|
+
|
|
151
|
+
if include_idm_data:
|
|
152
|
+
if verbose:
|
|
153
|
+
print("Getting IDM data...")
|
|
154
|
+
df_idm = process_idm_data(eptr, start_date, end_date, org_id)
|
|
155
|
+
df = (
|
|
156
|
+
df.merge(df_idm, on=["contract"], how="left")
|
|
157
|
+
.fillna(0.0)
|
|
158
|
+
.infer_objects(copy=False)
|
|
159
|
+
)
|
|
160
|
+
df["idm_net"] = df["idm_long"] - df["idm_short"]
|
|
161
|
+
df["dabi_idm_net"] = df["dabi_net"] + df["idm_net"]
|
|
162
|
+
df["dabi_idm_net"] = df["dabi_idm_net"].round(2)
|
|
163
|
+
|
|
164
|
+
if include_org_id and org_id is not None:
|
|
165
|
+
df["org_id"] = org_id
|
|
166
|
+
|
|
167
|
+
return df
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def get_dabi_idm_data(
|
|
171
|
+
eptr: EPTR2,
|
|
172
|
+
start_date: str,
|
|
173
|
+
end_date: str,
|
|
174
|
+
org_id: str | None = None,
|
|
175
|
+
verbose: bool = False,
|
|
176
|
+
):
|
|
177
|
+
"""
|
|
178
|
+
This function retrieves DABI IDM data for a specific organization. It is a wrapper around the `process_idm_data` function.
|
|
179
|
+
"""
|
|
180
|
+
|
|
181
|
+
return get_day_ahead_and_bilateral_matches(
|
|
182
|
+
eptr=eptr,
|
|
183
|
+
start_date=start_date,
|
|
184
|
+
end_date=end_date,
|
|
185
|
+
org_id=org_id,
|
|
186
|
+
include_idm_data=True,
|
|
187
|
+
include_contract_symbol=True,
|
|
188
|
+
include_org_id=True,
|
|
189
|
+
verbose=verbose,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def get_dabi_idm_data_period(
|
|
194
|
+
eptr: EPTR2,
|
|
195
|
+
period: str,
|
|
196
|
+
org_id: str | None = None,
|
|
197
|
+
verbose: bool = False,
|
|
198
|
+
):
|
|
199
|
+
"""
|
|
200
|
+
This function retrieves DABI IDM data for a specific organization over a period.
|
|
201
|
+
It is a wrapper around the `get_dabi_idm_data` function.
|
|
202
|
+
"""
|
|
203
|
+
|
|
204
|
+
start_date, end_date = get_start_end_dates_period(period=period)
|
|
205
|
+
|
|
206
|
+
return get_dabi_idm_data(
|
|
207
|
+
eptr=eptr,
|
|
208
|
+
start_date=start_date,
|
|
209
|
+
end_date=end_date,
|
|
210
|
+
org_id=org_id,
|
|
211
|
+
verbose=verbose,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def get_day_ahead_detail_info(
|
|
216
|
+
eptr: EPTR2,
|
|
217
|
+
start_date: str,
|
|
218
|
+
end_date: str,
|
|
219
|
+
verbose: bool = False,
|
|
220
|
+
include_contract_symbol: bool = False,
|
|
221
|
+
lives: int = 3,
|
|
222
|
+
**kwargs,
|
|
223
|
+
) -> pd.DataFrame:
|
|
224
|
+
"""
|
|
225
|
+
This function gets day ahead detail information such as regular, block, flexible bids & asks (offers).
|
|
226
|
+
"""
|
|
227
|
+
|
|
228
|
+
df_d: dict[pd.DataFrame] = {}
|
|
229
|
+
|
|
230
|
+
items = [
|
|
231
|
+
"dam-bid",
|
|
232
|
+
"dam-offer",
|
|
233
|
+
"dam-block-bid",
|
|
234
|
+
"dam-block-offer",
|
|
235
|
+
"dam-flexible-bid",
|
|
236
|
+
"dam-flexible-offer",
|
|
237
|
+
# "dam-flexible-matching",
|
|
238
|
+
]
|
|
239
|
+
|
|
240
|
+
map_d = {
|
|
241
|
+
"dam-bid": {"bidQuantity": "bid"},
|
|
242
|
+
"dam-offer": {"offerQuantity": "ask"},
|
|
243
|
+
"dam-block-bid": {
|
|
244
|
+
"amountOfPurchasingTowardsMatchedBlock": "block_long_match",
|
|
245
|
+
"amountOfPurchasingTowardsUnMatchedBlock": "block_long_remaining",
|
|
246
|
+
},
|
|
247
|
+
"dam-block-offer": {
|
|
248
|
+
"amountOfSalesTowardsMatchedBlock": "block_short_match",
|
|
249
|
+
"amountOfSalesTowardsUnMatchedBlock": "block_short_remaining",
|
|
250
|
+
},
|
|
251
|
+
"dam-flexible-bid": {
|
|
252
|
+
"totalBuyingFlexibleOfferQuantity": "flex_long_total",
|
|
253
|
+
"matchedBuyingFlexibleOfferQuantity": "flex_long_match",
|
|
254
|
+
"unmatchedBuyingFlexibleOfferQuantity": "flex_long_remaining",
|
|
255
|
+
},
|
|
256
|
+
"dam-flexible-offer": {
|
|
257
|
+
"totalSellingFlexibleOfferQuantity": "flex_short_total",
|
|
258
|
+
"matchedSellingFlexibleOfferQuantity": "flex_short_match",
|
|
259
|
+
"unmatchedSellingFlexibleOfferQuantity": "flex_short_remaining",
|
|
260
|
+
},
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
df: pd.DataFrame | None = None
|
|
264
|
+
|
|
265
|
+
while len(items) > 0:
|
|
266
|
+
for item in items:
|
|
267
|
+
try:
|
|
268
|
+
if verbose:
|
|
269
|
+
print(f"Fetching {item} data...")
|
|
270
|
+
df_d[item] = eptr.call(
|
|
271
|
+
item,
|
|
272
|
+
start_date=start_date,
|
|
273
|
+
end_date=end_date,
|
|
274
|
+
request_kwargs={"timeout": kwargs.get("timeout", 5)},
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
df_d[item].rename(map_d[item], axis=1, inplace=True)
|
|
278
|
+
if "hour" in df_d[item].columns:
|
|
279
|
+
df_d[item].drop("hour", axis=1, inplace=True)
|
|
280
|
+
elif "time" in df_d[item].columns:
|
|
281
|
+
df_d[item].drop("time", axis=1, inplace=True)
|
|
282
|
+
|
|
283
|
+
if df is None:
|
|
284
|
+
df = df_d[item].copy()
|
|
285
|
+
else:
|
|
286
|
+
df = df.merge(df_d[item], on="date", how="outer")
|
|
287
|
+
|
|
288
|
+
except Exception as e:
|
|
289
|
+
if verbose:
|
|
290
|
+
print(f"Error fetching {item}: {e}")
|
|
291
|
+
lives -= 1
|
|
292
|
+
if lives <= 0:
|
|
293
|
+
print("Max lives reached. Exiting.")
|
|
294
|
+
break
|
|
295
|
+
continue
|
|
296
|
+
|
|
297
|
+
items = [item for item in items if item not in df_d or df_d[item].empty]
|
|
298
|
+
|
|
299
|
+
if include_contract_symbol:
|
|
300
|
+
try:
|
|
301
|
+
df["contract"] = df["date"].apply(lambda x: iso_to_contract(x))
|
|
302
|
+
except Exception as e:
|
|
303
|
+
print("Contract information could not be added. Error:", e)
|
|
304
|
+
|
|
305
|
+
return df
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from datetime import datetime, timedelta, timezone
|
|
2
2
|
import pytz
|
|
3
|
+
from typing import Literal
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
def check_iso_format(
|
|
@@ -49,11 +50,16 @@ def get_today_utc3():
|
|
|
49
50
|
return get_utc3_now().strftime("%Y-%m-%d")
|
|
50
51
|
|
|
51
52
|
|
|
52
|
-
def get_date_from_key(key):
|
|
53
|
+
def get_date_from_key(key: Literal["today", "start_of_month", "end_of_month"]):
|
|
53
54
|
if key == "today":
|
|
54
55
|
res = get_today_utc3()
|
|
55
56
|
elif key == "start_of_month":
|
|
56
57
|
res = get_utc3_now().strftime("%Y-%m-01")
|
|
58
|
+
elif key == "end_of_month":
|
|
59
|
+
res = (
|
|
60
|
+
(get_utc3_now().replace(day=1) + timedelta(days=31)).replace(day=1)
|
|
61
|
+
- timedelta(days=1)
|
|
62
|
+
).strftime("%Y-%m-%d")
|
|
57
63
|
|
|
58
64
|
return res
|
|
59
65
|
|
|
@@ -399,3 +405,51 @@ def check_date_for_settlement(x: str | datetime, settlement_day=15):
|
|
|
399
405
|
return True
|
|
400
406
|
|
|
401
407
|
return False
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
def date_str_to_datetime(date_str: str, fmt: str = "%Y-%m-%d"):
|
|
411
|
+
"""
|
|
412
|
+
Convert a date string to a datetime object.
|
|
413
|
+
"""
|
|
414
|
+
try:
|
|
415
|
+
return pytz.timezone("Europe/Istanbul").localize(
|
|
416
|
+
datetime.strptime(date_str, fmt)
|
|
417
|
+
)
|
|
418
|
+
except ValueError:
|
|
419
|
+
print(f"Invalid date format: {date_str}. Expected format: {fmt}.")
|
|
420
|
+
return None
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def offset_date_by_n_days(date_str: str, fmt: str = "%Y-%m-%d", n: int = 1):
|
|
424
|
+
"""
|
|
425
|
+
Get the previous day from a given date string.
|
|
426
|
+
"""
|
|
427
|
+
dt = date_str_to_datetime(date_str, fmt)
|
|
428
|
+
if dt:
|
|
429
|
+
offset_day = dt + timedelta(days=n)
|
|
430
|
+
return offset_day.strftime(fmt)
|
|
431
|
+
return None
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
def get_previous_day(date_str: str, fmt: str = "%Y-%m-%d"):
|
|
435
|
+
"""
|
|
436
|
+
Get the previous day from a given date string. Useful for IDM queries.
|
|
437
|
+
"""
|
|
438
|
+
return offset_date_by_n_days(date_str, fmt, n=-1)
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
def get_start_end_dates_period(period: str):
|
|
442
|
+
"""
|
|
443
|
+
Get the start and end dates for a given period.
|
|
444
|
+
"""
|
|
445
|
+
|
|
446
|
+
dt = pytz.timezone("Europe/Istanbul").localize(
|
|
447
|
+
datetime.strptime(period, "%Y-%m-%d")
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
start_date = dt.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
|
451
|
+
end_date = (start_date + timedelta(days=31)).replace(day=1) - timedelta(days=1)
|
|
452
|
+
start_date = start_date.strftime("%Y-%m-%d")
|
|
453
|
+
end_date = end_date.strftime("%Y-%m-%d")
|
|
454
|
+
|
|
455
|
+
return start_date, end_date
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
from eptr2 import EPTR2
|
|
2
|
-
import pandas as pd
|
|
3
|
-
from eptr2.util.time import iso_to_contract
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def get_day_ahead_and_bilateral_matches(
|
|
7
|
-
eptr: EPTR2,
|
|
8
|
-
start_date: str,
|
|
9
|
-
end_date: str,
|
|
10
|
-
verbose: bool = False,
|
|
11
|
-
include_contract_symbol: bool = False,
|
|
12
|
-
org_id: str = None,
|
|
13
|
-
):
|
|
14
|
-
"""
|
|
15
|
-
This composite function gets day ahead and bilateral matches for the whole market or for a single organization.
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
if verbose:
|
|
19
|
-
print("Getting day ahead matches...")
|
|
20
|
-
|
|
21
|
-
df_da = eptr.call(
|
|
22
|
-
"dam-clearing", start_date=start_date, end_date=end_date, org_id=org_id
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
df = df_da.rename(
|
|
26
|
-
{"matchedBids": "da_long", "matchedOffers": "da_short"}, axis=1
|
|
27
|
-
).drop("hour", axis=1)
|
|
28
|
-
|
|
29
|
-
if verbose:
|
|
30
|
-
print("Getting bilateral long matches...")
|
|
31
|
-
|
|
32
|
-
df_bi_long = eptr.call(
|
|
33
|
-
"bi-long", start_date=start_date, end_date=end_date, org_id=org_id
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
df = df.merge(
|
|
37
|
-
df_bi_long.rename({"quantity": "bi_long"}, axis=1).drop("hour", axis=1),
|
|
38
|
-
on="date",
|
|
39
|
-
how="left",
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
if verbose:
|
|
43
|
-
print("Getting bilateral short matches...")
|
|
44
|
-
|
|
45
|
-
df_bi_short = eptr.call(
|
|
46
|
-
"bi-short", start_date=start_date, end_date=end_date, org_id=org_id
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
df = df.merge(
|
|
50
|
-
df_bi_short.rename({"quantity": "bi_short"}, axis=1).drop("hour", axis=1),
|
|
51
|
-
on="date",
|
|
52
|
-
how="left",
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
if include_contract_symbol:
|
|
56
|
-
try:
|
|
57
|
-
df["contract"] = df["date"].apply(lambda x: iso_to_contract(x))
|
|
58
|
-
except Exception as e:
|
|
59
|
-
print("Contract information could not be added. Error:", e)
|
|
60
|
-
|
|
61
|
-
return df
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def get_day_ahead_detail_info(
|
|
65
|
-
eptr: EPTR2,
|
|
66
|
-
start_date: str,
|
|
67
|
-
end_date: str,
|
|
68
|
-
verbose: bool = False,
|
|
69
|
-
include_contract_symbol: bool = False,
|
|
70
|
-
lives: int = 3,
|
|
71
|
-
**kwargs,
|
|
72
|
-
) -> pd.DataFrame:
|
|
73
|
-
"""
|
|
74
|
-
This function gets day ahead detail information such as regular, block, flexible bids & asks (offers).
|
|
75
|
-
"""
|
|
76
|
-
|
|
77
|
-
df_d: dict[pd.DataFrame] = {}
|
|
78
|
-
|
|
79
|
-
items = [
|
|
80
|
-
"dam-bid",
|
|
81
|
-
"dam-offer",
|
|
82
|
-
"dam-block-bid",
|
|
83
|
-
"dam-block-offer",
|
|
84
|
-
"dam-flexible-bid",
|
|
85
|
-
"dam-flexible-offer",
|
|
86
|
-
# "dam-flexible-matching",
|
|
87
|
-
]
|
|
88
|
-
|
|
89
|
-
map_d = {
|
|
90
|
-
"dam-bid": {"bidQuantity": "bid"},
|
|
91
|
-
"dam-offer": {"offerQuantity": "ask"},
|
|
92
|
-
"dam-block-bid": {
|
|
93
|
-
"amountOfPurchasingTowardsMatchedBlock": "block_long_match",
|
|
94
|
-
"amountOfPurchasingTowardsUnMatchedBlock": "block_long_remaining",
|
|
95
|
-
},
|
|
96
|
-
"dam-block-offer": {
|
|
97
|
-
"amountOfSalesTowardsMatchedBlock": "block_short_match",
|
|
98
|
-
"amountOfSalesTowardsUnMatchedBlock": "block_short_remaining",
|
|
99
|
-
},
|
|
100
|
-
"dam-flexible-bid": {
|
|
101
|
-
"totalBuyingFlexibleOfferQuantity": "flex_long_total",
|
|
102
|
-
"matchedBuyingFlexibleOfferQuantity": "flex_long_match",
|
|
103
|
-
"unmatchedBuyingFlexibleOfferQuantity": "flex_long_remaining",
|
|
104
|
-
},
|
|
105
|
-
"dam-flexible-offer": {
|
|
106
|
-
"totalSellingFlexibleOfferQuantity": "flex_short_total",
|
|
107
|
-
"matchedSellingFlexibleOfferQuantity": "flex_short_match",
|
|
108
|
-
"unmatchedSellingFlexibleOfferQuantity": "flex_short_remaining",
|
|
109
|
-
},
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
df: pd.DataFrame | None = None
|
|
113
|
-
|
|
114
|
-
while len(items) > 0:
|
|
115
|
-
for item in items:
|
|
116
|
-
try:
|
|
117
|
-
if verbose:
|
|
118
|
-
print(f"Fetching {item} data...")
|
|
119
|
-
df_d[item] = eptr.call(
|
|
120
|
-
item,
|
|
121
|
-
start_date=start_date,
|
|
122
|
-
end_date=end_date,
|
|
123
|
-
request_kwargs={"timeout": kwargs.get("timeout", 5)},
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
df_d[item].rename(map_d[item], axis=1, inplace=True)
|
|
127
|
-
if "hour" in df_d[item].columns:
|
|
128
|
-
df_d[item].drop("hour", axis=1, inplace=True)
|
|
129
|
-
elif "time" in df_d[item].columns:
|
|
130
|
-
df_d[item].drop("time", axis=1, inplace=True)
|
|
131
|
-
|
|
132
|
-
if df is None:
|
|
133
|
-
df = df_d[item].copy()
|
|
134
|
-
else:
|
|
135
|
-
df = df.merge(df_d[item], on="date", how="outer")
|
|
136
|
-
|
|
137
|
-
except Exception as e:
|
|
138
|
-
if verbose:
|
|
139
|
-
print(f"Error fetching {item}: {e}")
|
|
140
|
-
lives -= 1
|
|
141
|
-
if lives <= 0:
|
|
142
|
-
print("Max lives reached. Exiting.")
|
|
143
|
-
break
|
|
144
|
-
continue
|
|
145
|
-
|
|
146
|
-
items = [item for item in items if item not in df_d or df_d[item].empty]
|
|
147
|
-
|
|
148
|
-
# df.fillna(0, inplace=True)
|
|
149
|
-
|
|
150
|
-
if include_contract_symbol:
|
|
151
|
-
try:
|
|
152
|
-
df["contract"] = df["date"].apply(lambda x: iso_to_contract(x))
|
|
153
|
-
except Exception as e:
|
|
154
|
-
print("Contract information could not be added. Error:", e)
|
|
155
|
-
|
|
156
|
-
return df
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|