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.
Files changed (36) hide show
  1. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/PKG-INFO +1 -1
  2. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/composite/__init__.py +1 -1
  3. eptr2-1.1.2.dev1/eptr2/composite/dabi_idm.py +305 -0
  4. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/util/time.py +55 -1
  5. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/pyproject.toml +1 -1
  6. eptr2-1.1.1.dev0/eptr2/composite/dabi.py +0 -156
  7. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/LICENSE +0 -0
  8. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/README.md +0 -0
  9. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/__init__.py +0 -0
  10. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/composite/bpm.py +0 -0
  11. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/composite/consumption.py +0 -0
  12. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/composite/idm_log.py +0 -0
  13. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/composite/mms.py +0 -0
  14. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/composite/price_and_cost.py +0 -0
  15. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/composite/production.py +0 -0
  16. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/main.py +0 -0
  17. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/mapping/__init__.py +0 -0
  18. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/mapping/checks.py +0 -0
  19. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/mapping/help.py +0 -0
  20. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/mapping/parameters.py +0 -0
  21. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/mapping/path.py +0 -0
  22. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/mapping/processing.py +0 -0
  23. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/processing/__init__.py +0 -0
  24. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/processing/postprocess/__init__.py +0 -0
  25. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/processing/postprocess/items.py +0 -0
  26. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/processing/preprocess/__init__.py +0 -0
  27. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/processing/preprocess/calls.py +0 -0
  28. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/processing/preprocess/params.py +0 -0
  29. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/tutorials/__init__.py +0 -0
  30. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/tutorials/calc.py +0 -0
  31. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/tutorials/demo.py +0 -0
  32. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/tutorials/main.py +0 -0
  33. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/util/__init__.py +0 -0
  34. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/util/certificate.py +0 -0
  35. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/util/costs.py +0 -0
  36. {eptr2-1.1.1.dev0 → eptr2-1.1.2.dev1}/eptr2/util/evaluation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: eptr2
3
- Version: 1.1.1.dev0
3
+ Version: 1.1.2.dev1
4
4
  Summary: EPIAS Transparency Platform v2.0 Python client by Robokami Data
5
5
  License: Apache-2.0
6
6
  Author: Tideseed
@@ -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.dabi import *
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,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "eptr2"
3
- version = "1.1.1.dev0"
3
+ version = "1.1.2.dev1"
4
4
  description = "EPIAS Transparency Platform v2.0 Python client by Robokami Data"
5
5
  authors = ["Tideseed <info@tideseed.com>"]
6
6
  license = "Apache License 2.0"
@@ -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