btgsolutions-dataservices-python-client 3.2.7__tar.gz → 3.2.9__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 (39) hide show
  1. {btgsolutions_dataservices_python_client-3.2.7/btgsolutions_dataservices_python_client.egg-info → btgsolutions_dataservices_python_client-3.2.9}/PKG-INFO +55 -4
  2. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/README.md +53 -2
  3. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/__init__.py +1 -1
  4. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/config.py +6 -0
  5. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/rest/__init__.py +1 -0
  6. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/rest/historical_candles.py +18 -4
  7. btgsolutions_dataservices_python_client-3.2.9/btgsolutions_dataservices/rest/historical_candles_crypto.py +177 -0
  8. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/rest/quotes.py +4 -4
  9. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/websocket/__init__.py +2 -1
  10. btgsolutions_dataservices_python_client-3.2.9/btgsolutions_dataservices/websocket/broker_analytics.py +300 -0
  11. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9/btgsolutions_dataservices_python_client.egg-info}/PKG-INFO +55 -4
  12. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices_python_client.egg-info/SOURCES.txt +2 -0
  13. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/setup.py +1 -1
  14. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/LICENSE +0 -0
  15. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/MANIFEST.in +0 -0
  16. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/exceptions.py +0 -0
  17. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/rest/authenticator.py +0 -0
  18. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/rest/broker_reference.py +0 -0
  19. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/rest/bulk_data.py +0 -0
  20. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/rest/company_data.py +0 -0
  21. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/rest/corporate_events.py +0 -0
  22. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/rest/hfn.py +0 -0
  23. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/rest/intraday_candles.py +0 -0
  24. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/rest/intraday_tick_data.py +0 -0
  25. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/rest/public_sources.py +0 -0
  26. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/rest/reference_data.py +0 -0
  27. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/rest/stock_loan.py +0 -0
  28. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/rest/ticker_last_event.py +0 -0
  29. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/rest/ticker_last_event_polling.py +0 -0
  30. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/websocket/hfn_websocket_client.py +0 -0
  31. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/websocket/market_data_feed.py +0 -0
  32. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/websocket/market_data_websocket_client.py +0 -0
  33. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices/websocket/websocket_default_functions.py +0 -0
  34. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices_python_client.egg-info/dependency_links.txt +0 -0
  35. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices_python_client.egg-info/requires.txt +0 -0
  36. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/btgsolutions_dataservices_python_client.egg-info/top_level.txt +0 -0
  37. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/pyproject.toml +0 -0
  38. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/requirements.txt +0 -0
  39. {btgsolutions_dataservices_python_client-3.2.7 → btgsolutions_dataservices_python_client-3.2.9}/setup.cfg +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: btgsolutions_dataservices_python_client
3
- Version: 3.2.7
3
+ Version: 3.2.9
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
7
- Requires-Python: >=3.9,<3.14
7
+ Requires-Python: >=3.9,<3.15
8
8
  Description-Content-Type: text/markdown
9
9
  License-File: LICENSE
10
10
  Requires-Dist: pandas>=2.2.2
@@ -179,6 +179,31 @@ ws.run(on_message=lambda message: print(message))
179
179
  # sleep(1)
180
180
  ```
181
181
 
182
+ ##### Broker Analytics
183
+
184
+ ```python
185
+ import btgsolutions_dataservices as btg
186
+
187
+ ws = btg.BrokerAnalyticsWebSocketClient(api_key='YOUR_API_KEY')
188
+ ws.run(on_message=lambda message: print(message))
189
+
190
+ ws.available_tickers()
191
+ ws.available_brokers()
192
+ ws.subscribe_top_tickers(n=10, brokers=['85'])
193
+ ws.subscribe_top_brokers(n=5, tickers=['SNFF11'])
194
+ ws.subscribed_to()
195
+ ws.get_last_event(analytics_type='top_tickers', n=3, brokers=['85', '3'])
196
+ ws.get_last_event(analytics_type='top_brokers', n=100, tickers=['SNFF11'])
197
+ ws.get_last_event()
198
+ ws.unsubscribe_top_tickers(brokers=['85'])
199
+ ws.unsubscribe_top_brokers(tickers=['SNFF11'])
200
+
201
+ ## The following is optional to keep the program running in a .py file:
202
+ # from time import sleep
203
+ # while True:
204
+ # sleep(1)
205
+ ```
206
+
182
207
  #### Intraday Candles
183
208
 
184
209
  ```python
@@ -245,7 +270,7 @@ last_event.get()
245
270
  ```python
246
271
  import btgsolutions_dataservices as btg
247
272
  hist_candles = btg.HistoricalCandles(api_key='YOUR_API_KEY')
248
- hist_candles.get_interday_history_candles(ticker='PETR4', market_type='stocks', corporate_events_adj=True, start_date='2023-10-01', end_date='2023-10-13', rmv_after_market=True, timezone='UTC', raw_data=False)
273
+ hist_candles.get_interday_history_candles(ticker='PETR4', market_type='stocks', corporate_events_adj=True, start_date='2023-10-01', end_date='2023-10-13', rmv_after_market=True, timezone='UTC', raw_data=False, round=False)
249
274
  ```
250
275
 
251
276
  ##### Intraday
