detquantlib 3.2.8__tar.gz → 3.4.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.2.8 → detquantlib-3.4.0}/PKG-INFO +2 -1
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/data/databases/detdatabase.py +139 -6
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/outputs/outputs_interface.py +12 -5
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/tradable_products/tradable_products.py +12 -2
- {detquantlib-3.2.8 → detquantlib-3.4.0}/pyproject.toml +2 -1
- {detquantlib-3.2.8 → detquantlib-3.4.0}/LICENSE.txt +0 -0
- {detquantlib-3.2.8 → detquantlib-3.4.0}/README.md +0 -0
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/__init__.py +0 -0
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/data/__init__.py +0 -0
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/data/entsoe/entsoe.py +0 -0
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/data/sftp/sftp.py +0 -0
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/dates/__init__.py +0 -0
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/dates/dates.py +0 -0
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/figures/__init__.py +0 -0
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/figures/plotly_figures.py +0 -0
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/outputs/__init__.py +0 -0
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/stats/__init__.py +0 -0
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/stats/data_analysis.py +0 -0
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/tradable_products/__init__.py +0 -0
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/utils/__init__.py +0 -0
- {detquantlib-3.2.8 → detquantlib-3.4.0}/detquantlib/utils/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: detquantlib
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.4.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
|
|
@@ -15,6 +15,7 @@ Requires-Dist: paramiko (>=3.5.1,<4.0.0)
|
|
|
15
15
|
Requires-Dist: plotly (>=6.1.2,<7.0.0)
|
|
16
16
|
Requires-Dist: pyodbc (>=5.2.0,<6.0.0)
|
|
17
17
|
Requires-Dist: python-dotenv (>=1.1.0,<2.0.0)
|
|
18
|
+
Requires-Dist: scipy (>=1.15.2,<2.0.0)
|
|
18
19
|
Project-URL: Repository, https://github.com/Dynamic-Energy-Trading/detquantlib
|
|
19
20
|
Description-Content-Type: text/markdown
|
|
20
21
|
|
|
@@ -649,16 +649,16 @@ class DetDatabase:
|
|
|
649
649
|
Loads account positions from the database, over a user-defined range of trading dates.
|
|
650
650
|
|
|
651
651
|
Args:
|
|
652
|
-
start_trading_date: Start trading date
|
|
653
|
-
end_trading_date: End trading date
|
|
652
|
+
start_trading_date: Start trading date.
|
|
653
|
+
end_trading_date: End trading date.
|
|
654
654
|
columns: Requested database table columns. Set columns=["*"] (i.e. as list) to get
|
|
655
655
|
all columns.
|
|
656
656
|
|
|
657
657
|
Returns:
|
|
658
|
-
Dataframe containing
|
|
658
|
+
Dataframe containing account positions.
|
|
659
659
|
|
|
660
660
|
Raises:
|
|
661
|
-
ValueError: Raises an error if no
|
|
661
|
+
ValueError: Raises an error if no position data is found for user inputs.
|
|
662
662
|
"""
|
|
663
663
|
# Set default column values
|
|
664
664
|
if columns is None:
|
|
@@ -678,8 +678,8 @@ class DetDatabase:
|
|
|
678
678
|
table = DetDatabaseDefinitions.DEFINITIONS["table_name_account_position"]
|
|
679
679
|
query = (
|
|
680
680
|
f"SELECT {columns_str} FROM {table} "
|
|
681
|
-
f"WHERE CAST ([InsertionTimestamp] AS DATE)
|
|
682
|
-
f"'{end_trading_date_str}'
|
|
681
|
+
f"WHERE CAST ([InsertionTimestamp] AS DATE) BETWEEN '{start_trading_date_str}' AND "
|
|
682
|
+
f"'{end_trading_date_str}'"
|
|
683
683
|
)
|
|
684
684
|
|
|
685
685
|
# Query db
|
|
@@ -687,6 +687,7 @@ class DetDatabase:
|
|
|
687
687
|
df = self.query_db(query)
|
|
688
688
|
self.close_connection()
|
|
689
689
|
|
|
690
|
+
# Assert data
|
|
690
691
|
if df.empty:
|
|
691
692
|
raise ValueError("No account position data found for user-defined inputs.")
|
|
692
693
|
|
|
@@ -704,6 +705,136 @@ class DetDatabase:
|
|
|
704
705
|
|
|
705
706
|
return df
|
|
706
707
|
|
|
708
|
+
def load_instruments(
|
|
709
|
+
self,
|
|
710
|
+
identifiers: list,
|
|
711
|
+
columns: list = None,
|
|
712
|
+
) -> pd.DataFrame:
|
|
713
|
+
"""
|
|
714
|
+
Loads instrument data based on identifier (of account positions) from the database.
|
|
715
|
+
|
|
716
|
+
Args:
|
|
717
|
+
identifiers: Instrument identifiers (of account positions).
|
|
718
|
+
columns: Requested database table columns. Set columns=["*"] (i.e. as list) to get
|
|
719
|
+
all columns.
|
|
720
|
+
|
|
721
|
+
Returns:
|
|
722
|
+
Dataframe containing instrument data.
|
|
723
|
+
|
|
724
|
+
Raises:
|
|
725
|
+
ValueError: Raises an error if no instrument data is found for user inputs.
|
|
726
|
+
"""
|
|
727
|
+
# Set default column values
|
|
728
|
+
if columns is None:
|
|
729
|
+
columns = ["*"]
|
|
730
|
+
|
|
731
|
+
# Convert columns from list to string
|
|
732
|
+
if len(columns) == 1:
|
|
733
|
+
columns_str = str(columns[0])
|
|
734
|
+
else:
|
|
735
|
+
columns_str = f"[{'], ['.join(columns)}]"
|
|
736
|
+
|
|
737
|
+
# Convert tenors from list to string
|
|
738
|
+
identifiers_str = ", ".join(f"'{i}'" for i in identifiers)
|
|
739
|
+
|
|
740
|
+
# Create query
|
|
741
|
+
table = DetDatabaseDefinitions.DEFINITIONS["table_name_instruments"]
|
|
742
|
+
query = f"SELECT {columns_str} FROM {table} WHERE [id] IN ({identifiers_str})"
|
|
743
|
+
|
|
744
|
+
# Query db
|
|
745
|
+
self.open_connection()
|
|
746
|
+
df = self.query_db(query)
|
|
747
|
+
self.close_connection()
|
|
748
|
+
|
|
749
|
+
# Assert data
|
|
750
|
+
if df.empty:
|
|
751
|
+
raise ValueError("No instrument data found for user-defined inputs.")
|
|
752
|
+
|
|
753
|
+
return df
|
|
754
|
+
|
|
755
|
+
def load_eex_eod_prices(
|
|
756
|
+
self,
|
|
757
|
+
product_code: str,
|
|
758
|
+
start_trading_date: datetime,
|
|
759
|
+
end_trading_date: datetime,
|
|
760
|
+
columns: list = None,
|
|
761
|
+
) -> pd.DataFrame:
|
|
762
|
+
"""
|
|
763
|
+
Loads futures end-of-day EEX prices from the database, over a user-defined range of trading
|
|
764
|
+
dates.
|
|
765
|
+
|
|
766
|
+
Args:
|
|
767
|
+
product_code: Product code format indicating commodity, tenor and delivery type as
|
|
768
|
+
defined in the EEX.EODPrice DET database. Assumed product code format do not
|
|
769
|
+
include other product code format (i.e. DEBW and DEBWE do not co-exist)
|
|
770
|
+
start_trading_date: Start trading date.
|
|
771
|
+
end_trading_date: End trading date.
|
|
772
|
+
columns: Requested database table columns. Set columns=["*"] (i.e. as list) to get
|
|
773
|
+
all columns.
|
|
774
|
+
|
|
775
|
+
Returns:
|
|
776
|
+
Dataframe containing EEX futures end-of-day prices.
|
|
777
|
+
|
|
778
|
+
Raises:
|
|
779
|
+
ValueError: Raises an error if no price data is found for user inputs.
|
|
780
|
+
"""
|
|
781
|
+
# Set default column values
|
|
782
|
+
if columns is None:
|
|
783
|
+
columns = ["*"]
|
|
784
|
+
else:
|
|
785
|
+
# Assert required columns
|
|
786
|
+
columns = list(
|
|
787
|
+
set(columns)
|
|
788
|
+
| {"TradingDate", "Product", "Delivery Start", "Delivery End", "Settlement Price"}
|
|
789
|
+
)
|
|
790
|
+
|
|
791
|
+
# Convert columns from list to string
|
|
792
|
+
if len(columns) == 1:
|
|
793
|
+
columns_str = str(columns[0])
|
|
794
|
+
else:
|
|
795
|
+
columns_str = f"[{'], ['.join(columns)}]"
|
|
796
|
+
|
|
797
|
+
# Convert dates from datetime to string
|
|
798
|
+
start_trading_date_str = start_trading_date.strftime("%Y-%m-%d")
|
|
799
|
+
end_trading_date_str = end_trading_date.strftime("%Y-%m-%d")
|
|
800
|
+
|
|
801
|
+
# Create query
|
|
802
|
+
table = DetDatabaseDefinitions.DEFINITIONS["table_name_eex_eod_price"]
|
|
803
|
+
query = (
|
|
804
|
+
f"SELECT {columns_str} FROM {table} "
|
|
805
|
+
f"WHERE [Product] LIKE '{product_code}' "
|
|
806
|
+
f"AND CAST ([TradingDate] AS DATE) BETWEEN '{start_trading_date_str}' AND "
|
|
807
|
+
f"'{end_trading_date_str}'"
|
|
808
|
+
)
|
|
809
|
+
|
|
810
|
+
# Query db
|
|
811
|
+
self.open_connection()
|
|
812
|
+
df = self.query_db(query)
|
|
813
|
+
self.close_connection()
|
|
814
|
+
|
|
815
|
+
# Assert data
|
|
816
|
+
if df.empty:
|
|
817
|
+
raise ValueError("No price data found for user-defined inputs.")
|
|
818
|
+
|
|
819
|
+
# Sort data
|
|
820
|
+
df.sort_values(
|
|
821
|
+
by=["TradingDate", "Delivery Start", "Delivery End"],
|
|
822
|
+
axis=0,
|
|
823
|
+
ascending=True,
|
|
824
|
+
inplace=True,
|
|
825
|
+
ignore_index=True,
|
|
826
|
+
)
|
|
827
|
+
|
|
828
|
+
# Convert dates from datetime.date to pd.Timestamp
|
|
829
|
+
df["TradingDate"] = pd.DatetimeIndex(df["TradingDate"])
|
|
830
|
+
df["Delivery Start"] = pd.DatetimeIndex(df["Delivery Start"])
|
|
831
|
+
df["Delivery End"] = pd.DatetimeIndex(df["Delivery End"])
|
|
832
|
+
|
|
833
|
+
# Drop duplicates
|
|
834
|
+
df = df.drop_duplicates()
|
|
835
|
+
|
|
836
|
+
return df
|
|
837
|
+
|
|
707
838
|
|
|
708
839
|
class DetDatabaseDefinitions:
|
|
709
840
|
"""A class containing some hard-coded definitions related to the DET database."""
|
|
@@ -714,4 +845,6 @@ class DetDatabaseDefinitions:
|
|
|
714
845
|
table_name_entsoe_imbalance_price="[ENTSOE].[ImbalancePrice]",
|
|
715
846
|
table_name_futures_eod_settlement_price="[VW].[EODSettlementPrice]",
|
|
716
847
|
table_name_account_position="[TT].[AccountPosition]",
|
|
848
|
+
table_name_instruments="[TT].[Instrument]",
|
|
849
|
+
table_name_eex_eod_price="[EEX].[EODPrice]",
|
|
717
850
|
)
|
|
@@ -12,7 +12,12 @@ class OutputItem:
|
|
|
12
12
|
"""A class to easily manage, store and export a model output."""
|
|
13
13
|
|
|
14
14
|
def __init__(
|
|
15
|
-
self,
|
|
15
|
+
self,
|
|
16
|
+
data=None,
|
|
17
|
+
filename: str = None,
|
|
18
|
+
extension: str = None,
|
|
19
|
+
sub_path: str = None,
|
|
20
|
+
export_options: dict = None,
|
|
16
21
|
):
|
|
17
22
|
"""
|
|
18
23
|
Constructor method.
|
|
@@ -23,11 +28,13 @@ class OutputItem:
|
|
|
23
28
|
extension: File extension to be used when exporting the output data
|
|
24
29
|
sub_path: Within the output base directory, indicates the sub-path (if any) of the
|
|
25
30
|
folder where the output data should be exported
|
|
31
|
+
export_options: Additional options for the function exporting the output data to a file
|
|
26
32
|
"""
|
|
27
33
|
self.data = data
|
|
28
34
|
self.filename = filename
|
|
29
35
|
self.extension = extension
|
|
30
36
|
self.sub_path = sub_path
|
|
37
|
+
self.export_options = dict() if export_options is None else export_options
|
|
31
38
|
|
|
32
39
|
def export_to_file(self, folder_dir: Path = None):
|
|
33
40
|
"""
|
|
@@ -74,7 +81,7 @@ class OutputItem:
|
|
|
74
81
|
"""
|
|
75
82
|
data_type = type(self.data)
|
|
76
83
|
if data_type is pd.DataFrame:
|
|
77
|
-
self.data.to_csv(file_dir,
|
|
84
|
+
self.data.to_csv(file_dir, **self.export_options)
|
|
78
85
|
else:
|
|
79
86
|
raise TypeError(f"Exporting data type {data_type} to csv file is not supported.")
|
|
80
87
|
|
|
@@ -91,7 +98,7 @@ class OutputItem:
|
|
|
91
98
|
data_type = type(self.data)
|
|
92
99
|
if data_type is dict:
|
|
93
100
|
with open(file_dir, "w") as f:
|
|
94
|
-
json.dump(self.data, f, indent=4)
|
|
101
|
+
json.dump(self.data, f, indent=4, **self.export_options)
|
|
95
102
|
else:
|
|
96
103
|
raise TypeError(f"Exporting data type {data_type} to json file is not supported.")
|
|
97
104
|
|
|
@@ -107,7 +114,7 @@ class OutputItem:
|
|
|
107
114
|
"""
|
|
108
115
|
data_type = type(self.data)
|
|
109
116
|
if data_type is go.Figure:
|
|
110
|
-
self.data.write_html(file_dir)
|
|
117
|
+
self.data.write_html(file_dir, **self.export_options)
|
|
111
118
|
else:
|
|
112
119
|
raise TypeError(f"Exporting data type {data_type} to html file is not supported.")
|
|
113
120
|
|
|
@@ -123,7 +130,7 @@ class OutputItem:
|
|
|
123
130
|
"""
|
|
124
131
|
data_type = type(self.data)
|
|
125
132
|
if data_type is np.ndarray:
|
|
126
|
-
np.savez_compressed(file_dir, data=self.data)
|
|
133
|
+
np.savez_compressed(file_dir, data=self.data, **self.export_options)
|
|
127
134
|
else:
|
|
128
135
|
raise TypeError(f"Exporting data type {data_type} to npz file is not supported.")
|
|
129
136
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# Python built-in packages
|
|
2
|
+
import math
|
|
2
3
|
from datetime import datetime
|
|
3
4
|
from typing import Literal
|
|
4
5
|
|
|
@@ -13,7 +14,7 @@ from detquantlib.dates.dates import calc_months_diff
|
|
|
13
14
|
def convert_delivery_start_date_to_maturity(
|
|
14
15
|
trading_date: datetime,
|
|
15
16
|
delivery_start_date: datetime,
|
|
16
|
-
product: Literal["month", "quarter", "year"],
|
|
17
|
+
product: Literal["day", "weekend", "week", "month", "quarter", "year"],
|
|
17
18
|
) -> int:
|
|
18
19
|
"""
|
|
19
20
|
Calculates the number of maturities between the input trading date and the input delivery
|
|
@@ -34,7 +35,16 @@ def convert_delivery_start_date_to_maturity(
|
|
|
34
35
|
# Make input product string lower case only
|
|
35
36
|
product = product.lower()
|
|
36
37
|
|
|
37
|
-
if product == "
|
|
38
|
+
if product == "day":
|
|
39
|
+
maturity = (delivery_start_date - trading_date).days
|
|
40
|
+
|
|
41
|
+
elif product == "week":
|
|
42
|
+
maturity = math.ceil((delivery_start_date - trading_date).ceil("D").days / 7)
|
|
43
|
+
|
|
44
|
+
elif product == "weekend":
|
|
45
|
+
maturity = math.ceil((delivery_start_date - trading_date).ceil("D").days / 7)
|
|
46
|
+
|
|
47
|
+
elif product == "month":
|
|
38
48
|
maturity = calc_months_diff(
|
|
39
49
|
start_date=trading_date,
|
|
40
50
|
end_date=delivery_start_date,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "detquantlib"
|
|
3
|
-
version = "3.
|
|
3
|
+
version = "3.4.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"
|
|
@@ -17,6 +17,7 @@ pandas = "^2.3.0"
|
|
|
17
17
|
plotly = "^6.1.2"
|
|
18
18
|
pyodbc = "^5.2.0"
|
|
19
19
|
python-dotenv = "^1.1.0"
|
|
20
|
+
scipy = "^1.15.2"
|
|
20
21
|
|
|
21
22
|
[tool.poetry.group.dev.dependencies]
|
|
22
23
|
toml = "^0.10.2"
|
|
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
|