eetc-utils 1.9.0__tar.gz → 2.0.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.
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/PKG-INFO +3 -3
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/README.md +2 -2
- eetc_utils-2.0.0/pyproject.toml +64 -0
- eetc_utils-1.9.0/pyproject.toml → eetc_utils-2.0.0/pyproject.toml.orig +1 -1
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/src/eetc_utils/clients/eetc_data.py +28 -22
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/src/eetc_utils/strategy/backtesting/engine.py +1 -1
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/src/eetc_utils/strategy/engine.py +1 -3
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/LICENSE +0 -0
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/src/eetc_utils/__init__.py +0 -0
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/src/eetc_utils/clients/__init__.py +0 -0
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/src/eetc_utils/clients/claude.py +0 -0
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/src/eetc_utils/clients/eetc_notifications.py +0 -0
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/src/eetc_utils/finance.py +0 -0
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/src/eetc_utils/options.py +0 -0
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/src/eetc_utils/strategy/__init__.py +0 -0
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/src/eetc_utils/strategy/backtesting/__init__.py +0 -0
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/src/eetc_utils/strategy/backtesting/broker_sim.py +0 -0
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/src/eetc_utils/strategy/backtesting/metrics.py +0 -0
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/src/eetc_utils/strategy/backtesting/strategy.py +0 -0
- {eetc_utils-1.9.0 → eetc_utils-2.0.0}/src/eetc_utils/strategy/strategy.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: eetc-utils
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: EETC Utils Library
|
|
5
5
|
Author: East Empire Trading Company, Stefan Delic, Milos Dovedan
|
|
6
6
|
Author-email: East Empire Trading Company <eastempiretradingcompany2019@gmail.com>, Stefan Delic <einfach.jung1@gmail.com>, Milos Dovedan <dovedanmilosh@gmail.com>
|
|
@@ -147,8 +147,8 @@ import os
|
|
|
147
147
|
# Initialize client (requires EETC_API_KEY environment variable)
|
|
148
148
|
client = EETCDataClient(api_key=os.getenv("EETC_API_KEY"))
|
|
149
149
|
|
|
150
|
-
# Fetch price data
|
|
151
|
-
price_data = client.get_price_data(
|
|
150
|
+
# Fetch price data (one symbol or a list, batched into few requests)
|
|
151
|
+
price_data = client.get_price_data(["AAPL", "MSFT"], from_date="2024-01-01")
|
|
152
152
|
|
|
153
153
|
# Get fundamentals
|
|
154
154
|
fundamentals = client.get_fundamentals(symbol="AAPL")
|
|
@@ -124,8 +124,8 @@ import os
|
|
|
124
124
|
# Initialize client (requires EETC_API_KEY environment variable)
|
|
125
125
|
client = EETCDataClient(api_key=os.getenv("EETC_API_KEY"))
|
|
126
126
|
|
|
127
|
-
# Fetch price data
|
|
128
|
-
price_data = client.get_price_data(
|
|
127
|
+
# Fetch price data (one symbol or a list, batched into few requests)
|
|
128
|
+
price_data = client.get_price_data(["AAPL", "MSFT"], from_date="2024-01-01")
|
|
129
129
|
|
|
130
130
|
# Get fundamentals
|
|
131
131
|
fundamentals = client.get_fundamentals(symbol="AAPL")
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["uv_build>=0.11.6,<0.12.0"]
|
|
3
|
+
build-backend = "uv_build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "eetc-utils"
|
|
7
|
+
version = "2.0.0"
|
|
8
|
+
description = "EETC Utils Library"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
requires-python = ">=3.12,<4.0"
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Operating System :: OS Independent",
|
|
16
|
+
]
|
|
17
|
+
dependencies = [
|
|
18
|
+
"pandas>=2.3.3,<3.0.0",
|
|
19
|
+
"numpy>=2.3.4,<3.0.0",
|
|
20
|
+
"arch>=8.0.0,<9.0.0",
|
|
21
|
+
"requests>=2.28.0,<3.0.0",
|
|
22
|
+
"anthropic>=1.6.0,<2.0.0",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[[project.authors]]
|
|
26
|
+
name = "East Empire Trading Company"
|
|
27
|
+
email = "eastempiretradingcompany2019@gmail.com"
|
|
28
|
+
|
|
29
|
+
[[project.authors]]
|
|
30
|
+
name = "Stefan Delic"
|
|
31
|
+
email = "einfach.jung1@gmail.com"
|
|
32
|
+
|
|
33
|
+
[[project.authors]]
|
|
34
|
+
name = "Milos Dovedan"
|
|
35
|
+
email = "dovedanmilosh@gmail.com"
|
|
36
|
+
|
|
37
|
+
[[project.maintainers]]
|
|
38
|
+
name = "East Empire Trading Company"
|
|
39
|
+
email = "eastempiretradingcompany2019@gmail.com"
|
|
40
|
+
|
|
41
|
+
[[project.maintainers]]
|
|
42
|
+
name = "Stefan Delic"
|
|
43
|
+
email = "einfach.jung1@gmail.com"
|
|
44
|
+
|
|
45
|
+
[[project.maintainers]]
|
|
46
|
+
name = "Milos Dovedan"
|
|
47
|
+
email = "dovedanmilosh@gmail.com"
|
|
48
|
+
|
|
49
|
+
[project.urls]
|
|
50
|
+
Homepage = "https://github.com/east-empire-trading-company/eetc-utils"
|
|
51
|
+
Repository = "https://github.com/east-empire-trading-company/eetc-utils"
|
|
52
|
+
"Bug Tracker" = "https://github.com/east-empire-trading-company/eetc-utils/issues"
|
|
53
|
+
|
|
54
|
+
[dependency-groups]
|
|
55
|
+
dev = [
|
|
56
|
+
"black>=25.9.0,<26.0.0",
|
|
57
|
+
"pytest>=9.0.1,<10.0.0",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
[[tool.uv.index]]
|
|
61
|
+
name = "testpypi"
|
|
62
|
+
url = "https://test.pypi.org/simple/"
|
|
63
|
+
publish-url = "https://test.pypi.org/legacy/"
|
|
64
|
+
explicit = true
|
|
@@ -4,6 +4,9 @@ import pandas as pd
|
|
|
4
4
|
import requests
|
|
5
5
|
from requests import Response
|
|
6
6
|
|
|
7
|
+
# max number of symbols the /price/ endpoint accepts per request
|
|
8
|
+
PRICE_BATCH_SIZE = 500
|
|
9
|
+
|
|
7
10
|
|
|
8
11
|
class EETCDataClient:
|
|
9
12
|
"""
|
|
@@ -55,44 +58,47 @@ class EETCDataClient:
|
|
|
55
58
|
|
|
56
59
|
def get_price_data(
|
|
57
60
|
self,
|
|
58
|
-
|
|
61
|
+
symbols: Union[str, List[str]],
|
|
59
62
|
date: Optional[str] = None,
|
|
60
63
|
from_date: Optional[str] = None,
|
|
61
64
|
to_date: Optional[str] = None,
|
|
62
65
|
as_json: bool = False,
|
|
63
66
|
) -> Union[pd.DataFrame, List[Dict]]:
|
|
64
67
|
"""
|
|
65
|
-
Get historical price data
|
|
68
|
+
Get historical price data for one or more symbols from EETC Data
|
|
69
|
+
Hub via REST API.
|
|
66
70
|
|
|
67
|
-
|
|
71
|
+
Symbols are fetched in alphabetically sorted batches of
|
|
72
|
+
PRICE_BATCH_SIZE, since each request costs about the same in
|
|
73
|
+
BigQuery whether it reads one symbol or hundreds.
|
|
74
|
+
|
|
75
|
+
:param symbols: Ticker symbol (e.g., "AAPL") or list of ticker
|
|
76
|
+
symbols.
|
|
68
77
|
:param date: Specific date in format "yyyy-mm-dd".
|
|
69
78
|
:param from_date: Earliest date in format "yyyy-mm-dd".
|
|
70
79
|
:param to_date: Latest date in format "yyyy-mm-dd".
|
|
71
80
|
:param as_json: If True, returns raw JSON list; if False
|
|
72
81
|
(default), returns pandas DataFrame.
|
|
73
|
-
:return: Historical price data as pandas DataFrame
|
|
74
|
-
list of dicts (if as_json=True).
|
|
82
|
+
:return: Historical price data as pandas DataFrame sorted by
|
|
83
|
+
symbol and date (default) or list of dicts (if as_json=True).
|
|
75
84
|
:raises requests.HTTPError: If the API request fails.
|
|
76
85
|
"""
|
|
77
86
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
# add optional query params
|
|
82
|
-
if date:
|
|
83
|
-
params["date"] = date
|
|
84
|
-
|
|
85
|
-
if from_date:
|
|
86
|
-
params["from_date"] = from_date
|
|
87
|
+
if isinstance(symbols, str):
|
|
88
|
+
symbols = [symbols]
|
|
87
89
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
response = self._send_http_request(url, params)
|
|
90
|
+
symbols = sorted(set(symbols))
|
|
91
|
+
url = f"{self.base_url}/price/"
|
|
92
|
+
params = {"date": date, "from_date": from_date, "to_date": to_date}
|
|
93
|
+
params = {k: v for k, v in params.items() if v is not None}
|
|
93
94
|
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
response_data = []
|
|
96
|
+
for i in range(0, len(symbols), PRICE_BATCH_SIZE):
|
|
97
|
+
batch = symbols[i : i + PRICE_BATCH_SIZE]
|
|
98
|
+
response = self._send_http_request(
|
|
99
|
+
url, {**params, "symbols": ",".join(batch)}
|
|
100
|
+
)
|
|
101
|
+
response_data.extend(response.json())
|
|
96
102
|
|
|
97
103
|
if as_json:
|
|
98
104
|
return response_data
|
|
@@ -101,7 +107,7 @@ class EETCDataClient:
|
|
|
101
107
|
return pd.DataFrame()
|
|
102
108
|
|
|
103
109
|
df = pd.json_normalize(response_data)
|
|
104
|
-
df = df.sort_values(by=["date"])
|
|
110
|
+
df = df.sort_values(by=["symbol", "date"], ignore_index=True)
|
|
105
111
|
|
|
106
112
|
return df
|
|
107
113
|
|
|
@@ -21,9 +21,7 @@ class Engine:
|
|
|
21
21
|
} # output
|
|
22
22
|
|
|
23
23
|
# fetch input data
|
|
24
|
-
price_df = self.client.get_price_data(
|
|
25
|
-
symbol=symbol, from_date=start, to_date=end
|
|
26
|
-
)
|
|
24
|
+
price_df = self.client.get_price_data(symbol, from_date=start, to_date=end)
|
|
27
25
|
context = {
|
|
28
26
|
"engine": self,
|
|
29
27
|
"symbol": symbol,
|
|
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
|