@@ -253,7 +278,7 @@ hist_candles.get_interday_history_candles(ticker='PETR4', market_type='stocks',
253
278
  ```python
254
279
  import btgsolutions_dataservices as btg
255
280
  hist_candles = btg.HistoricalCandles(api_key='YOUR_API_KEY')
256
- hist_candles.get_intraday_history_candles(ticker='PETR4', market_type='stocks', corporate_events_adj=True, date='2023-10-06', candle='1m', rmv_after_market=True, timezone='UTC', raw_data=False)
281
+ hist_candles.get_intraday_history_candles(ticker='PETR4', market_type='stocks', corporate_events_adj=True, date='2023-10-06', candle='1m', rmv_after_market=True, timezone='UTC', raw_data=False, round=True)
257
282
  ```
258
283
 
259
284
  ##### Available Tickers
@@ -272,6 +297,32 @@ hist_candles = btg.HistoricalCandles(api_key='YOUR_API_KEY')
272
297
  hist_candles.get_intraday_history_candles(ticker='PETR4', market_type='stocks', corporate_events_adj=True, date='2023-10-06', candle='1m', rmv_after_market=True, timezone='UTC', raw_data=False).plot(x='candle_time', y='close_price', kind='scatter')
273
298
  ```
274
299
 
300
+ #### Historical Candles Crypto
301
+
302
+ ##### Interday
303
+
304
+ ```python
305
+ import btgsolutions_dataservices as btg
306
+ hist_candles_crypto = btg.HistoricalCandlesCrypto(api_key='YOUR_API_KEY')
307
+ hist_candles_crypto.get_interday_history_candles(ticker='BTC', currency='BRL', exchange='consolidated', start_date='2025-06-01', end_date='2025-07-01', timezone='UTC', raw_data=False)
308
+ ```
309
+
310
+ ##### Intraday
311
+
312
+ ```python
313
+ import btgsolutions_dataservices as btg
314
+ hist_candles_crypto = btg.HistoricalCandlesCrypto(api_key='YOUR_API_KEY')
315
+ hist_candles_crypto.get_intraday_history_candles(ticker='BTC', currency='BRL', exchange='consolidated', date='2025-06-01', candle='1h', timezone='America/Sao_Paulo', raw_data=False)
316
+ ```
317
+
318
+ ##### Available Tickers
319
+
320
+ ```python
321
+ import btgsolutions_dataservices as btg
322
+ hist_candles_crypto = btg.HistoricalCandlesCrypto(api_key='YOUR_API_KEY')
323
+ hist_candles_crypto.get_available_tickers(exchange='coinbase', date='2023-01-13')
324
+ ```
325
+
275
326
  #### Historical Tick Data (Bulk Data)
276
327
 
277
328
  ##### Available Tickers
@@ -156,6 +156,31 @@ ws.run(on_message=lambda message: print(message))
156
156
  # sleep(1)
157
157
  ```
158
158
 
159
+ ##### Broker Analytics
160
+
161
+ ```python
162
+ import btgsolutions_dataservices as btg
163
+
164
+ ws = btg.BrokerAnalyticsWebSocketClient(api_key='YOUR_API_KEY')
165
+ ws.run(on_message=lambda message: print(message))
166
+
167
+ ws.available_tickers()
168
+ ws.available_brokers()
169
+ ws.subscribe_top_tickers(n=10, brokers=['85'])
170
+ ws.subscribe_top_brokers(n=5, tickers=['SNFF11'])
171
+ ws.subscribed_to()
172
+ ws.get_last_event(analytics_type='top_tickers', n=3, brokers=['85', '3'])
173
+ ws.get_last_event(analytics_type='top_brokers', n=100, tickers=['SNFF11'])
174
+ ws.get_last_event()
175
+ ws.unsubscribe_top_tickers(brokers=['85'])
176
+ ws.unsubscribe_top_brokers(tickers=['SNFF11'])
177
+
178
+ ## The following is optional to keep the program running in a .py file:
179
+ # from time import sleep
180
+ # while True:
181
+ # sleep(1)
182
+ ```
183
+
159
184
  #### Intraday Candles
160
185
 
161
186
  ```python
@@ -222,7 +247,7 @@ last_event.get()
222
247
  ```python
223
248
  import btgsolutions_dataservices as btg
224
249
  hist_candles = btg.HistoricalCandles(api_key='YOUR_API_KEY')
225
- hist_candles.get_interday_history_candles(ticker='PETR4', market_type='stocks', corporate_events_adj=True, start_date='2023-10-01', end_date='2023-10-13', rmv_after_market=True, timezone='UTC', raw_data=False)
250
+ hist_candles.get_interday_history_candles(ticker='PETR4', market_type='stocks', corporate_events_adj=True, start_date='2023-10-01', end_date='2023-10-13', rmv_after_market=True, timezone='UTC', raw_data=False, round=False)
226
251
  ```
227
252
 
228
253
  ##### Intraday
@@ -230,7 +255,7 @@ hist_candles.get_interday_history_candles(ticker='PETR4', market_type='stocks',
230
255
  ```python
231
256
  import btgsolutions_dataservices as btg
232
257
  hist_candles = btg.HistoricalCandles(api_key='YOUR_API_KEY')
233
- hist_candles.get_intraday_history_candles(ticker='PETR4', market_type='stocks', corporate_events_adj=True, date='2023-10-06', candle='1m', rmv_after_market=True, timezone='UTC', raw_data=False)
258
+ hist_candles.get_intraday_history_candles(ticker='PETR4', market_type='stocks', corporate_events_adj=True, date='2023-10-06', candle='1m', rmv_after_market=True, timezone='UTC', raw_data=False, round=True)
234
259
  ```
235
260
 
236
261
  ##### Available Tickers
@@ -249,6 +274,32 @@ hist_candles = btg.HistoricalCandles(api_key='YOUR_API_KEY')
249
274
  hist_candles.get_intraday_history_candles(ticker='PETR4', market_type='stocks', corporate_events_adj=True, date='2023-10-06', candle='1m', rmv_after_market=True, timezone='UTC', raw_data=False).plot(x='candle_time', y='close_price', kind='scatter')
250
275
  ```
251
276
 
277
+ #### Historical Candles Crypto
278
+
279
+ ##### Interday
280
+
281
+ ```python
282
+ import btgsolutions_dataservices as btg
283
+ hist_candles_crypto = btg.HistoricalCandlesCrypto(api_key='YOUR_API_KEY')
284
+ hist_candles_crypto.get_interday_history_candles(ticker='BTC', currency='BRL', exchange='consolidated', start_date='2025-06-01', end_date='2025-07-01', timezone='UTC', raw_data=False)
285
+ ```
286
+
287
+ ##### Intraday
288
+
289
+ ```python
290
+ import btgsolutions_dataservices as btg
291
+ hist_candles_crypto = btg.HistoricalCandlesCrypto(api_key='YOUR_API_KEY')
292
+ hist_candles_crypto.get_intraday_history_candles(ticker='BTC', currency='BRL', exchange='consolidated', date='2025-06-01', candle='1h', timezone='America/Sao_Paulo', raw_data=False)
293
+ ```
294
+
295
+ ##### Available Tickers
296
+
297
+ ```python
298
+ import btgsolutions_dataservices as btg
299
+ hist_candles_crypto = btg.HistoricalCandlesCrypto(api_key='YOUR_API_KEY')
300
+ hist_candles_crypto.get_available_tickers(exchange='coinbase', date='2023-01-13')
301
+ ```
302
+
252
303
  #### Historical Tick Data (Bulk Data)
253
304
 
254
305
  ##### Available Tickers
@@ -1,4 +1,4 @@
1
- __version__ = "3.2.7"
1
+ __version__ = "3.2.9"
2
2
 
3
3
  from .websocket import *
4
4
  from .rest import *
@@ -136,3 +136,9 @@ hfn_socket_urls = {
136
136
  REALTIME: f'{url_ws}v2/hfn/{CL}',
137
137
  },
138
138
  }
