detquantlib 3.5.1__tar.gz → 3.6.0__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.
- {detquantlib-3.5.1 → detquantlib-3.6.0}/PKG-INFO +1 -1
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/data/databases/detdatabase.py +143 -14
- {detquantlib-3.5.1 → detquantlib-3.6.0}/pyproject.toml +1 -1
- {detquantlib-3.5.1 → detquantlib-3.6.0}/LICENSE.txt +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/README.md +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/__init__.py +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/data/__init__.py +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/data/entsoe/entsoe.py +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/data/sftp/sftp.py +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/dates/__init__.py +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/dates/dates.py +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/figures/__init__.py +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/figures/plotly_figures.py +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/outputs/__init__.py +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/outputs/outputs_interface.py +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/stats/__init__.py +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/stats/data_analysis.py +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/tradable_products/__init__.py +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/tradable_products/tradable_products.py +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/utils/__init__.py +0 -0
- {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/utils/utils.py +0 -0
|
@@ -704,7 +704,7 @@ class DetDatabase:
|
|
|
704
704
|
table = DetDatabaseDefinitions.DEFINITIONS["table_name_account_position"]
|
|
705
705
|
query = (
|
|
706
706
|
f"SELECT {columns_str} FROM {table} "
|
|
707
|
-
f"WHERE CAST
|
|
707
|
+
f"WHERE CAST(InsertionTimestamp AS DATE) BETWEEN '{start_trading_date_str}' AND "
|
|
708
708
|
f"'{end_trading_date_str}'"
|
|
709
709
|
)
|
|
710
710
|
|
|
@@ -717,17 +717,16 @@ class DetDatabase:
|
|
|
717
717
|
if df.empty:
|
|
718
718
|
raise ValueError("No account position data found for user-defined inputs.")
|
|
719
719
|
|
|
720
|
-
# Sort data
|
|
721
|
-
df.
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
df["InsertionTimestamp"] = pd.DatetimeIndex(df["InsertionTimestamp"])
|
|
720
|
+
# Sort data and convert dates from datetime.date to pd.Timestamp
|
|
721
|
+
if "InsertionTimestamp" in df.columns:
|
|
722
|
+
df.sort_values(
|
|
723
|
+
by=["InsertionTimestamp"],
|
|
724
|
+
axis=0,
|
|
725
|
+
ascending=True,
|
|
726
|
+
inplace=True,
|
|
727
|
+
ignore_index=True,
|
|
728
|
+
)
|
|
729
|
+
df["InsertionTimestamp"] = pd.DatetimeIndex(df["InsertionTimestamp"])
|
|
731
730
|
|
|
732
731
|
return df
|
|
733
732
|
|
|
@@ -828,8 +827,8 @@ class DetDatabase:
|
|
|
828
827
|
table = DetDatabaseDefinitions.DEFINITIONS["table_name_eex_eod_price"]
|
|
829
828
|
query = (
|
|
830
829
|
f"SELECT {columns_str} FROM {table} "
|
|
831
|
-
f"WHERE
|
|
832
|
-
f"AND CAST
|
|
830
|
+
f"WHERE Product LIKE '{product_code}' "
|
|
831
|
+
f"AND CAST(TradingDate AS DATE) BETWEEN '{start_trading_date_str}' AND "
|
|
833
832
|
f"'{end_trading_date_str}'"
|
|
834
833
|
)
|
|
835
834
|
|
|
@@ -862,6 +861,135 @@ class DetDatabase:
|
|
|
862
861
|
|
|
863
862
|
return df
|
|
864
863
|
|
|
864
|
+
def load_forecast_customer_volume(
|
|
865
|
+
self,
|
|
866
|
+
profile: str,
|
|
867
|
+
forecast_date: datetime,
|
|
868
|
+
start_delivery_date: datetime,
|
|
869
|
+
end_delivery_date: datetime,
|
|
870
|
+
local_timezone: str,
|
|
871
|
+
timezone_aware_dates: bool = False,
|
|
872
|
+
columns: list = None,
|
|
873
|
+
) -> pd.DataFrame:
|
|
874
|
+
"""
|
|
875
|
+
Loads customer volume forecasts from DET database.
|
|
876
|
+
|
|
877
|
+
Args:
|
|
878
|
+
profile: Customer/profile name.
|
|
879
|
+
Note on the 'Portfolio' and 'Portfolioweekend' profiles:
|
|
880
|
+
- Profile names 'Portfolio' and 'Portfolioweekend' refer to the same set of
|
|
881
|
+
connection points.
|
|
882
|
+
- In the database, the profile name is set to 'Portfolio' when the forecast date
|
|
883
|
+
is between Monday and Friday.
|
|
884
|
+
- In the database, the profile name is set to 'Portfolioweekend' when the forecast
|
|
885
|
+
date is Saturday or Sunday.
|
|
886
|
+
- When calling this method, the input argument 'profile' can be set to
|
|
887
|
+
'PortfolioAll' to automatically let the method switch between 'Portfolio' and
|
|
888
|
+
'Portfolioweekend', based on the used-input forecast date.
|
|
889
|
+
forecast_date: Date on which customer volume forecast is generated.
|
|
890
|
+
start_delivery_date: First delivery date included.
|
|
891
|
+
end_delivery_date: Last delivery date included.
|
|
892
|
+
local_timezone: Local timezone (needed to account for DST switches).
|
|
893
|
+
timezone_aware_dates: If true, returns all dates as timezone-aware. Otherwise, returns
|
|
894
|
+
them as timezone-naive.
|
|
895
|
+
columns: Requested database table columns. Set columns=["*"] (i.e. as list) to get all
|
|
896
|
+
columns.
|
|
897
|
+
|
|
898
|
+
Returns:
|
|
899
|
+
Dataframe containing customer volume forecasts.
|
|
900
|
+
|
|
901
|
+
Raises:
|
|
902
|
+
ValueError: Raises an error if no volume forecast data is found for user inputs.
|
|
903
|
+
"""
|
|
904
|
+
# Convert profile if set to "PortfolioAll"
|
|
905
|
+
if profile == "PortfolioAll":
|
|
906
|
+
if forecast_date.weekday() > 4:
|
|
907
|
+
profile = "Portfolioweekend"
|
|
908
|
+
else:
|
|
909
|
+
profile = "Portfolio"
|
|
910
|
+
|
|
911
|
+
# Convert start delivery date from local timezone to UTC and string
|
|
912
|
+
start_delivery_date = start_delivery_date.replace(tzinfo=ZoneInfo(local_timezone))
|
|
913
|
+
start_delivery_date = start_delivery_date.astimezone(ZoneInfo("UTC"))
|
|
914
|
+
start_date_str = start_delivery_date.strftime("%Y-%m-%d %H:%M:%S")
|
|
915
|
+
|
|
916
|
+
# Set delivery end time
|
|
917
|
+
end_delivery_date = end_delivery_date.replace(hour=23, minute=59, second=59)
|
|
918
|
+
|
|
919
|
+
# Convert end delivery date form local timezone to UTC and string
|
|
920
|
+
end_delivery_date = end_delivery_date.replace(tzinfo=ZoneInfo(local_timezone))
|
|
921
|
+
end_delivery_date = end_delivery_date.astimezone(ZoneInfo("UTC"))
|
|
922
|
+
end_date_str = end_delivery_date.strftime("%Y-%m-%d %H:%M:%S")
|
|
923
|
+
|
|
924
|
+
# Set default column values
|
|
925
|
+
if columns is None:
|
|
926
|
+
columns = ["*"]
|
|
927
|
+
|
|
928
|
+
# Convert columns from list to string
|
|
929
|
+
if len(columns) == 1:
|
|
930
|
+
columns_str = str(columns[0])
|
|
931
|
+
else:
|
|
932
|
+
columns_str = f"[{'], ['.join(columns)}]"
|
|
933
|
+
|
|
934
|
+
# Convert dates from datetime to string
|
|
935
|
+
forecast_date = forecast_date.strftime("%Y-%m-%d")
|
|
936
|
+
|
|
937
|
+
# Create query
|
|
938
|
+
table = DetDatabaseDefinitions.DEFINITIONS["table_name_forecast_customer_volume"]
|
|
939
|
+
query = (
|
|
940
|
+
f"SELECT {columns_str} FROM {table} "
|
|
941
|
+
f"WHERE Profile = '{profile}'"
|
|
942
|
+
f"AND ForecastDate = '{forecast_date}'"
|
|
943
|
+
f"AND CAST(Datetime AS DATETIME) BETWEEN '{start_date_str}' AND "
|
|
944
|
+
f"'{end_date_str}'"
|
|
945
|
+
)
|
|
946
|
+
|
|
947
|
+
# Query db
|
|
948
|
+
self.open_connection()
|
|
949
|
+
df = self.query_db(query)
|
|
950
|
+
self.close_connection()
|
|
951
|
+
|
|
952
|
+
# Assert data
|
|
953
|
+
if df.empty:
|
|
954
|
+
raise ValueError("No volume forecast data found for user-defined inputs.")
|
|
955
|
+
|
|
956
|
+
# Sort data
|
|
957
|
+
sort_cols = ["Profile", "ForecastDate", "Datetime"]
|
|
958
|
+
sort_cols = [c for c in sort_cols if c in df.columns]
|
|
959
|
+
if len(sort_cols) > 0:
|
|
960
|
+
df.sort_values(
|
|
961
|
+
by=sort_cols,
|
|
962
|
+
axis=0,
|
|
963
|
+
ascending=True,
|
|
964
|
+
inplace=True,
|
|
965
|
+
ignore_index=True,
|
|
966
|
+
)
|
|
967
|
+
|
|
968
|
+
# Localize, convert and set timezone-(un)aware datetimes
|
|
969
|
+
cols_date = ["ForecastDate", "Datetime", "InsertionTimestamp"]
|
|
970
|
+
for c in cols_date:
|
|
971
|
+
if c in df.columns:
|
|
972
|
+
# Convert from datetime to pandas timestamp
|
|
973
|
+
df[c] = pd.DatetimeIndex(df[c])
|
|
974
|
+
|
|
975
|
+
# Convert to timezone-aware dates
|
|
976
|
+
if c == "ForecastDate":
|
|
977
|
+
df[c] = df[c].dt.tz_localize(local_timezone)
|
|
978
|
+
else:
|
|
979
|
+
df[c] = df[c].dt.tz_localize("UTC")
|
|
980
|
+
df[c] = df[c].dt.tz_convert(local_timezone)
|
|
981
|
+
|
|
982
|
+
if not timezone_aware_dates:
|
|
983
|
+
df[c] = df[c].dt.tz_localize(None)
|
|
984
|
+
|
|
985
|
+
# Rescale column values
|
|
986
|
+
df["kWh"] = df["kWh"] / 1000
|
|
987
|
+
|
|
988
|
+
# Rename columns
|
|
989
|
+
df = df.rename(columns={"kWh": "Volume(MWh)", "Datetime": "DeliveryStart"})
|
|
990
|
+
|
|
991
|
+
return df
|
|
992
|
+
|
|
865
993
|
|
|
866
994
|
class DetDatabaseDefinitions:
|
|
867
995
|
"""A class containing some hard-coded definitions related to the DET database."""
|
|
@@ -874,4 +1002,5 @@ class DetDatabaseDefinitions:
|
|
|
874
1002
|
table_name_account_position="[TT].[AccountPosition]",
|
|
875
1003
|
table_name_instruments="[TT].[Instrument]",
|
|
876
1004
|
table_name_eex_eod_price="[EEX].[EODPrice]",
|
|
1005
|
+
table_name_forecast_customer_volume="[DISP].[ForecastGold]",
|
|
877
1006
|
)
|
|
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
|