bw-essentials-core 0.1.19__py3-none-any.whl → 0.1.20__py3-none-any.whl
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.
Potentially problematic release.
This version of bw-essentials-core might be problematic. Click here for more details.
- bw_essentials/services/api_client.py +36 -0
- bw_essentials/services/master_data.py +51 -0
- {bw_essentials_core-0.1.19.dist-info → bw_essentials_core-0.1.20.dist-info}/METADATA +1 -1
- {bw_essentials_core-0.1.19.dist-info → bw_essentials_core-0.1.20.dist-info}/RECORD +6 -6
- {bw_essentials_core-0.1.19.dist-info → bw_essentials_core-0.1.20.dist-info}/WHEEL +0 -0
- {bw_essentials_core-0.1.19.dist-info → bw_essentials_core-0.1.20.dist-info}/top_level.txt +0 -0
|
@@ -15,6 +15,7 @@ import logging
|
|
|
15
15
|
import os
|
|
16
16
|
import sys
|
|
17
17
|
import time
|
|
18
|
+
import httpx
|
|
18
19
|
from importlib.util import spec_from_file_location, module_from_spec
|
|
19
20
|
from typing import Optional, Dict, Any
|
|
20
21
|
|
|
@@ -195,6 +196,41 @@ class ApiClient:
|
|
|
195
196
|
"""
|
|
196
197
|
return self._request("get", url, endpoint, params=params)
|
|
197
198
|
|
|
199
|
+
async def _async_get(self, url: str, endpoint: str, headers: dict | None = None, params: dict | None = None):
|
|
200
|
+
"""
|
|
201
|
+
Async GET request, aligned with the sync _request() style.
|
|
202
|
+
"""
|
|
203
|
+
headers = self._update_headers(headers or {})
|
|
204
|
+
params = params or {}
|
|
205
|
+
formatted_url = f"{url.rstrip('/')}/{endpoint.lstrip('/')}"
|
|
206
|
+
|
|
207
|
+
logger.info(f"GET {formatted_url} | Headers: {headers} | Params: {params}")
|
|
208
|
+
|
|
209
|
+
start = time.time()
|
|
210
|
+
try:
|
|
211
|
+
async with httpx.AsyncClient() as client:
|
|
212
|
+
response = await client.get(formatted_url, headers=headers, params=params)
|
|
213
|
+
|
|
214
|
+
elapsed_time_ms = (time.time() - start) * 1000
|
|
215
|
+
|
|
216
|
+
# parse JSON safely
|
|
217
|
+
try:
|
|
218
|
+
json_data = response.json()
|
|
219
|
+
except ValueError:
|
|
220
|
+
logger.error(f"Non-JSON response from {formatted_url}")
|
|
221
|
+
json_data = None
|
|
222
|
+
|
|
223
|
+
self._log_response("GET", formatted_url, response.status_code, elapsed_time_ms, json_data)
|
|
224
|
+
|
|
225
|
+
response.raise_for_status()
|
|
226
|
+
return json_data
|
|
227
|
+
|
|
228
|
+
except Exception as exc:
|
|
229
|
+
elapsed_time_ms = (time.time() - start) * 1000
|
|
230
|
+
logger.error(f"GET {formatted_url} failed after {elapsed_time_ms:.2f}ms")
|
|
231
|
+
logger.exception(exc)
|
|
232
|
+
raise
|
|
233
|
+
|
|
198
234
|
def _post(
|
|
199
235
|
self,
|
|
200
236
|
url: str,
|
|
@@ -299,3 +299,54 @@ class MasterData(ApiClient):
|
|
|
299
299
|
response = self._get(url=self.base_url, endpoint=self.urls["broker_partner_mapping_details"].format(broker_partner, broker))
|
|
300
300
|
logger.info(f"Broker partner mapping {response =}")
|
|
301
301
|
return response.get('data', {})
|
|
302
|
+
|
|
303
|
+
async def get_broker_data_async(self, symbols, broker, username=None):
|
|
304
|
+
"""
|
|
305
|
+
Asynchronously retrieve broker-specific data for specified symbols.
|
|
306
|
+
|
|
307
|
+
This function fetches broker-specific details such as margin and leverage
|
|
308
|
+
for a list of provided trading symbols from the broker master service.
|
|
309
|
+
|
|
310
|
+
Args:
|
|
311
|
+
username (str) [Optional]: The user_id for whom data is requested.
|
|
312
|
+
symbols (str): A comma-separated string of trading symbols.
|
|
313
|
+
broker (str): The broker identifier for which data is requested.
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
list: A list of dictionaries containing broker data for each symbol
|
|
317
|
+
or an empty list if no data is available.
|
|
318
|
+
"""
|
|
319
|
+
logger.info(f"In - get_broker_data_async {broker =}")
|
|
320
|
+
broker_data_response = await self._async_get(
|
|
321
|
+
url=f"{self.base_url}",
|
|
322
|
+
endpoint = self.urls["broker_details"].format(broker),
|
|
323
|
+
params={"symbols": symbols, "user_id": username},
|
|
324
|
+
headers={}
|
|
325
|
+
)
|
|
326
|
+
return broker_data_response.get('data', [])
|
|
327
|
+
|
|
328
|
+
def get_broker_data_all(self, symbols, broker, username=None):
|
|
329
|
+
"""
|
|
330
|
+
Retrieve broker-specific data for specified symbols.
|
|
331
|
+
|
|
332
|
+
This function fetches broker-specific details such as margin and leverage
|
|
333
|
+
for a list of provided trading symbols from the broker master service.
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
username (str) [Optional]: The user_id for whom data is requested.
|
|
337
|
+
symbols (str): A comma-separated string of trading symbols.
|
|
338
|
+
broker (str): The broker identifier for which data is requested.
|
|
339
|
+
|
|
340
|
+
Returns:
|
|
341
|
+
dict: A dictionary containing broker data for the first symbol or
|
|
342
|
+
an empty dictionary if no data is available.
|
|
343
|
+
"""
|
|
344
|
+
logger.info(f"In - get_broker_data {broker =}")
|
|
345
|
+
broker_data_response = self._get(
|
|
346
|
+
url=f"{self.base_url}",
|
|
347
|
+
endpoint=self.urls['broker_details'].format(broker),
|
|
348
|
+
params={"symbols": symbols, "user_id": username},
|
|
349
|
+
)
|
|
350
|
+
if broker_data_response.get('data'):
|
|
351
|
+
return broker_data_response.get('data')
|
|
352
|
+
return {}
|
|
@@ -11,11 +11,11 @@ bw_essentials/notifications/teams_notifications.py,sha256=1tkS3tTJQZ5ByMwK2WXpFg
|
|
|
11
11
|
bw_essentials/s3_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
bw_essentials/s3_utils/s3_utils.py,sha256=wzjVrTX22_8PMX86svKFYGMZwgjBHbOaeEsxO-lR7BY,12922
|
|
13
13
|
bw_essentials/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
-
bw_essentials/services/api_client.py,sha256=
|
|
14
|
+
bw_essentials/services/api_client.py,sha256=hGgM1rwiI7Yvq0tj0XfqZUV_hSXEm4S5Vw0lyNvSVDY,9553
|
|
15
15
|
bw_essentials/services/broker.py,sha256=W4y31K7dF4LHfQSvnAwVWfGoYKkdz-W2TXqTLhkUxn8,9348
|
|
16
16
|
bw_essentials/services/job_scheduler.py,sha256=1fQDWBvNa3bMCm3YzlJehoS-HONUSu4_oquuBv6t0Lg,1966
|
|
17
17
|
bw_essentials/services/market_pricer.py,sha256=Qc9lxzAjhefAvjyEKsBPDu60bF6_61cnSpZNfjGMyDg,11755
|
|
18
|
-
bw_essentials/services/master_data.py,sha256=
|
|
18
|
+
bw_essentials/services/master_data.py,sha256=rybavhEbrasaf2NDgSlbn6Jy0jmEDkSqH5XtQ6FrGp4,14195
|
|
19
19
|
bw_essentials/services/model_portfolio_reporting.py,sha256=VLSvfRZOdn-nI3MtgfcqP0ZE3aTqBU0NcncLffPVtD8,4407
|
|
20
20
|
bw_essentials/services/notification.py,sha256=nnvtEqUphhCSTavsV75XvLp1ZNVV-kLU_cFc8zLNIec,5396
|
|
21
21
|
bw_essentials/services/payment.py,sha256=Em8Lvg7aX1Ga4CJDpJimyE_ByZhJZKM6W6rw2cUUIvw,1479
|
|
@@ -25,7 +25,7 @@ bw_essentials/services/trade_placement.py,sha256=PrzeU2XXC9HF1IQ1dMDM_ZHxmC491sO
|
|
|
25
25
|
bw_essentials/services/user_app.py,sha256=1z73G91TygW_MgHjkUVA2WIdN4CQjx_oSZWW6NqFit8,11774
|
|
26
26
|
bw_essentials/services/user_portfolio.py,sha256=uUQUCG8Av8eKBIw-TlNtOPpQluO9HjAkxMzzO5jfzbo,22179
|
|
27
27
|
bw_essentials/services/user_portfolio_reporting.py,sha256=pwqfW95LTiGOGufcTphljFxPlOd-G4Q263UtoQURPxM,6772
|
|
28
|
-
bw_essentials_core-0.1.
|
|
29
|
-
bw_essentials_core-0.1.
|
|
30
|
-
bw_essentials_core-0.1.
|
|
31
|
-
bw_essentials_core-0.1.
|
|
28
|
+
bw_essentials_core-0.1.20.dist-info/METADATA,sha256=pcM0NUKJCPJNkAiOjqSJmTMmCEIjWnYHkBvpKeOK0M8,7502
|
|
29
|
+
bw_essentials_core-0.1.20.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
30
|
+
bw_essentials_core-0.1.20.dist-info/top_level.txt,sha256=gDc5T_y5snwKGXDQUusEus-FEt0RFwG644Yn_58wQOQ,14
|
|
31
|
+
bw_essentials_core-0.1.20.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|