139
+
140
+ broker_analytics_socket_urls = {
141
+ BR: {
142
+ REALTIME: f'{base_url_ws}{ws_br_b3_base_path}broker-analytics',
143
+ }
144
+ }
@@ -1,5 +1,6 @@
1
1
  from .intraday_candles import IntradayCandles
2
2
  from .historical_candles import HistoricalCandles
3
+ from .historical_candles_crypto import HistoricalCandlesCrypto
3
4
  from .authenticator import Authenticator
4
5
  from .bulk_data import BulkData
5
6
  from .hfn import HighFrequencyNews
@@ -24,6 +24,7 @@ class HistoricalCandles:
24
24
  >>> end_date = '2023-10-20',
25
25
  >>> rmv_after_market = True,
26
26
  >>> timezone = 'UTC',
27
+ >>> round = True,
27
28
  >>> raw_data = False
28
29
  >>> )
29
30
 
@@ -37,6 +38,7 @@ class HistoricalCandles:
37
38
  >>> rmv_after_market = True,
38
39
  >>> timezone = 'UTC',
39
40
  >>> candle='1m',
41
+ >>> round = True,
40
42
  >>> raw_data = False
41
43
  >>> )
42
44
 
@@ -63,7 +65,8 @@ class HistoricalCandles:
63
65
  corporate_events_adj:bool,
64
66
  rmv_after_market:bool,
65
67
  timezone:str,
66
- raw_data:bool=False
68
+ raw_data:bool=False,
69
+ round:bool=True
67
70
  ):
68
71
  """
69
72
  This method provides historical candles for a given ticket in determined period.
@@ -93,12 +96,17 @@ class HistoricalCandles:
93
96
  raw_data: bool
94
97
  If false, returns data in a dataframe. If true, returns raw data.
95
98
  Field is not required. Default: False.
99
+ round: bool
100
+ Apply rounding to prices.
101
+ Useful when corporate_events_adj=True, since price adjustment factors
102
+ may generate values with many decimal places.
103
+ Field is not required. Default: True.
96
104
  """
97
105
 
98
106
  if market_type not in ['stocks', 'derivatives']:
99
107
  raise MarketTypeError(f'Allowed values: "stocks" or "derivatives". Input value: "{market_type}".')
100
108
 
101
- url = f"{url_apis_v3}/marketdata/history/candles/intraday/{market_type}?ticker={ticker}&corporate_events_adj={corporate_events_adj}&rmv_after_market={rmv_after_market}&timezone={timezone}&date={date}&candle={candle}"
109
+ url = f"{url_apis_v3}/marketdata/history/candles/intraday/{market_type}?ticker={ticker}&corporate_events_adj={corporate_events_adj}&rmv_after_market={rmv_after_market}&timezone={timezone}&date={date}&candle={candle}&round={round}"
102
110
  response = requests.request("GET", url, headers=self.headers)
103
111
  if response.status_code == 200:
104
112
  response_data = json.loads(response.text)
@@ -116,7 +124,8 @@ class HistoricalCandles:
116
124
  corporate_events_adj:bool,
117
125
  rmv_after_market:bool,
118
126
  timezone:str,
119
- raw_data:bool=False
127
+ raw_data:bool=False,
128
+ round:bool=True
120
129
  ):
121
130
  """
122
131
  This method provides historical candles for a given ticket in determined period.
@@ -146,12 +155,17 @@ class HistoricalCandles:
146
155
  raw_data: bool
147
156
  If false, returns data in a dataframe. If true, returns raw data.
148
157
  Field is not required. Default: False.
158
+ round: bool
159
+ Apply rounding to prices.
160
+ Useful when corporate_events_adj=True, since price adjustment factors
161
+ may generate values with many decimal places.
162
+ Field is not required. Default: True.
149
163
  """
