btgsolutions-dataservices-python-client 3.3.0__tar.gz → 4.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.
- {btgsolutions_dataservices_python_client-3.3.0/btgsolutions_dataservices_python_client.egg-info → btgsolutions_dataservices_python_client-4.0.0}/PKG-INFO +10 -26
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/README.md +9 -25
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/__init__.py +1 -1
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/__init__.py +0 -1
- btgsolutions_dataservices_python_client-3.3.0/btgsolutions_dataservices/rest/hfn_v3.py → btgsolutions_dataservices_python_client-4.0.0/btgsolutions_dataservices/rest/hfn.py +4 -4
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/websocket/__init__.py +0 -1
- btgsolutions_dataservices_python_client-3.3.0/btgsolutions_dataservices/websocket/hfn_v3_websocket_client.py → btgsolutions_dataservices_python_client-4.0.0/btgsolutions_dataservices/websocket/hfn_websocket_client.py +6 -6
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0/btgsolutions_dataservices_python_client.egg-info}/PKG-INFO +10 -26
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices_python_client.egg-info/SOURCES.txt +0 -2
- btgsolutions_dataservices_python_client-3.3.0/btgsolutions_dataservices/rest/hfn.py +0 -323
- btgsolutions_dataservices_python_client-3.3.0/btgsolutions_dataservices/websocket/hfn_websocket_client.py +0 -191
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/LICENSE +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/MANIFEST.in +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/config.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/exceptions.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/alternative_data_companies.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/alternative_data_funds.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/alternative_data_macro_markets.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/alternative_data_metadata.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/alternative_data_ownership.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/alternative_data_people.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/authenticator.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/book_scope.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/broker_analytics.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/broker_reference.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/bulk_data.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/company_data.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/corporate_events.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/historical_candles.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/historical_candles_crypto.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/intraday_candles.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/intraday_tick_data.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/public_sources.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/quotes.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/reference_data.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/stock_loan.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/ticker_last_event.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/rest/ticker_last_event_polling.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/websocket/broker_analytics.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/websocket/market_data_feed.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/websocket/market_data_websocket_client.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices/websocket/websocket_default_functions.py +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices_python_client.egg-info/dependency_links.txt +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices_python_client.egg-info/requires.txt +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/btgsolutions_dataservices_python_client.egg-info/top_level.txt +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/pyproject.toml +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/requirements.txt +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/setup.cfg +0 -0
- {btgsolutions_dataservices_python_client-3.3.0 → btgsolutions_dataservices_python_client-4.0.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: btgsolutions_dataservices_python_client
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.0.0
|
|
4
4
|
Summary: Python package containing several classes and data for extracting and manipulating market and trading data.
|
|
5
5
|
Home-page: https://github.com/BTG-Pactual-Solutions/btgsolutions-dataservices-python-client
|
|
6
6
|
Author: BTG Solutions Data Services powered by BTG Pactual Solutions
|
|
@@ -383,28 +383,7 @@ bulk_data.get_compressed_data(channel='98', date='2026-01-30', data_type='instru
|
|
|
383
383
|
|
|
384
384
|
```python
|
|
385
385
|
import btgsolutions_dataservices as btg
|
|
386
|
-
ws = btg.HFNWebSocketClient(api_key='YOUR_API_KEY'
|
|
387
|
-
ws.run(on_message=lambda message: print(message))
|
|
388
|
-
|
|
389
|
-
## The following is optional to keep the program running in a .py file:
|
|
390
|
-
# from time import sleep
|
|
391
|
-
# while True:
|
|
392
|
-
# sleep(1)
|
|
393
|
-
```
|
|
394
|
-
|
|
395
|
-
#### High Frequency News
|
|
396
|
-
|
|
397
|
-
```python
|
|
398
|
-
import btgsolutions_dataservices as btg
|
|
399
|
-
hfn = btg.HighFrequencyNews(api_key='YOUR_API_KEY')
|
|
400
|
-
hfn.latest_news()
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
#### High Frequency News V3 Stream
|
|
404
|
-
|
|
405
|
-
```python
|
|
406
|
-
import btgsolutions_dataservices as btg
|
|
407
|
-
ws = btg.HFNV3WebSocketClient(api_key='YOUR_API_KEY')
|
|
386
|
+
ws = btg.HFNWebSocketClient(api_key='YOUR_API_KEY')
|
|
408
387
|
ws.run(on_message=lambda message: print(message))
|
|
409
388
|
|
|
410
389
|
# Subscribe to live economy news in Portuguese
|
|
@@ -420,13 +399,18 @@ ws.available_filters(settings={})
|
|
|
420
399
|
ws.unsubscribe()
|
|
421
400
|
|
|
422
401
|
ws.close()
|
|
402
|
+
|
|
403
|
+
## The following is optional to keep the program running in a .py file:
|
|
404
|
+
# from time import sleep
|
|
405
|
+
# while True:
|
|
406
|
+
# sleep(1)
|
|
423
407
|
```
|
|
424
408
|
|
|
425
|
-
#### High Frequency News
|
|
409
|
+
#### High Frequency News
|
|
426
410
|
|
|
427
411
|
```python
|
|
428
412
|
import btgsolutions_dataservices as btg
|
|
429
|
-
hfn = btg.
|
|
413
|
+
hfn = btg.HighFrequencyNews(api_key='YOUR_API_KEY')
|
|
430
414
|
|
|
431
415
|
# Latest news with filters
|
|
432
416
|
hfn.get_latest_news(feed='economy', text_language='portuguese', limit=10)
|
|
@@ -437,7 +421,7 @@ hfn.get_latest_news(tags=['PETR4', 'VALE3'])
|
|
|
437
421
|
# Historical news for a date range
|
|
438
422
|
hfn.get_historical_news(
|
|
439
423
|
start_date='2026-05-01T00:00:00.000Z',
|
|
440
|
-
end_date='2026-05-
|
|
424
|
+
end_date='2026-05-08T23:59:59.999Z',
|
|
441
425
|
feed='economy',
|
|
442
426
|
)
|
|
443
427
|
|
|
@@ -360,28 +360,7 @@ bulk_data.get_compressed_data(channel='98', date='2026-01-30', data_type='instru
|
|
|
360
360
|
|
|
361
361
|
```python
|
|
362
362
|
import btgsolutions_dataservices as btg
|
|
363
|
-
ws = btg.HFNWebSocketClient(api_key='YOUR_API_KEY'
|
|
364
|
-
ws.run(on_message=lambda message: print(message))
|
|
365
|
-
|
|
366
|
-
## The following is optional to keep the program running in a .py file:
|
|
367
|
-
# from time import sleep
|
|
368
|
-
# while True:
|
|
369
|
-
# sleep(1)
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
#### High Frequency News
|
|
373
|
-
|
|
374
|
-
```python
|
|
375
|
-
import btgsolutions_dataservices as btg
|
|
376
|
-
hfn = btg.HighFrequencyNews(api_key='YOUR_API_KEY')
|
|
377
|
-
hfn.latest_news()
|
|
378
|
-
```
|
|
379
|
-
|
|
380
|
-
#### High Frequency News V3 Stream
|
|
381
|
-
|
|
382
|
-
```python
|
|
383
|
-
import btgsolutions_dataservices as btg
|
|
384
|
-
ws = btg.HFNV3WebSocketClient(api_key='YOUR_API_KEY')
|
|
363
|
+
ws = btg.HFNWebSocketClient(api_key='YOUR_API_KEY')
|
|
385
364
|
ws.run(on_message=lambda message: print(message))
|
|
386
365
|
|
|
387
366
|
# Subscribe to live economy news in Portuguese
|
|
@@ -397,13 +376,18 @@ ws.available_filters(settings={})
|
|
|
397
376
|
ws.unsubscribe()
|
|
398
377
|
|
|
399
378
|
ws.close()
|
|
379
|
+
|
|
380
|
+
## The following is optional to keep the program running in a .py file:
|
|
381
|
+
# from time import sleep
|
|
382
|
+
# while True:
|
|
383
|
+
# sleep(1)
|
|
400
384
|
```
|
|
401
385
|
|
|
402
|
-
#### High Frequency News
|
|
386
|
+
#### High Frequency News
|
|
403
387
|
|
|
404
388
|
```python
|
|
405
389
|
import btgsolutions_dataservices as btg
|
|
406
|
-
hfn = btg.
|
|
390
|
+
hfn = btg.HighFrequencyNews(api_key='YOUR_API_KEY')
|
|
407
391
|
|
|
408
392
|
# Latest news with filters
|
|
409
393
|
hfn.get_latest_news(feed='economy', text_language='portuguese', limit=10)
|
|
@@ -414,7 +398,7 @@ hfn.get_latest_news(tags=['PETR4', 'VALE3'])
|
|
|
414
398
|
# Historical news for a date range
|
|
415
399
|
hfn.get_historical_news(
|
|
416
400
|
start_date='2026-05-01T00:00:00.000Z',
|
|
417
|
-
end_date='2026-05-
|
|
401
|
+
end_date='2026-05-08T23:59:59.999Z',
|
|
418
402
|
feed='economy',
|
|
419
403
|
)
|
|
420
404
|
|
|
@@ -4,7 +4,6 @@ from .historical_candles_crypto import HistoricalCandlesCrypto
|
|
|
4
4
|
from .authenticator import Authenticator
|
|
5
5
|
from .bulk_data import BulkData
|
|
6
6
|
from .hfn import HighFrequencyNews
|
|
7
|
-
from .hfn_v3 import HighFrequencyNewsV3
|
|
8
7
|
from .quotes import Quotes
|
|
9
8
|
from .intraday_tick_data import IntradayTickData
|
|
10
9
|
from .ticker_last_event import TickerLastEvent
|
|
@@ -8,16 +8,16 @@ import pandas as pd
|
|
|
8
8
|
from .authenticator import Authenticator
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
class
|
|
11
|
+
class HighFrequencyNews:
|
|
12
12
|
"""
|
|
13
|
-
This class provides latest and historical news through the HFN
|
|
13
|
+
This class provides latest and historical news through the HFN API,
|
|
14
14
|
with rich filtering by feed, source, language, tags, categories and free text.
|
|
15
15
|
|
|
16
16
|
* Main use case:
|
|
17
17
|
|
|
18
|
-
>>> from btgsolutions_dataservices import
|
|
18
|
+
>>> from btgsolutions_dataservices import HighFrequencyNews
|
|
19
19
|
|
|
20
|
-
>>> hfn =
|
|
20
|
+
>>> hfn = HighFrequencyNews(
|
|
21
21
|
>>> api_key='YOUR_API_KEY',
|
|
22
22
|
>>> )
|
|
23
23
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from .market_data_websocket_client import MarketDataWebSocketClient
|
|
2
2
|
from .hfn_websocket_client import HFNWebSocketClient
|
|
3
|
-
from .hfn_v3_websocket_client import HFNV3WebSocketClient
|
|
4
3
|
from .market_data_feed import MarketDataFeed
|
|
5
4
|
from .broker_analytics import BrokerAnalyticsWebSocketClient
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
from typing import Optional, Dict,
|
|
2
|
+
from typing import Optional, Dict, Any
|
|
3
3
|
from ..exceptions import WSTypeError, FeedError
|
|
4
4
|
from ..rest import Authenticator
|
|
5
5
|
from ..config import hfn_v3_socket_url, MAX_WS_RECONNECT_RETRIES
|
|
@@ -10,9 +10,9 @@ import ssl
|
|
|
10
10
|
import threading
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class
|
|
13
|
+
class HFNWebSocketClient:
|
|
14
14
|
"""
|
|
15
|
-
This class connects with the BTG Solutions Data Services HFN
|
|
15
|
+
This class connects with the BTG Solutions Data Services HFN WebSocket,
|
|
16
16
|
providing a bidirectional real-time news stream with rich subscription filters,
|
|
17
17
|
on-demand queries, and reader engagement metrics.
|
|
18
18
|
|
|
@@ -28,9 +28,9 @@ class HFNV3WebSocketClient:
|
|
|
28
28
|
|
|
29
29
|
* Main use case:
|
|
30
30
|
|
|
31
|
-
>>> from btgsolutions_dataservices import
|
|
31
|
+
>>> from btgsolutions_dataservices import HFNWebSocketClient
|
|
32
32
|
|
|
33
|
-
>>> ws =
|
|
33
|
+
>>> ws = HFNWebSocketClient(
|
|
34
34
|
>>> api_key='YOUR_API_KEY',
|
|
35
35
|
>>> )
|
|
36
36
|
>>> ws.run()
|
|
@@ -84,7 +84,7 @@ class HFNV3WebSocketClient:
|
|
|
84
84
|
reconnect: bool = True,
|
|
85
85
|
):
|
|
86
86
|
"""
|
|
87
|
-
Initializes a connection to the HFN
|
|
87
|
+
Initializes a connection to the HFN WebSocket.
|
|
88
88
|
|
|
89
89
|
Upon successful connection the server sends a ``message`` event containing
|
|
90
90
|
the server-assigned ``clientId``. Use :meth:`subscribe` afterwards to start
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: btgsolutions_dataservices_python_client
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.0.0
|
|
4
4
|
Summary: Python package containing several classes and data for extracting and manipulating market and trading data.
|
|
5
5
|
Home-page: https://github.com/BTG-Pactual-Solutions/btgsolutions-dataservices-python-client
|
|
6
6
|
Author: BTG Solutions Data Services powered by BTG Pactual Solutions
|
|
@@ -383,28 +383,7 @@ bulk_data.get_compressed_data(channel='98', date='2026-01-30', data_type='instru
|
|
|
383
383
|
|
|
384
384
|
```python
|
|
385
385
|
import btgsolutions_dataservices as btg
|
|
386
|
-
ws = btg.HFNWebSocketClient(api_key='YOUR_API_KEY'
|
|
387
|
-
ws.run(on_message=lambda message: print(message))
|
|
388
|
-
|
|
389
|
-
## The following is optional to keep the program running in a .py file:
|
|
390
|
-
# from time import sleep
|
|
391
|
-
# while True:
|
|
392
|
-
# sleep(1)
|
|
393
|
-
```
|
|
394
|
-
|
|
395
|
-
#### High Frequency News
|
|
396
|
-
|
|
397
|
-
```python
|
|
398
|
-
import btgsolutions_dataservices as btg
|
|
399
|
-
hfn = btg.HighFrequencyNews(api_key='YOUR_API_KEY')
|
|
400
|
-
hfn.latest_news()
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
#### High Frequency News V3 Stream
|
|
404
|
-
|
|
405
|
-
```python
|
|
406
|
-
import btgsolutions_dataservices as btg
|
|
407
|
-
ws = btg.HFNV3WebSocketClient(api_key='YOUR_API_KEY')
|
|
386
|
+
ws = btg.HFNWebSocketClient(api_key='YOUR_API_KEY')
|
|
408
387
|
ws.run(on_message=lambda message: print(message))
|
|
409
388
|
|
|
410
389
|
# Subscribe to live economy news in Portuguese
|
|
@@ -420,13 +399,18 @@ ws.available_filters(settings={})
|
|
|
420
399
|
ws.unsubscribe()
|
|
421
400
|
|
|
422
401
|
ws.close()
|
|
402
|
+
|
|
403
|
+
## The following is optional to keep the program running in a .py file:
|
|
404
|
+
# from time import sleep
|
|
405
|
+
# while True:
|
|
406
|
+
# sleep(1)
|
|
423
407
|
```
|
|
424
408
|
|
|
425
|
-
#### High Frequency News
|
|
409
|
+
#### High Frequency News
|
|
426
410
|
|
|
427
411
|
```python
|
|
428
412
|
import btgsolutions_dataservices as btg
|
|
429
|
-
hfn = btg.
|
|
413
|
+
hfn = btg.HighFrequencyNews(api_key='YOUR_API_KEY')
|
|
430
414
|
|
|
431
415
|
# Latest news with filters
|
|
432
416
|
hfn.get_latest_news(feed='economy', text_language='portuguese', limit=10)
|
|
@@ -437,7 +421,7 @@ hfn.get_latest_news(tags=['PETR4', 'VALE3'])
|
|
|
437
421
|
# Historical news for a date range
|
|
438
422
|
hfn.get_historical_news(
|
|
439
423
|
start_date='2026-05-01T00:00:00.000Z',
|
|
440
|
-
end_date='2026-05-
|
|
424
|
+
end_date='2026-05-08T23:59:59.999Z',
|
|
441
425
|
feed='economy',
|
|
442
426
|
)
|
|
443
427
|
|
|
@@ -22,7 +22,6 @@ btgsolutions_dataservices/rest/bulk_data.py
|
|
|
22
22
|
btgsolutions_dataservices/rest/company_data.py
|
|
23
23
|
btgsolutions_dataservices/rest/corporate_events.py
|
|
24
24
|
btgsolutions_dataservices/rest/hfn.py
|
|
25
|
-
btgsolutions_dataservices/rest/hfn_v3.py
|
|
26
25
|
btgsolutions_dataservices/rest/historical_candles.py
|
|
27
26
|
btgsolutions_dataservices/rest/historical_candles_crypto.py
|
|
28
27
|
btgsolutions_dataservices/rest/intraday_candles.py
|
|
@@ -35,7 +34,6 @@ btgsolutions_dataservices/rest/ticker_last_event.py
|
|
|
35
34
|
btgsolutions_dataservices/rest/ticker_last_event_polling.py
|
|
36
35
|
btgsolutions_dataservices/websocket/__init__.py
|
|
37
36
|
btgsolutions_dataservices/websocket/broker_analytics.py
|
|
38
|
-
btgsolutions_dataservices/websocket/hfn_v3_websocket_client.py
|
|
39
37
|
btgsolutions_dataservices/websocket/hfn_websocket_client.py
|
|
40
38
|
btgsolutions_dataservices/websocket/market_data_feed.py
|
|
41
39
|
btgsolutions_dataservices/websocket/market_data_websocket_client.py
|
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
from typing import Optional
|
|
3
|
-
from ..exceptions import BadResponse
|
|
4
|
-
import requests
|
|
5
|
-
from ..config import url_apis
|
|
6
|
-
import json
|
|
7
|
-
import pandas as pd
|
|
8
|
-
from .authenticator import Authenticator
|
|
9
|
-
|
|
10
|
-
class HighFrequencyNews:
|
|
11
|
-
"""
|
|
12
|
-
This class provides realtime and historical news of several news .
|
|
13
|
-
|
|
14
|
-
* Main use case:
|
|
15
|
-
|
|
16
|
-
>>> from btgsolutions_dataservices import HighFrequencyNews
|
|
17
|
-
|
|
18
|
-
>>> hfn = HighFrequencyNews(
|
|
19
|
-
>>> api_key='YOUR_API_KEY',
|
|
20
|
-
>>> )
|
|
21
|
-
>>> latest_news = hfn.latest_news(
|
|
22
|
-
>>> n = 15,
|
|
23
|
-
>>> )
|
|
24
|
-
|
|
25
|
-
>>> petro_news = hfn.filter_news(
|
|
26
|
-
>>> ticker = 'PETR4',
|
|
27
|
-
>>> )
|
|
28
|
-
|
|
29
|
-
>>> ibov_news = hfn.filter_news(
|
|
30
|
-
>>> tag = 'IBOV',
|
|
31
|
-
>>> )
|
|
32
|
-
|
|
33
|
-
>>> news_21_08 = hfn.historical_news(
|
|
34
|
-
>>> start_date = '2023-08-21',
|
|
35
|
-
>>> end_date = '2023-08-22',
|
|
36
|
-
>>> )
|
|
37
|
-
|
|
38
|
-
>>> available_feeds = hfn.get_available_feeds()
|
|
39
|
-
>>> available_sources = hfn.get_available_sources()
|
|
40
|
-
>>> available_tickers = hfn.get_available_tickers()
|
|
41
|
-
>>> available_tags = hfn.get_available_tags()
|
|
42
|
-
|
|
43
|
-
Parameters
|
|
44
|
-
----------------
|
|
45
|
-
api_key: str
|
|
46
|
-
User identification key.
|
|
47
|
-
Field is required.
|
|
48
|
-
"""
|
|
49
|
-
def __init__(
|
|
50
|
-
self,
|
|
51
|
-
api_key: Optional[str]
|
|
52
|
-
):
|
|
53
|
-
self.api_key = api_key
|
|
54
|
-
self.token = Authenticator(self.api_key).token
|
|
55
|
-
self.headers = {"authorization": f"authorization {self.token}"}
|
|
56
|
-
|
|
57
|
-
self.available_countries = ['brazil', 'chile']
|
|
58
|
-
self.available_feeds = ['raw', 'economy', 'politics', 'crypto', 'cvm', 'ptax']
|
|
59
|
-
|
|
60
|
-
self.available_ref_types = ['tickers','tags', 'feeds', 'sources']
|
|
61
|
-
|
|
62
|
-
self.min_news = 1
|
|
63
|
-
self.max_news = 200
|
|
64
|
-
|
|
65
|
-
def latest_news(
|
|
66
|
-
self,
|
|
67
|
-
feed:str='raw',
|
|
68
|
-
country:str='brazil',
|
|
69
|
-
n:int=10,
|
|
70
|
-
raw_data:bool=False
|
|
71
|
-
):
|
|
72
|
-
"""
|
|
73
|
-
Latest news by feed.
|
|
74
|
-
|
|
75
|
-
Parameters
|
|
76
|
-
----------------
|
|
77
|
-
feed: str
|
|
78
|
-
News feed.
|
|
79
|
-
Example: 'raw', 'economy', 'politics', 'crypto', 'cvm'.
|
|
80
|
-
Default: 'raw'.
|
|
81
|
-
Field is not required.
|
|
82
|
-
country: str
|
|
83
|
-
Country name.
|
|
84
|
-
Example: 'brazil', 'chile'.
|
|
85
|
-
Default: 'brazil'.
|
|
86
|
-
Field is not required.
|
|
87
|
-
n: int
|
|
88
|
-
Number of news to be returned.
|
|
89
|
-
Default: 10.
|
|
90
|
-
Field is not required.
|
|
91
|
-
raw_data: bool
|
|
92
|
-
If True, returns raw data from API, if False, returns a Pandas DataFrame.
|
|
93
|
-
Default: False.
|
|
94
|
-
Field is not required.
|
|
95
|
-
"""
|
|
96
|
-
|
|
97
|
-
if country not in self.available_countries:
|
|
98
|
-
raise Exception(f"Must provide a valid 'country' parameter. Input: '{country}'. Accepted values: {self.available_countries}")
|
|
99
|
-
|
|
100
|
-
if feed not in self.available_feeds:
|
|
101
|
-
raise Exception(f"Must provide a valid 'feed' parameter. Input: '{feed}'. Accepted values: {self.available_feeds}")
|
|
102
|
-
|
|
103
|
-
if not self.min_news < n < self.max_news:
|
|
104
|
-
raise Exception(f"Invalid 'n' parameter. Input: '{n}'. 'n' Must be >= {self.min_news} and <= {self.max_news}")
|
|
105
|
-
|
|
106
|
-
url = f"{url_apis}/hfn/{country}/latest_news/{feed}?n={n}"
|
|
107
|
-
|
|
108
|
-
response = requests.request("GET", url, headers=self.headers)
|
|
109
|
-
if response.status_code == 200:
|
|
110
|
-
response_data = json.loads(response.text)
|
|
111
|
-
if raw_data:
|
|
112
|
-
return response_data
|
|
113
|
-
else:
|
|
114
|
-
return pd.DataFrame(response_data)
|
|
115
|
-
else:
|
|
116
|
-
response = json.loads(response.text)
|
|
117
|
-
raise BadResponse(f'Error: {response.get("ApiClientError")}.\n{response.get("SuggestedAction", "")}')
|
|
118
|
-
|
|
119
|
-
def filter_news(
|
|
120
|
-
self,
|
|
121
|
-
ticker:str=None,
|
|
122
|
-
tag:str=None,
|
|
123
|
-
force:bool=True,
|
|
124
|
-
country:str='brazil',
|
|
125
|
-
raw_data:bool=False
|
|
126
|
-
):
|
|
127
|
-
"""
|
|
128
|
-
Filter news by ticker or tag. If both ticker and tag are provided, the filter will be by ticker only
|
|
129
|
-
|
|
130
|
-
Parameters
|
|
131
|
-
----------------
|
|
132
|
-
ticker: str
|
|
133
|
-
Ticker symbol. Will be used to filter news.
|
|
134
|
-
Example: 'VALE3', 'PETR4'.
|
|
135
|
-
Field is not required.
|
|
136
|
-
tag: str
|
|
137
|
-
Tag name. Will be used to filter news.
|
|
138
|
-
Example: 'IBOV', 'TESOURO', 'RENDA_FIXA'.
|
|
139
|
-
Field is not required.
|
|
140
|
-
force: bool
|
|
141
|
-
Force to return news even if it does not match the requested parameters.
|
|
142
|
-
Default: True
|
|
143
|
-
Example: True, False.
|
|
144
|
-
Field is required.
|
|
145
|
-
country: str
|
|
146
|
-
Country name.
|
|
147
|
-
Default: 'brazil'
|
|
148
|
-
Example: 'brazil', 'chile'.
|
|
149
|
-
Field is required.
|
|
150
|
-
raw_data: bool
|
|
151
|
-
If True, returns raw data from API, if False, returns a Pandas DataFrame.
|
|
152
|
-
Default: False.
|
|
153
|
-
Field is not required.
|
|
154
|
-
"""
|
|
155
|
-
if force is True: force_str = 'true'
|
|
156
|
-
else: force_str = 'false'
|
|
157
|
-
|
|
158
|
-
if country not in self.available_countries:
|
|
159
|
-
raise Exception(f"Must provide a valid 'country' parameter. Input: '{country}'. Accepted values: {self.available_countries}")
|
|
160
|
-
|
|
161
|
-
if not isinstance(ticker, str) and not isinstance(tag, str):
|
|
162
|
-
raise Exception(f"Must provide a ticker or a tag in order to filter news")
|
|
163
|
-
elif isinstance(ticker, str):
|
|
164
|
-
url = f"{url_apis}/hfn/{country}/filter_news/tickers/{ticker}?force={force_str}"
|
|
165
|
-
else:
|
|
166
|
-
url = f"{url_apis}/hfn/{country}/filter_news/tags/{tag}?force={force_str}"
|
|
167
|
-
|
|
168
|
-
response = requests.request("GET", url, headers=self.headers)
|
|
169
|
-
if response.status_code == 200:
|
|
170
|
-
response_data = json.loads(response.text)
|
|
171
|
-
if raw_data:
|
|
172
|
-
return response_data
|
|
173
|
-
else:
|
|
174
|
-
return pd.DataFrame(response_data)
|
|
175
|
-
else:
|
|
176
|
-
response = json.loads(response.text)
|
|
177
|
-
raise BadResponse(f'Error: {response.get("ApiClientError")}.\n{response.get("SuggestedAction", "")}')
|
|
178
|
-
|
|
179
|
-
def historical_news(
|
|
180
|
-
self,
|
|
181
|
-
start_date:str,
|
|
182
|
-
end_date:str,
|
|
183
|
-
feed:str='raw',
|
|
184
|
-
country:str='brazil',
|
|
185
|
-
raw_data:bool=False
|
|
186
|
-
):
|
|
187
|
-
"""
|
|
188
|
-
Provide a datetime interval and get all the news registered on that interval. The interval between start_date and end_date must be 24 hours maximum.
|
|
189
|
-
|
|
190
|
-
Parameters
|
|
191
|
-
----------------
|
|
192
|
-
start_date: str
|
|
193
|
-
Upper bound for news publishing time. Supported formats: ISO Date (YYYY-MM-DD), Long Date (MMM DD YYYY), Short Date (MM/DD/YYYY).
|
|
194
|
-
Example: '2023-08-21'.
|
|
195
|
-
Field is required.
|
|
196
|
-
end_date: str
|
|
197
|
-
Lower bound for news publishing time. Supported formats: ISO Date (YYYY-MM-DD), Long Date (MMM DD YYYY), Short Date (MM/DD/YYYY).
|
|
198
|
-
Example: '2023-08-22'.
|
|
199
|
-
Field is required.
|
|
200
|
-
feed: str
|
|
201
|
-
Feed name.
|
|
202
|
-
Default: 'raw'
|
|
203
|
-
Example: 'raw', 'economy', 'politics', 'crypto', 'cvm'.
|
|
204
|
-
Field is required.
|
|
205
|
-
country: str
|
|
206
|
-
Country name.
|
|
207
|
-
Default: 'brazil'
|
|
208
|
-
Example: 'brazil', 'chile'.
|
|
209
|
-
Field is required.
|
|
210
|
-
raw_data: bool
|
|
211
|
-
If True, returns raw data from API, if False, returns a Pandas DataFrame.
|
|
212
|
-
Default: False.
|
|
213
|
-
Field is not required.
|
|
214
|
-
"""
|
|
215
|
-
if country not in self.available_countries:
|
|
216
|
-
raise Exception(f"Must provide a valid 'country' parameter. Input: '{country}'. Accepted values: {self.available_countries}")
|
|
217
|
-
|
|
218
|
-
if feed not in self.available_feeds:
|
|
219
|
-
raise Exception(f"Must provide a valid 'feed' parameter. Input: '{feed}'. Accepted values: {self.available_feeds}")
|
|
220
|
-
|
|
221
|
-
url = f"{url_apis}/hfn/{country}/news_history?start_date={start_date}&end_date={end_date}&feed={feed}"
|
|
222
|
-
|
|
223
|
-
response = requests.request("GET", url, headers=self.headers)
|
|
224
|
-
if response.status_code == 200:
|
|
225
|
-
response_data = json.loads(response.text)
|
|
226
|
-
if raw_data:
|
|
227
|
-
return response_data
|
|
228
|
-
else:
|
|
229
|
-
return pd.DataFrame(response_data)
|
|
230
|
-
else:
|
|
231
|
-
response = json.loads(response.text)
|
|
232
|
-
raise BadResponse(f'Error: {response.get("ApiClientError")}.\n{response.get("SuggestedAction", "")}')
|
|
233
|
-
|
|
234
|
-
def get_available_feeds(self, country:str='brazil'):
|
|
235
|
-
"""
|
|
236
|
-
This method provides all feeds available for query.
|
|
237
|
-
|
|
238
|
-
Parameters
|
|
239
|
-
----------------
|
|
240
|
-
country: str
|
|
241
|
-
Country name.
|
|
242
|
-
Default: 'brazil'
|
|
243
|
-
Example: 'brazil', 'chile'.
|
|
244
|
-
Field is required.
|
|
245
|
-
"""
|
|
246
|
-
return self.__get_available_reference(ref_type='feeds', country=country)
|
|
247
|
-
|
|
248
|
-
def get_available_sources(self, country:str='brazil'):
|
|
249
|
-
"""
|
|
250
|
-
This method provides all sources available for query.
|
|
251
|
-
|
|
252
|
-
Parameters
|
|
253
|
-
----------------
|
|
254
|
-
country: str
|
|
255
|
-
Country name.
|
|
256
|
-
Default: 'brazil'
|
|
257
|
-
Example: 'brazil', 'chile'.
|
|
258
|
-
Field is required.
|
|
259
|
-
"""
|
|
260
|
-
return self.__get_available_reference(ref_type='sources', country=country)
|
|
261
|
-
|
|
262
|
-
def get_available_tickers(self, country:str='brazil'):
|
|
263
|
-
"""
|
|
264
|
-
This method provides all tickers available for query.
|
|
265
|
-
|
|
266
|
-
Parameters
|
|
267
|
-
----------------
|
|
268
|
-
country: str
|
|
269
|
-
Country name.
|
|
270
|
-
Default: 'brazil'
|
|
271
|
-
Example: 'brazil', 'chile'.
|
|
272
|
-
Field is required.
|
|
273
|
-
"""
|
|
274
|
-
return self.__get_available_reference(ref_type='tickers', country=country)
|
|
275
|
-
|
|
276
|
-
def get_available_tags(self, country:str='brazil'):
|
|
277
|
-
"""
|
|
278
|
-
This method provides all tags available for query.
|
|
279
|
-
|
|
280
|
-
Parameters
|
|
281
|
-
----------------
|
|
282
|
-
country: str
|
|
283
|
-
Country name.
|
|
284
|
-
Default: 'brazil'
|
|
285
|
-
Example: 'brazil', 'chile'.
|
|
286
|
-
Field is required.
|
|
287
|
-
"""
|
|
288
|
-
return self.__get_available_reference(ref_type='tags', country=country)
|
|
289
|
-
|
|
290
|
-
def __get_available_reference(
|
|
291
|
-
self,
|
|
292
|
-
ref_type:str,
|
|
293
|
-
country:str='brazil',
|
|
294
|
-
):
|
|
295
|
-
"""
|
|
296
|
-
Inner function to query reference data by type.
|
|
297
|
-
|
|
298
|
-
Parameters
|
|
299
|
-
----------------
|
|
300
|
-
ref_type: str
|
|
301
|
-
Reference type.
|
|
302
|
-
Example: 'brazil', 'chile'.
|
|
303
|
-
Field is required.
|
|
304
|
-
country: str
|
|
305
|
-
Country name.
|
|
306
|
-
Default: 'brazil'
|
|
307
|
-
Example: 'brazil', 'chile'.
|
|
308
|
-
Field is required.
|
|
309
|
-
"""
|
|
310
|
-
if ref_type not in self.available_ref_types:
|
|
311
|
-
raise Exception(f"Must provide a valid 'ref_type' parameter. Input: '{ref_type}'. Accepted values: {self.available_ref_types}")
|
|
312
|
-
|
|
313
|
-
if country not in self.available_countries:
|
|
314
|
-
raise Exception(f"Must provide a valid 'country' parameter. Input: '{country}'. Accepted values: {self.available_countries}")
|
|
315
|
-
|
|
316
|
-
url = f"{url_apis}/hfn/{country}/available_{ref_type}"
|
|
317
|
-
|
|
318
|
-
response = requests.request("GET", url, headers=self.headers)
|
|
319
|
-
if response.status_code == 200:
|
|
320
|
-
return json.loads(response.text)
|
|
321
|
-
else:
|
|
322
|
-
response = json.loads(response.text)
|
|
323
|
-
raise BadResponse(f'Error: {response.get("ApiClientError")}.\n{response.get("SuggestedAction", "")}')
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
from typing import Optional, List
|
|
3
|
-
from ..exceptions import WSTypeError, DelayedError, FeedError
|
|
4
|
-
from ..rest import Authenticator
|
|
5
|
-
from ..config import hfn_socket_urls, MAX_WS_RECONNECT_RETRIES, VALID_STREAM_TYPES, VALID_COUNTRIES, REALTIME, BR
|
|
6
|
-
from .websocket_default_functions import _on_open, _on_message, _on_error, _on_close
|
|
7
|
-
import websocket
|
|
8
|
-
import json
|
|
9
|
-
import ssl
|
|
10
|
-
import threading
|
|
11
|
-
|
|
12
|
-
class HFNWebSocketClient:
|
|
13
|
-
"""
|
|
14
|
-
This class connects with BTG Solutions Data Services HFN WebSocket, receiving high frequency news in realtime or delayed feeds.
|
|
15
|
-
|
|
16
|
-
* Main use case:
|
|
17
|
-
|
|
18
|
-
>>> from btgsolutions_dataservices import HFNWebSocketClient
|
|
19
|
-
>>> ws = HFNWebSocketClient(
|
|
20
|
-
>>> api_key='YOUR_API_KEY',
|
|
21
|
-
>>> stream_type='realtime',
|
|
22
|
-
>>> country='brazil',
|
|
23
|
-
>>> ssl=True
|
|
24
|
-
>>> )
|
|
25
|
-
>>> ws.run()
|
|
26
|
-
>>> ws.get_latest_news()
|
|
27
|
-
>>> ws.close()
|
|
28
|
-
|
|
29
|
-
Parameters
|
|
30
|
-
----------------
|
|
31
|
-
api_key: str
|
|
32
|
-
User identification key.
|
|
33
|
-
Field is required.
|
|
34
|
-
|
|
35
|
-
stream_type: str
|
|
36
|
-
Websocket connection feed.
|
|
37
|
-
Options: 'realtime', 'delayed'.
|
|
38
|
-
Field is not required. Default: 'realtime'.
|
|
39
|
-
|
|
40
|
-
country: str
|
|
41
|
-
Country name.
|
|
42
|
-
Options: 'brazil' or 'chile'.
|
|
43
|
-
Field is not required. Default: 'brazil'.
|
|
44
|
-
|
|
45
|
-
ssl: bool
|
|
46
|
-
Enable or disable ssl configuration.
|
|
47
|
-
Field is not required. Default: True (enable).
|
|
48
|
-
"""
|
|
49
|
-
def __init__(
|
|
50
|
-
self,
|
|
51
|
-
api_key:str,
|
|
52
|
-
stream_type:Optional[str] = REALTIME,
|
|
53
|
-
country:Optional[str] = BR,
|
|
54
|
-
ssl:Optional[bool] = True,
|
|
55
|
-
**kwargs,
|
|
56
|
-
):
|
|
57
|
-
self.api_key = api_key
|
|
58
|
-
self.ssl = ssl
|
|
59
|
-
|
|
60
|
-
self.__authenticator = Authenticator(self.api_key)
|
|
61
|
-
self.__nro_reconnect_retries = 0
|
|
62
|
-
|
|
63
|
-
if stream_type not in VALID_STREAM_TYPES:
|
|
64
|
-
raise FeedError(f"Must provide a valid 'stream_type' parameter. Valid options are: {VALID_STREAM_TYPES}")
|
|
65
|
-
if country not in VALID_COUNTRIES:
|
|
66
|
-
raise FeedError(f"Must provide a valid 'country' parameter. Valid options are: {VALID_COUNTRIES}")
|
|
67
|
-
|
|
68
|
-
try:
|
|
69
|
-
self.url = hfn_socket_urls[country][stream_type]
|
|
70
|
-
except:
|
|
71
|
-
raise WSTypeError(f"There is no WebSocket type for your specifications (stream_type:{stream_type}, country:{country})\nPlease check your request parameters and try again")
|
|
72
|
-
|
|
73
|
-
self.websocket_cfg = kwargs
|
|
74
|
-
|
|
75
|
-
def run(
|
|
76
|
-
self,
|
|
77
|
-
on_open = None,
|
|
78
|
-
on_message = None,
|
|
79
|
-
on_error = None,
|
|
80
|
-
on_close = None,
|
|
81
|
-
reconnect=True
|
|
82
|
-
):
|
|
83
|
-
"""
|
|
84
|
-
Initializes a connection to websocket and starts to receive high frequency news.
|
|
85
|
-
|
|
86
|
-
Parameters
|
|
87
|
-
----------
|
|
88
|
-
on_open: function
|
|
89
|
-
- Called at opening connection to websocket.
|
|
90
|
-
- Field is not required.
|
|
91
|
-
- Default: prints that the connection was opened in case of success.
|
|
92
|
-
|
|
93
|
-
on_message: function
|
|
94
|
-
- Called every time it receives a message.
|
|
95
|
-
- Arguments:
|
|
96
|
-
1. Data received from the server.
|
|
97
|
-
- Field is not required.
|
|
98
|
-
- Default: prints the data.
|
|
99
|
-
|
|
100
|
-
on_error: function
|
|
101
|
-
- Called when a error occurs.
|
|
102
|
-
- Arguments:
|
|
103
|
-
1. Exception object.
|
|
104
|
-
- Field is not required.
|
|
105
|
-
- Default: prints the error.
|
|
106
|
-
|
|
107
|
-
on_close: function
|
|
108
|
-
- Called when connection is closed.
|
|
109
|
-
- Arguments:
|
|
110
|
-
1. close_status_code.
|
|
111
|
-
2. close_msg.
|
|
112
|
-
- Field is not required.
|
|
113
|
-
- Default: prints a message that the connection was closed.
|
|
114
|
-
reconnect: bool
|
|
115
|
-
Try reconnect if connection is closed.
|
|
116
|
-
Field is not required.
|
|
117
|
-
Default: True.
|
|
118
|
-
"""
|
|
119
|
-
if on_open is None:
|
|
120
|
-
on_open = _on_open
|
|
121
|
-
if on_message is None:
|
|
122
|
-
on_message = _on_message
|
|
123
|
-
if on_error is None:
|
|
124
|
-
on_error = _on_error
|
|
125
|
-
if on_close is None:
|
|
126
|
-
on_close = _on_close
|
|
127
|
-
|
|
128
|
-
def intermediary_on_open(ws):
|
|
129
|
-
on_open()
|
|
130
|
-
self.__nro_reconnect_retries = 0
|
|
131
|
-
|
|
132
|
-
def intermediary_on_message(ws, data):
|
|
133
|
-
on_message(data)
|
|
134
|
-
|
|
135
|
-
def intermediary_on_error(ws, error):
|
|
136
|
-
on_error(error)
|
|
137
|
-
|
|
138
|
-
def intermediary_on_close(ws, close_status_code, close_msg):
|
|
139
|
-
on_close(close_status_code, close_msg)
|
|
140
|
-
|
|
141
|
-
if reconnect:
|
|
142
|
-
if self.__nro_reconnect_retries == MAX_WS_RECONNECT_RETRIES:
|
|
143
|
-
print(f"### Fail retriyng reconnect")
|
|
144
|
-
return
|
|
145
|
-
self.__nro_reconnect_retries +=1
|
|
146
|
-
print(f"### Reconnecting.... Attempts: {self.__nro_reconnect_retries}/{MAX_WS_RECONNECT_RETRIES}")
|
|
147
|
-
self.run(on_open, on_message, on_error, on_close, reconnect)
|
|
148
|
-
|
|
149
|
-
self.ws = websocket.WebSocketApp(
|
|
150
|
-
url=self.url,
|
|
151
|
-
on_open=intermediary_on_open,
|
|
152
|
-
on_message=intermediary_on_message,
|
|
153
|
-
on_error=intermediary_on_error,
|
|
154
|
-
on_close=intermediary_on_close,
|
|
155
|
-
header={
|
|
156
|
-
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36",
|
|
157
|
-
"Sec-WebSocket-Protocol": self.__authenticator.token,
|
|
158
|
-
}
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
ssl_conf = {} if self.ssl else {"sslopt": {"cert_reqs": ssl.CERT_NONE}}
|
|
162
|
-
wst = threading.Thread(target=self.ws.run_forever, kwargs=ssl_conf)
|
|
163
|
-
wst.daemon = True
|
|
164
|
-
wst.start()
|
|
165
|
-
|
|
166
|
-
while True:
|
|
167
|
-
if self.ws.sock is not None and self.ws.sock.connected:
|
|
168
|
-
break
|
|
169
|
-
pass
|
|
170
|
-
|
|
171
|
-
def __send(self, data):
|
|
172
|
-
"""
|
|
173
|
-
Class method to be used internally. Sends data to websocket.
|
|
174
|
-
"""
|
|
175
|
-
if not isinstance(data, str):
|
|
176
|
-
data = json.dumps(data)
|
|
177
|
-
print(f'Sending data: {data}')
|
|
178
|
-
return self.ws.send(data)
|
|
179
|
-
|
|
180
|
-
def close(self):
|
|
181
|
-
"""
|
|
182
|
-
Closes connection with websocket.
|
|
183
|
-
"""
|
|
184
|
-
self.ws.close()
|
|
185
|
-
|
|
186
|
-
def get_latest_news(self):
|
|
187
|
-
"""
|
|
188
|
-
Get the latest news from our High Frequency News service.
|
|
189
|
-
|
|
190
|
-
"""
|
|
191
|
-
self.__send({'action':'latest_news'})
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|