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.
Files changed (21) hide show
  1. {detquantlib-3.5.1 → detquantlib-3.6.0}/PKG-INFO +1 -1
  2. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/data/databases/detdatabase.py +143 -14
  3. {detquantlib-3.5.1 → detquantlib-3.6.0}/pyproject.toml +1 -1
  4. {detquantlib-3.5.1 → detquantlib-3.6.0}/LICENSE.txt +0 -0
  5. {detquantlib-3.5.1 → detquantlib-3.6.0}/README.md +0 -0
  6. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/__init__.py +0 -0
  7. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/data/__init__.py +0 -0
  8. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/data/entsoe/entsoe.py +0 -0
  9. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/data/sftp/sftp.py +0 -0
  10. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/dates/__init__.py +0 -0
  11. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/dates/dates.py +0 -0
  12. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/figures/__init__.py +0 -0
  13. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/figures/plotly_figures.py +0 -0
  14. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/outputs/__init__.py +0 -0
  15. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/outputs/outputs_interface.py +0 -0
  16. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/stats/__init__.py +0 -0
  17. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/stats/data_analysis.py +0 -0
  18. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/tradable_products/__init__.py +0 -0
  19. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/tradable_products/tradable_products.py +0 -0
  20. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/utils/__init__.py +0 -0
  21. {detquantlib-3.5.1 → detquantlib-3.6.0}/detquantlib/utils/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: detquantlib
3
- Version: 3.5.1
3
+ Version: 3.6.0
4
4
  Summary: An internal library containing functions and classes that can be used across Quant models.
5
5
  Author: DET
6
6
  Requires-Python: >=3.10,<4.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 ([InsertionTimestamp] AS DATE) BETWEEN '{start_trading_date_str}' AND "
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.sort_values(
722
- by=["InsertionTimestamp"],
723
- axis=0,
724
- ascending=True,
725
- inplace=True,
726
- ignore_index=True,
727
- )
728
-
729
- # Convert dates from datetime.date to pd.Timestamp
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 [Product] LIKE '{product_code}' "
832
- f"AND CAST ([TradingDate] AS DATE) BETWEEN '{start_trading_date_str}' AND "
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
  )
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "detquantlib"
3
- version = "3.5.1"
3
+ version = "3.6.0"
4
4
  description = "An internal library containing functions and classes that can be used across Quant models."
5
5
  authors = ["DET"]
6
6
  readme = "README.md"
File without changes
File without changes