150
164
 
151
165
  if market_type not in ['stocks', 'derivatives']:
152
166
  raise MarketTypeError(f'Allowed values: "stocks" or "derivatives". Input value: "{market_type}".')
153
167
 
154
- url = f"{url_apis_v3}/marketdata/history/candles/interday/{market_type}?ticker={ticker}&corporate_events_adj={corporate_events_adj}&rmv_after_market={rmv_after_market}&timezone={timezone}&start_date={start_date}&end_date={end_date}"
168
+ url = f"{url_apis_v3}/marketdata/history/candles/interday/{market_type}?ticker={ticker}&corporate_events_adj={corporate_events_adj}&rmv_after_market={rmv_after_market}&timezone={timezone}&start_date={start_date}&end_date={end_date}&round={round}"
155
169
  response = requests.request("GET", url, headers=self.headers)
156
170
  if response.status_code == 200:
157
171
  response_data = json.loads(response.text)
@@ -0,0 +1,177 @@
1
+ from typing import Optional
2
+ from ..exceptions import BadResponse, MarketTypeError
3
+ import requests
4
+ from ..config import url_apis_v3
5
+ from .authenticator import Authenticator
6
+ import json
7
+ import pandas as pd
8
+
9
+ class HistoricalCandlesCrypto:
10
+ """
11
+ This class provides historical candles for cryptocurrencies.
12
+
13
+ Available tickers: ETH, SOL, BTC
14
+ Available exchanges: coinbase, mercado_bitcoin, consolidated
15
+ Available currencies: BRL, USD
16
+ Available candles: '1s', '30s', '1m', '5m', '15m', '30m', '1h'
17
+
18
+ * Main use case - Interday:
19
+
20
+ >>> from btgsolutions_dataservices import HistoricalCandlesCrypto
21
+ >>> hist_candles = HistoricalCandlesCrypto(
22
+ >>> api_key='YOUR_API_KEY',
23
+ >>> )
24
+ >>> hist_candles.get_interday_history_candles(
25
+ >>> ticker = 'BTC',
26
+ >>> currency = 'BRL',
27
+ >>> exchange = 'consolidated',
28
+ >>> start_date = '2025-06-01',
29
+ >>> end_date = '2025-07-01',
30
+ >>> timezone = 'UTC',
31
+ >>> raw_data = False
32
+ >>> )
33
+
34
+ * Main use case - Intraday:
35
+
36
+ >>> hist_candles.get_intraday_history_candles(
37
+ >>> ticker = 'BTC',
38
+ >>> currency = 'BRL',
39
+ >>> exchange = 'consolidated',
40
+ >>> date = '2025-06-01',
41
+ >>> timezone = 'America/Sao_Paulo',
42
+ >>> candle='1h',
43
+ >>> raw_data = False
44
+ >>> )
45
+
46
+ Parameters
47
+ ----------------
48
+ api_key: str
49
+ User identification key.
50
+ Field is required.
51
+ """
52
+ def __init__(
53
+ self,
54
+ api_key:Optional[str]
55
+ ):
56
+ self.api_key = api_key
57
+ self.token = Authenticator(self.api_key).token
58
+ self.headers = {"authorization": f"authorization {self.token}"}
59
+
60
+ def get_intraday_history_candles(
61
+ self,
62
+ ticker:str,
63
+ currency:str,
64
+ exchange:str,
65
+ date:str,
66
+ candle:str,
67
+ timezone:str,
68
+ raw_data:bool=False
69
+ ):
70
+ """
71
+ This method provides historical intraday candles for cryptocurrencies.
72
+
73
+ Parameters
74
+ ----------------
75
+ ticker: str
76
+ Cryptocurrency ticker.
77
+ Field is required. Allowed values: 'BTC', 'ETH', 'SOL'.
78
+ currency: str
79
+ Currency for the prices.
80
+ Field is required. Allowed values: 'BRL' or 'USD'.
81
+ exchange: str
82
+ Exchange name.
83
+ Field is required. Allowed values: 'coinbase', 'mercado_bitcoin', 'consolidated'.
84
+ date: string<date>
85
+ Date of requested data. Format: "YYYY-MM-DD".
86
+ Field is required. Example: '2025-06-01'.
87
+ candle: str
88
+ Candle period.
89
+ Field is required. Allowed values: '1s', '30s', '1m', '5m', '15m', '30m', '1h'.
90
+ timezone: str
91
+ Timezone of the datetime.
92
+ Field is required. Allowed values: 'America/Sao_Paulo' or 'UTC'.
93
+ raw_data: bool
94
+ If false, returns data in a dataframe. If true, returns raw data.
95
+ Field is not required. Default: False.
96
+ """
97
+
98
+ url = f"{url_apis_v3}/marketdata/history/candles/intraday/crypto?ticker={ticker}&currency={currency}&exchange={exchange}&date={date}&candle={candle}&timezone={timezone}"
99
+ response = requests.request("GET", url, headers=self.headers)
100
+ if response.status_code == 200:
101
+ response_data = json.loads(response.text)
102
+ return response_data if raw_data else pd.DataFrame(response_data)
103
+
104
+ response = json.loads(response.text)
105
+ raise BadResponse(f'Error: {response.get("ApiClientError", "")}.\n{response.get("SuggestedAction", "")}')
106
+
107
+ def get_interday_history_candles(
108
+ self,
109
+ ticker:str,
110
+ currency:str,
111
+ exchange:str,
112
+ start_date:str,
113
+ end_date:str,
114
+ timezone:str,
115
+ raw_data:bool=False
116
+ ):
117
+ """
118
+ This method provides historical daily candles for cryptocurrencies.
119
+
120
+ Parameters
121
+ ----------------
122
+ ticker: str
123
+ Cryptocurrency ticker.
124
+ Field is required. Allowed values: 'BTC', 'ETH', 'SOL'.
125
+ currency: str
126
+ Currency for the prices.
127
+ Field is required. Allowed values: 'BRL' or 'USD'.
128
+ exchange: str
129
+ Exchange name.
130
+ Field is required. Allowed values: 'coinbase', 'mercado_bitcoin', 'consolidated'.
131
+ start_date: string<date>
132
+ Start date of analysis. Format: "YYYY-MM-DD".
133
+ Field is required. Example: '2025-06-01'.
134
+ end_date: string<date>
135
+ End date of analysis. Format: "YYYY-MM-DD".
136
+ Field is required. Example: '2025-07-01'.
137
+ timezone: str
138
+ Timezone of the datetime.
139
+ Field is required. Allowed values: 'America/Sao_Paulo' or 'UTC'.
140
+ raw_data: bool
141
+ If false, returns data in a dataframe. If true, returns raw data.
142
+ Field is not required. Default: False.
143
+ """
144
+
145
+ url = f"{url_apis_v3}/marketdata/history/candles/interday/crypto?ticker={ticker}&currency={currency}&exchange={exchange}&start_date={start_date}&end_date={end_date}&timezone={timezone}"
146
+ response = requests.request("GET", url, headers=self.headers)
147
+ if response.status_code == 200:
148
+ response_data = json.loads(response.text)
149
+ return response_data if raw_data else pd.DataFrame(response_data)
150
+
151
+ response = json.loads(response.text)
152
+ raise BadResponse(f'Error: {response.get("ApiClientError", "")}.\n{response.get("SuggestedAction", "")}')
153
+
154
+ def get_available_tickers(
155
+ self,
156
+ exchange:str,
157
+ date:str,
158
+ ):
159
+ """
160
+ This method provides all cryptocurrency tickers available for query.
161
+
162
+ Parameters
163
+ ----------------
164
+ exchange: str
165
+ Exchange name.
166
+ Field is required. Allowed values: 'coinbase', 'mercado_bitcoin', 'consolidated'.
167
+ date: string<date>
168
+ Date of requested data. Format: "YYYY-MM-DD".
169
+ Field is required. Example: '2023-01-13'.
170
+ """
171
+
172
+ url = f"{url_apis_v3}/marketdata/history/candles/available-tickers/crypto?date={date}&exchange={exchange}"
173
+
174
+ response = requests.request("GET", url, headers=self.headers)
175
+ if response.status_code == 200: return response.json()
176
+ response = response.json()
177
+ raise BadResponse(f'Error: {response.get("ApiClientError", "") or response.get("ApiServerMessage", "")}.\n{response.get("SuggestedAction", "")}')
@@ -43,7 +43,7 @@ class Quotes:
43
43
  self.token = Authenticator(self.api_key).token
44
44
  self.headers = {"authorization": f"authorization {self.token}"}
45
45
 
46
- self.available_market_types = ['stocks', 'options', 'derivatives']
46
+ self.available_market_types = ['stocks', 'options', 'derivatives', 'indices']
47
47
  self.available_modes = ['realtime', 'delayed']
48
48
  self.available_variations = ['intraday', 'interday']
49
49
 
@@ -64,7 +64,7 @@ class Quotes:
64
64
  Field is required. Example: ['VALE3'], ['PETR4', 'PRIO3'].
65
65
  market_type: str
66
66
  Market type.
67
- Field is required. Example: 'stocks', 'options', 'derivatives'.
67
+ Field is required. Example: 'stocks', 'options', 'derivatives', 'indices'.
68
68
  mode: str
69
69
  Realtime or 15-minutes delayed.
70
70
  Field is required. Example: 'realtime' or 'delayed'.
@@ -111,7 +111,7 @@ class Quotes:
111
111
  ----------------
112
112
  market_type: str
113
113
  Market type.
114
- Field is required. Example: 'stocks', 'options', 'derivatives'.
114
+ Field is required. Example: 'stocks', 'options', 'derivatives', 'indices'.
115
115
  mode: str
116
116
  Realtime or 15-minutes delayed.
117
117
  Field is not required. Example: 'realtime' or 'delayed'.
@@ -172,7 +172,7 @@ class Quotes:
172
172
  ----------------
173
173
  market_type: str
174
174
  Market type.
175
- Field is required. Example: 'stocks', 'options', 'derivatives'.
175
+ Field is required. Example: 'stocks', 'options', 'derivatives', 'indices'.
176
176
  mode: str
177
177
  Realtime or 15-minutes delayed.
178
178
  Field is not required. Example: 'realtime' or 'delayed'.
@@ -1,3 +1,4 @@
1
1
  from .market_data_websocket_client import MarketDataWebSocketClient
2
2
  from .hfn_websocket_client import HFNWebSocketClient
3
- from .market_data_feed import MarketDataFeed
3
+ from .market_data_feed import MarketDataFeed
4
+ from .broker_analytics import BrokerAnalyticsWebSocketClient
@@ -0,0 +1,300 @@
1
+ from typing import Optional, List
2
+ from ..exceptions import WSTypeError
3
+ from ..rest import Authenticator
4
+ from ..config import broker_analytics_socket_urls, MAX_WS_RECONNECT_RETRIES, REALTIME, BR
5
+ from .websocket_default_functions import _on_open, _on_message, _on_error, _on_close
6
+ import websocket
7
+ import json
8
+ import ssl
9
+ import threading
10
+
11
+
12
+ class BrokerAnalyticsWebSocketClient:
13
+ """
14
+ This class connects with BTG Solutions Data Services Broker Analytics WebSocket,
15
+ receiving broker analytics events (top tickers by broker and top brokers by ticker).
16
+
17
+ * Main use case:
18
+
19
+ >>> from btgsolutions_dataservices import BrokerAnalyticsWebSocketClient
20
+ >>> ws = BrokerAnalyticsWebSocketClient(
21
+ >>> api_key='YOUR_API_KEY',
22
+ >>> ssl=True
23
+ >>> )
24
+ >>> ws.run()
25
+ >>> ws.available_tickers()
26
+ >>> ws.available_brokers()
27
+ >>> ws.subscribe_top_tickers(n=10, brokers=['85'])
28
+ >>> ws.subscribe_top_brokers(n=5)
29
+ >>> ws.subscribed_to()
30
+ >>> ws.get_last_event(analytics_type='top_tickers', n=3, brokers=['85', '3'])
31
+ >>> ws.get_last_event(analytics_type='top_brokers', n=5)
32
+ >>> ws.unsubscribe_top_tickers(brokers=['85'])
33
+ >>> ws.unsubscribe_top_brokers()
34
+ >>> ws.close()
35
+
36
+ Parameters
37
+ ----------------
38
+ api_key: str
39
+ User identification key.
40
+ Field is required.
41
+
42
+ ssl: bool
43
+ Enable or disable ssl configuration.
44
+ Field is not required. Default: True (enable).
45
+ """
46
+
47
+ def __init__(
48
+ self,
49
+ api_key: str,
50
+ ssl: Optional[bool] = True,
51
+ **kwargs,
52
+ ):
53
+ self.api_key = api_key
54
+ self.ssl = ssl
55
+
56
+ self.__authenticator = Authenticator(self.api_key)
57
+ self.__nro_reconnect_retries = 0
58
+
59
+ try:
60
+ self.url = broker_analytics_socket_urls[BR][REALTIME]
61
+ except Exception:
62
+ raise WSTypeError(
63
+ "There is no WebSocket type for Broker Analytics (brazil/realtime).\nPlease check your request parameters and try again"
64
+ )
65
+
66
+ self.websocket_cfg = kwargs
67
+
68
+ def run(
69
+ self,
70
+ on_open=None,
71
+ on_message=None,
72
+ on_error=None,
73
+ on_close=None,
74
+ reconnect=True
75
+ ):
76
+ """
77
+ Initializes a connection to websocket and starts to receive Broker Analytics events.
78
+
79
+ Parameters
80
+ ----------
81
+ on_open: function
82
+ - Called at opening connection to websocket.
83
+ - Field is not required.
84
+ - Default: prints that the connection was opened in case of success.
85
+
86
+ on_message: function
87
+ - Called every time it receives a message.
88
+ - Arguments:
89
+ 1. Data received from the server.
90
+ - Field is not required.
91
+ - Default: prints the data.
92
+
93
+ on_error: function
94
+ - Called when a error occurs.
95
+ - Arguments:
96
+ 1. Exception object.
97
+ - Field is not required.
98
+ - Default: prints the error.
99
+
100
+ on_close: function
101
+ - Called when connection is closed.
102
+ - Arguments:
103
+ 1. close_status_code.
104
+ 2. close_msg.
105
+ - Field is not required.
106
+ - Default: prints a message that the connection was closed.
107
+
108
+ reconnect: bool
109
+ Try reconnect if connection is closed.
110
+ Field is not required.
111
+ Default: True.
112
+ """
113
+ if on_open is None:
114
+ on_open = _on_open
115
+ if on_message is None:
116
+ on_message = _on_message
117
+ if on_error is None:
118
+ on_error = _on_error
119
+ if on_close is None:
120
+ on_close = _on_close
121
+
122
+ def intermediary_on_open(ws):
123
+ on_open()
124
+ self.__nro_reconnect_retries = 0
125
+
126
+ def intermediary_on_message(ws, data):
127
+ on_message(data)
128
+
129
+ def intermediary_on_error(ws, error):
130
+ on_error(error)
131
+
132
+ def intermediary_on_close(ws, close_status_code, close_msg):
133
+ on_close(close_status_code, close_msg)
134
+
135
+ if reconnect:
136
+ if self.__nro_reconnect_retries == MAX_WS_RECONNECT_RETRIES:
137
+ print("### Fail retriyng reconnect")
138
+ return
139
+ self.__nro_reconnect_retries += 1
140
+ print(f"### Reconnecting.... Attempts: {self.__nro_reconnect_retries}/{MAX_WS_RECONNECT_RETRIES}")
141
+ self.run(on_open, on_message, on_error, on_close, reconnect)
142
+
143
+ self.ws = websocket.WebSocketApp(
144
+ url=self.url,
145
+ on_open=intermediary_on_open,
146
+ on_message=intermediary_on_message,
147
+ on_error=intermediary_on_error,
148
+ on_close=intermediary_on_close,
149
+ header={
150
+ "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",
151
+ "Sec-WebSocket-Protocol": self.__authenticator.token,
152
+ }
153
+ )
154
+
155
+ ssl_conf = {} if self.ssl else {"sslopt": {"cert_reqs": ssl.CERT_NONE}}
156
+ wst = threading.Thread(target=self.ws.run_forever, kwargs=ssl_conf)
157
+ wst.daemon = True
158
+ wst.start()
159
+
160
+ while True:
161
+ if self.ws.sock is not None and self.ws.sock.connected:
162
+ break
163
+ pass
164
+
165
+ def __send(self, data):
166
+ if not isinstance(data, str):
167
+ data = json.dumps(data)
168
+ print(f"Sending data: {data}")
169
+ return self.ws.send(data)
170
+
171
+ def close(self):
172
+ """
173
+ Closes connection with websocket.
174
+ """
175
+ self.ws.close()
176
+
177
+ def subscribe_top_tickers(self, n: int = 10, brokers: Optional[List[str]] = None):
178
+ """
179
+ Subscribes to top tickers by broker.
180
+
181
+ Parameters
182
+ ----------
183
+ n: int
184
+ Number of results.
185
+ Field is not required. Default: 10.
186
+
187
+ brokers: list
188
+ Broker ids filter.
189
+ Field is not required.
190
+ """
191
+ params = {'type': 'top_tickers', 'n': n}
192
+ if brokers is not None:
193
+ params['brokers'] = brokers
194
+ self.__send({'action': 'subscribe', 'params': params})
195
+
196
+ def subscribe_top_brokers(self, n: int = 5, tickers: Optional[List[str]] = None):
197
+ """
198
+ Subscribes to top brokers by ticker.
199
+
200
+ Parameters
201
+ ----------
202
+ n: int
203
+ Number of results.
204
+ Field is not required. Default: 5.
205
+ tickers: list
206
+ Ticker symbols filter.
207
+ Field is not required.
208
+ """
209
+ params = {'type': 'top_brokers', 'n': n}
210
+ if tickers is not None:
211
+ params['tickers'] = tickers
212
+ self.__send({'action': 'subscribe', 'params': params})
213
+
214
+ def unsubscribe_top_tickers(self, brokers: Optional[List[str]] = None):
215
+ """
216
+ Unsubscribes from top tickers by broker.
217
+
218
+ Parameters
219
+ ----------
220
+ brokers: list
221
+ Broker ids filter.
222
+ Field is not required.
223
+ """
224
+ params = {'type': 'top_tickers'}
225
+ if brokers is not None:
226
+ params['brokers'] = brokers
227
+ self.__send({'action': 'unsubscribe', 'params': params})
228
+
229
+ def unsubscribe_top_brokers(self, tickers: Optional[List[str]] = None):
230
+ """
231
+ Unsubscribes from top brokers by ticker.
232
+
233
+ Parameters
234
+ ----------
235
+ tickers: list
236
+ Ticker symbols filter.
237
+ Field is not required.
238
+ """
239
+ params = {'type': 'top_brokers'}
240
+ if tickers is not None:
241
+ params['tickers'] = tickers
242
+ self.__send({'action': 'unsubscribe', 'params': params})
243
+
244
+ def get_last_event(
245
+ self,
246
+ analytics_type: Optional[str] = None,
247
+ n: Optional[int] = None,
248
+ brokers: Optional[List[str]] = None,
249
+ tickers: Optional[List[str]] = None,
250
+ ):
251
+ """
252
+ Returns latest broker analytics event.
253
+
254
+ Parameters
255
+ ----------
256
+ analytics_type: str
257
+ Analytics type.
258
+ Options: 'top_tickers' or 'top_brokers'.
259
+ Field is not required.
260
+
261
+ n: int
262
+ Number of results.
263
+ Field is not required.
264
+
265
+ brokers: list
266
+ Broker ids filter.
267
+ Field is not required.
268
+ tickers: list
269
+ Ticker symbols filter.
270
+ Field is not required.
271
+ """
272
+ payload = {'action': 'get_last_event'}
273
+ if analytics_type is not None:
274
+ params = {'type': analytics_type}
275
+ if n is not None:
276
+ params['n'] = n
277
+ if brokers is not None:
278
+ params['brokers'] = brokers
279
+ if tickers is not None:
280
+ params['tickers'] = tickers
281
+ payload['params'] = params
282
+ self.__send(payload)
283
+
284
+ def subscribed_to(self):
285
+ """
286
+ Returns current subscriptions.
287
+ """
288
+ self.__send({'action': 'subscribed_to'})
289
+
290
+ def available_tickers(self):
291
+ """
292
+ Returns available tickers.
293
+ """
294
+ self.__send({'action': 'available_tickers'})
295
+
296
+ def available_brokers(self):
297
+ """
298
+ Returns available brokers.
299
+ """
300
+ self.__send({'action': 'available_brokers'})
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: btgsolutions_dataservices_python_client
3
- Version: 3.2.7
3
+ Version: 3.2.9
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
7
- Requires-Python: >=3.9,<3.14
7
+ Requires-Python: >=3.9,<3.15
8
8
  Description-Content-Type: text/markdown
9
9
  License-File: LICENSE
10
10
  Requires-Dist: pandas>=2.2.2
@@ -179,6 +179,31 @@ ws.run(on_message=lambda message: print(message))
179
179
  # sleep(1)
180
180
  ```
181
181
 
182
+ ##### Broker Analytics
183
+
184
+ ```python
185
+ import btgsolutions_dataservices as btg
186
+
187
+ ws = btg.BrokerAnalyticsWebSocketClient(api_key='YOUR_API_KEY')
188
+ ws.run(on_message=lambda message: print(message))
189
+
190
+ ws.available_tickers()
191
+ ws.available_brokers()
192
+ ws.subscribe_top_tickers(n=10, brokers=['85'])
193
+ ws.subscribe_top_brokers(n=5, tickers=['SNFF11'])
194
+ ws.subscribed_to()
195
+ ws.get_last_event(analytics_type='top_tickers', n=3, brokers=['85', '3'])
196
+ ws.get_last_event(analytics_type='top_brokers', n=100, tickers=['SNFF11'])
197
+ ws.get_last_event()
198
+ ws.unsubscribe_top_tickers(brokers=['85'])
199
+ ws.unsubscribe_top_brokers(tickers=['SNFF11'])
200
+
201
+ ## The following is optional to keep the program running in a .py file:
202
+ # from time import sleep
203
+ # while True:
204
+ # sleep(1)
205
+ ```
206
+
182
207
  #### Intraday Candles
183
208
 
184
209
  ```python
@@ -245,7 +270,7 @@ last_event.get()
245
270
  ```python
246
271
  import btgsolutions_dataservices as btg
247
272
  hist_candles = btg.HistoricalCandles(api_key='YOUR_API_KEY')
248
- hist_candles.get_interday_history_candles(ticker='PETR4', market_type='stocks', corporate_events_adj=True, start_date='2023-10-01', end_date='2023-10-13', rmv_after_market=True, timezone='UTC', raw_data=False)
273
+ hist_candles.get_interday_history_candles(ticker='PETR4', market_type='stocks', corporate_events_adj=True, start_date='2023-10-01', end_date='2023-10-13', rmv_after_market=True, timezone='UTC', raw_data=False, round=False)
249
274
  ```
250
275
 
251
276
  ##### Intraday
@@ -253,7 +278,7 @@ hist_candles.get_interday_history_candles(ticker='PETR4', market_type='stocks',
253
278
  ```python
254
279
  import btgsolutions_dataservices as btg
255
280
  hist_candles = btg.HistoricalCandles(api_key='YOUR_API_KEY')
256
- hist_candles.get_intraday_history_candles(ticker='PETR4', market_type='stocks', corporate_events_adj=True, date='2023-10-06', candle='1m', rmv_after_market=True, timezone='UTC', raw_data=False)
281
+ hist_candles.get_intraday_history_candles(ticker='PETR4', market_type='stocks', corporate_events_adj=True, date='2023-10-06', candle='1m', rmv_after_market=True, timezone='UTC', raw_data=False, round=True)
257
282
  ```
258
283
 
259
284
  ##### Available Tickers
@@ -272,6 +297,32 @@ hist_candles = btg.HistoricalCandles(api_key='YOUR_API_KEY')
272
297
  hist_candles.get_intraday_history_candles(ticker='PETR4', market_type='stocks', corporate_events_adj=True, date='2023-10-06', candle='1m', rmv_after_market=True, timezone='UTC', raw_data=False).plot(x='candle_time', y='close_price', kind='scatter')
273
298
  ```
274
299
 
300
+ #### Historical Candles Crypto
301
+
302
+ ##### Interday
303
+
304
+ ```python
305
+ import btgsolutions_dataservices as btg
306
+ hist_candles_crypto = btg.HistoricalCandlesCrypto(api_key='YOUR_API_KEY')
307
+ hist_candles_crypto.get_interday_history_candles(ticker='BTC', currency='BRL', exchange='consolidated', start_date='2025-06-01', end_date='2025-07-01', timezone='UTC', raw_data=False)
308
+ ```
309
+
310
+ ##### Intraday
311
+
312
+ ```python
313
+ import btgsolutions_dataservices as btg
314
+ hist_candles_crypto = btg.HistoricalCandlesCrypto(api_key='YOUR_API_KEY')
315
+ hist_candles_crypto.get_intraday_history_candles(ticker='BTC', currency='BRL', exchange='consolidated', date='2025-06-01', candle='1h', timezone='America/Sao_Paulo', raw_data=False)
316
+ ```
317
+
318
+ ##### Available Tickers
319
+
320
+ ```python
321
+ import btgsolutions_dataservices as btg
322
+ hist_candles_crypto = btg.HistoricalCandlesCrypto(api_key='YOUR_API_KEY')
323
+ hist_candles_crypto.get_available_tickers(exchange='coinbase', date='2023-01-13')
324
+ ```
325
+
275
326
  #### Historical Tick Data (Bulk Data)
276
327
 
277
328
  ##### Available Tickers
@@ -15,6 +15,7 @@ btgsolutions_dataservices/rest/company_data.py
15
15
  btgsolutions_dataservices/rest/corporate_events.py
16
16
  btgsolutions_dataservices/rest/hfn.py
17
17
  btgsolutions_dataservices/rest/historical_candles.py
18
+ btgsolutions_dataservices/rest/historical_candles_crypto.py
18
19
  btgsolutions_dataservices/rest/intraday_candles.py
19
20
  btgsolutions_dataservices/rest/intraday_tick_data.py
20
21
  btgsolutions_dataservices/rest/public_sources.py
@@ -24,6 +25,7 @@ btgsolutions_dataservices/rest/stock_loan.py
24
25
  btgsolutions_dataservices/rest/ticker_last_event.py
25
26
  btgsolutions_dataservices/rest/ticker_last_event_polling.py
26
27
  btgsolutions_dataservices/websocket/__init__.py
28
+ btgsolutions_dataservices/websocket/broker_analytics.py
27
29
  btgsolutions_dataservices/websocket/hfn_websocket_client.py
28
30
  btgsolutions_dataservices/websocket/market_data_feed.py
29
31
  btgsolutions_dataservices/websocket/market_data_websocket_client.py
@@ -38,5 +38,5 @@ setup(
38
38
  packages=find_packages(),
39
39
  url="https://github.com/BTG-Pactual-Solutions/btgsolutions-dataservices-python-client",
40
40
  install_requires=install_requires,
41
- python_requires=">=3.9,<3.14",
41
+ python_requires=">=3.9,<3.15",
42
42
  )