btgsolutions-dataservices-python-client 2.10.2__py3-none-any.whl → 2.16.0__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.
- btgsolutions_dataservices/config.py +12 -1
- btgsolutions_dataservices/rest/__init__.py +2 -1
- btgsolutions_dataservices/rest/historical_candles.py +29 -1
- btgsolutions_dataservices/rest/intraday_candles.py +10 -1
- btgsolutions_dataservices/rest/stock_loan.py +110 -0
- btgsolutions_dataservices/rest/ticker_last_event.py +96 -11
- btgsolutions_dataservices/websocket/__init__.py +2 -1
- btgsolutions_dataservices/websocket/market_data_feed.py +412 -0
- btgsolutions_dataservices/websocket/market_data_websocket_client.py +17 -10
- btgsolutions_dataservices/websocket/websocket_default_functions.py +3 -0
- {btgsolutions_dataservices_python_client-2.10.2.dist-info → btgsolutions_dataservices_python_client-2.16.0.dist-info}/METADATA +154 -94
- {btgsolutions_dataservices_python_client-2.10.2.dist-info → btgsolutions_dataservices_python_client-2.16.0.dist-info}/RECORD +15 -13
- {btgsolutions_dataservices_python_client-2.10.2.dist-info → btgsolutions_dataservices_python_client-2.16.0.dist-info}/WHEEL +1 -1
- {btgsolutions_dataservices_python_client-2.10.2.dist-info → btgsolutions_dataservices_python_client-2.16.0.dist-info}/licenses/LICENSE +0 -0
- {btgsolutions_dataservices_python_client-2.10.2.dist-info → btgsolutions_dataservices_python_client-2.16.0.dist-info}/top_level.txt +0 -0
|
@@ -26,6 +26,7 @@ SECURITIES = 'securities'
|
|
|
26
26
|
TRADES = 'trades'
|
|
27
27
|
PROCESSEDTRADES = 'processed-trades'
|
|
28
28
|
INSTRUMENTSTATUS = 'instrument_status'
|
|
29
|
+
SETTLEMENTPRICES = 'settlement-price'
|
|
29
30
|
BOOKS = 'books'
|
|
30
31
|
INDICES = 'indices'
|
|
31
32
|
CANDLES1S = 'candles-1S'
|
|
@@ -49,10 +50,15 @@ VALID_MARKET_DATA_TYPES = [
|
|
|
49
50
|
CANDLES1S,
|
|
50
51
|
CANDLES1M,
|
|
51
52
|
STOPLOSS,
|
|
52
|
-
INSTRUMENTSTATUS
|
|
53
|
+
INSTRUMENTSTATUS,
|
|
54
|
+
SETTLEMENTPRICES
|
|
53
55
|
]
|
|
54
56
|
VALID_MARKET_DATA_SUBTYPES = [ALL, STOCKS, OPTIONS, DERIVATIVES]
|
|
55
57
|
|
|
58
|
+
FEED_A = "A"
|
|
59
|
+
FEED_B = "B"
|
|
60
|
+
VALID_FEEDS = [FEED_A, FEED_B]
|
|
61
|
+
|
|
56
62
|
market_data_socket_urls = {
|
|
57
63
|
B3: {
|
|
58
64
|
TRADES: {
|
|
@@ -130,6 +136,11 @@ market_data_socket_urls = {
|
|
|
130
136
|
DERIVATIVES: f"{url_ws}v2/marketdata/{INSTRUMENTSTATUS}/{DERIVATIVES}",
|
|
131
137
|
OPTIONS: f"{url_ws}v2/marketdata/{INSTRUMENTSTATUS}/{OPTIONS}",
|
|
132
138
|
}
|
|
139
|
+
},
|
|
140
|
+
SETTLEMENTPRICES: {
|
|
141
|
+
REALTIME: {
|
|
142
|
+
ALL: f"{url_ws}v2/marketdata/{SETTLEMENTPRICES}",
|
|
143
|
+
}
|
|
133
144
|
}
|
|
134
145
|
},
|
|
135
146
|
BMV: {
|
|
@@ -9,4 +9,5 @@ from .ticker_last_event import TickerLastEvent
|
|
|
9
9
|
from .corporate_events import CorporateEvents
|
|
10
10
|
from .company_data import CompanyData
|
|
11
11
|
from .public_sources import PublicSources
|
|
12
|
-
from .reference_data import ReferenceData
|
|
12
|
+
from .reference_data import ReferenceData
|
|
13
|
+
from .stock_loan import StockLoan
|
|
@@ -158,4 +158,32 @@ class HistoricalCandles:
|
|
|
158
158
|
return response_data if raw_data else pd.DataFrame(response_data)
|
|
159
159
|
|
|
160
160
|
response = json.loads(response.text)
|
|
161
|
-
raise BadResponse(f'Error: {response.get("ApiClientError", "")}.\n{response.get("SuggestedAction", "")}')
|
|
161
|
+
raise BadResponse(f'Error: {response.get("ApiClientError", "")}.\n{response.get("SuggestedAction", "")}')
|
|
162
|
+
|
|
163
|
+
def get_available_tickers(
|
|
164
|
+
self,
|
|
165
|
+
market_type:str,
|
|
166
|
+
date:str,
|
|
167
|
+
):
|
|
168
|
+
"""
|
|
169
|
+
This method provides all tickers available for query.
|
|
170
|
+
|
|
171
|
+
Parameters
|
|
172
|
+
----------------
|
|
173
|
+
market_type: str
|
|
174
|
+
Market type.
|
|
175
|
+
Options: 'stocks', 'derivatives' or 'indices'.
|
|
176
|
+
Field is required.
|
|
177
|
+
date: string<date>
|
|
178
|
+
Date of requested data. Format: "YYYY-MM-DD".
|
|
179
|
+
Field is required. Example: '2023-10-06'.
|
|
180
|
+
"""
|
|
181
|
+
|
|
182
|
+
if market_type not in ['stocks', 'derivatives', 'indices']: raise MarketTypeError(f"Must provide a valid 'market_type' parameter. Input: '{market_type}'. Accepted values: 'stocks', 'derivatives' or 'indices'.")
|
|
183
|
+
|
|
184
|
+
url = f"{url_apis_v3}/marketdata/history/candles/available-tickers/{market_type}?date={date}"
|
|
185
|
+
|
|
186
|
+
response = requests.request("GET", url, headers=self.headers)
|
|
187
|
+
if response.status_code == 200: return response.json()
|
|
188
|
+
response = response.json()
|
|
189
|
+
raise BadResponse(f'Error: {response.get("ApiClientError", "") or response.get("ApiServerMessage", "")}.\n{response.get("SuggestedAction", "")}')
|
|
@@ -58,7 +58,8 @@ class IntradayCandles:
|
|
|
58
58
|
start:int=0,
|
|
59
59
|
end:int=0,
|
|
60
60
|
mode:str='absolute',
|
|
61
|
-
raw_data:bool=False
|
|
61
|
+
raw_data:bool=False,
|
|
62
|
+
cross_filter:str='',
|
|
62
63
|
):
|
|
63
64
|
"""
|
|
64
65
|
This method provides realtime intraday candles for a given ticker.
|
|
@@ -93,6 +94,10 @@ class IntradayCandles:
|
|
|
93
94
|
Candle mode.
|
|
94
95
|
Example: 'absolute', 'relative' or 'spark'.
|
|
95
96
|
Default: absolute.
|
|
97
|
+
cross_filter: str
|
|
98
|
+
Filter trades by cross status. Available only when market_type is derivatives.
|
|
99
|
+
Options: 'all', 'only_cross' or 'without_cross'.
|
|
100
|
+
Default: 'all'.
|
|
96
101
|
raw_data: bool
|
|
97
102
|
If false, returns data in a dict of dataframes. If true, returns raw data.
|
|
98
103
|
Default: False.
|
|
@@ -101,6 +106,8 @@ class IntradayCandles:
|
|
|
101
106
|
if market_type not in ['stocks', 'derivatives', 'options', 'indices']: raise MarketTypeError(f"Must provide a valid 'market_type' parameter. Input: '{market_type}'. Accepted values: 'stocks', 'derivatives', 'options' or 'indices'.")
|
|
102
107
|
|
|
103
108
|
if delay not in ['delayed', 'realtime']: raise DelayError(f"Must provide a valid 'delay' parameter. Input: '{delay}'. Accepted values: 'delayed' or 'realtime'.")
|
|
109
|
+
|
|
110
|
+
if cross_filter and market_type != 'derivatives': raise DelayError(f"The 'cross_filter' flag is only valid for market_type 'derivatives'.")
|
|
104
111
|
|
|
105
112
|
tickers = ','.join(tickers) if type(tickers) is list else tickers
|
|
106
113
|
|
|
@@ -109,6 +116,8 @@ class IntradayCandles:
|
|
|
109
116
|
if start: url += f'&start={start}'
|
|
110
117
|
|
|
111
118
|
if end: url += f'&end={end}'
|
|
119
|
+
|
|
120
|
+
if cross_filter: url += f'&cross_filter={cross_filter}'
|
|
112
121
|
|
|
113
122
|
response = requests.request("GET", url, headers=self.headers)
|
|
114
123
|
if response.status_code == 200:
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
|
|
2
|
+
from typing import Optional
|
|
3
|
+
from ..exceptions import BadResponse
|
|
4
|
+
import requests
|
|
5
|
+
from ..config import url_api_v1
|
|
6
|
+
import json
|
|
7
|
+
from .authenticator import Authenticator
|
|
8
|
+
import pandas as pd
|
|
9
|
+
|
|
10
|
+
class StockLoan:
|
|
11
|
+
"""
|
|
12
|
+
This class provides trades related to stock loan operations.
|
|
13
|
+
|
|
14
|
+
* Main use case:
|
|
15
|
+
|
|
16
|
+
>>> from btgsolutions_dataservices import StockLoan
|
|
17
|
+
>>> stock_loan = StockLoan(
|
|
18
|
+
>>> api_key='YOUR_API_KEY',
|
|
19
|
+
>>> )
|
|
20
|
+
>>> trades = stock_loan.get_trades(
|
|
21
|
+
>>> ticker = 'PETR4'
|
|
22
|
+
>>> )
|
|
23
|
+
>>> trades = stock_loan.get_paginated_trades(
|
|
24
|
+
>>> page = 1,
|
|
25
|
+
>>> limit = 1000
|
|
26
|
+
>>> )
|
|
27
|
+
>>> stock_loan.get_available_tickers()
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------------
|
|
31
|
+
api_key: str
|
|
32
|
+
User identification key.
|
|
33
|
+
Field is required.
|
|
34
|
+
"""
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
api_key: Optional[str]
|
|
38
|
+
):
|
|
39
|
+
self.api_key = api_key
|
|
40
|
+
self.token = Authenticator(self.api_key).token
|
|
41
|
+
self.headers = {"authorization": f"authorization {self.token}"}
|
|
42
|
+
|
|
43
|
+
def get_trades(
|
|
44
|
+
self,
|
|
45
|
+
ticker:Optional[str]='',
|
|
46
|
+
):
|
|
47
|
+
"""
|
|
48
|
+
Returns trades related to stock loan operations.
|
|
49
|
+
|
|
50
|
+
Parameters
|
|
51
|
+
----------------
|
|
52
|
+
ticker : str, optional
|
|
53
|
+
The ticker symbol to be returned.
|
|
54
|
+
Example: 'PETR4'
|
|
55
|
+
|
|
56
|
+
"""
|
|
57
|
+
page = 1
|
|
58
|
+
df = pd.DataFrame()
|
|
59
|
+
while True:
|
|
60
|
+
url = f"{url_api_v1}/marketdata/stock-loan/daily-trades?page={page}&limit=20000"
|
|
61
|
+
if ticker: url += f'&ticker={ticker}'
|
|
62
|
+
response = requests.request("GET", url, headers=self.headers)
|
|
63
|
+
if response.status_code != 200: raise BadResponse(response.json())
|
|
64
|
+
response = response.json()
|
|
65
|
+
df = pd.concat([df, pd.DataFrame(response['data'])])
|
|
66
|
+
if response['totalPages'] <= page: break
|
|
67
|
+
page += 1
|
|
68
|
+
|
|
69
|
+
return df.reset_index(drop=True)
|
|
70
|
+
|
|
71
|
+
def get_paginated_trades(
|
|
72
|
+
self,
|
|
73
|
+
page:int,
|
|
74
|
+
limit:int,
|
|
75
|
+
ticker:Optional[str]='',
|
|
76
|
+
):
|
|
77
|
+
"""
|
|
78
|
+
Returns paginated trades related to stock loan operations.
|
|
79
|
+
|
|
80
|
+
Parameters
|
|
81
|
+
----------------
|
|
82
|
+
ticker : str, optional
|
|
83
|
+
The ticker symbol to be returned.
|
|
84
|
+
Example: 'PETR4'
|
|
85
|
+
|
|
86
|
+
page : int
|
|
87
|
+
Page number for paginated results.
|
|
88
|
+
Example: 1
|
|
89
|
+
|
|
90
|
+
limit : int
|
|
91
|
+
Maximum number of items to return per page.
|
|
92
|
+
Example: 1000
|
|
93
|
+
|
|
94
|
+
"""
|
|
95
|
+
url = f"{url_api_v1}/marketdata/stock-loan/daily-trades?page={page}&limit={limit}"
|
|
96
|
+
if ticker: url += f'&ticker={ticker}'
|
|
97
|
+
response = requests.request("GET", url, headers=self.headers)
|
|
98
|
+
if response.status_code == 200: return json.loads(response.text)
|
|
99
|
+
raise BadResponse(response.json())
|
|
100
|
+
|
|
101
|
+
def get_available_tickers(
|
|
102
|
+
self,
|
|
103
|
+
):
|
|
104
|
+
"""
|
|
105
|
+
This method provides all tickers available for query.
|
|
106
|
+
"""
|
|
107
|
+
url = f"{url_api_v1}/marketdata/stock-loan/available-tickers"
|
|
108
|
+
response = requests.request("GET", url, headers=self.headers)
|
|
109
|
+
if response.status_code == 200: return json.loads(response.text)
|
|
110
|
+
raise BadResponse(response.json())
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Optional
|
|
1
|
+
from typing import Optional, List
|
|
2
2
|
from ..exceptions import BadResponse
|
|
3
3
|
import requests
|
|
4
4
|
from ..config import url_api_v1
|
|
@@ -18,10 +18,16 @@ class TickerLastEvent:
|
|
|
18
18
|
>>> )
|
|
19
19
|
|
|
20
20
|
>>> last_event.get_trades(
|
|
21
|
+
>>> data_type = 'equities',
|
|
21
22
|
>>> ticker = 'PETR4',
|
|
22
23
|
>>> raw_data = False
|
|
23
24
|
>>> )
|
|
24
25
|
|
|
26
|
+
>>> last_event.get_tob(
|
|
27
|
+
>>> data_type = 'stocks',
|
|
28
|
+
>>> raw_data = False
|
|
29
|
+
>>> )
|
|
30
|
+
|
|
25
31
|
Parameters
|
|
26
32
|
----------------
|
|
27
33
|
api_key: str
|
|
@@ -33,10 +39,12 @@ class TickerLastEvent:
|
|
|
33
39
|
api_key:Optional[str]
|
|
34
40
|
):
|
|
35
41
|
self.api_key = api_key
|
|
36
|
-
self.
|
|
37
|
-
self.headers = {"authorization": f"authorization {self.token}"}
|
|
42
|
+
self.authenticator = Authenticator(self.api_key)
|
|
38
43
|
|
|
39
|
-
self.available_data_types =
|
|
44
|
+
self.available_data_types = {
|
|
45
|
+
"trades": ['equities', 'derivatives'],
|
|
46
|
+
"books": ['stocks', 'derivatives', 'options']
|
|
47
|
+
}
|
|
40
48
|
|
|
41
49
|
def get_trades(self, data_type:str, ticker:str, raw_data:bool=False):
|
|
42
50
|
|
|
@@ -56,12 +64,12 @@ class TickerLastEvent:
|
|
|
56
64
|
If false, returns data in a dataframe. If true, returns raw data.
|
|
57
65
|
Field is not required. Default: False.
|
|
58
66
|
"""
|
|
59
|
-
if data_type not in self.available_data_types:
|
|
60
|
-
raise Exception("Must provide a valid data_type. Valid data types are: {self.available_data_types}")
|
|
67
|
+
if data_type not in self.available_data_types["trades"]:
|
|
68
|
+
raise Exception(f"Must provide a valid data_type. Valid data types are: {self.available_data_types['trades']}")
|
|
61
69
|
|
|
62
70
|
url = f"{url_api_v1}/marketdata/last-event/trades/{data_type}?ticker={ticker}"
|
|
63
71
|
|
|
64
|
-
response = requests.request("GET", url, headers=self.
|
|
72
|
+
response = requests.request("GET", url, headers={"authorization": f"Bearer {self.authenticator.token}"})
|
|
65
73
|
if response.status_code == 200:
|
|
66
74
|
if raw_data:
|
|
67
75
|
return response.json()
|
|
@@ -70,23 +78,100 @@ class TickerLastEvent:
|
|
|
70
78
|
else:
|
|
71
79
|
response = json.loads(response.text)
|
|
72
80
|
raise BadResponse(f'Error: {response.get("error", "")}')
|
|
81
|
+
|
|
82
|
+
def get_tobs(self, data_type:str, raw_data:bool=False):
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
This method provides the last available top of book for all tickers of the given market type.
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------------
|
|
89
|
+
data_type: str
|
|
90
|
+
Market Data Type.
|
|
91
|
+
Field is required.
|
|
92
|
+
Example: 'stocks', 'derivatives', 'options'.
|
|
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
|
+
if data_type not in self.available_data_types["books"]:
|
|
99
|
+
raise Exception(f"Must provide a valid data_type. Valid data types are: {self.available_data_types}")
|
|
100
|
+
|
|
101
|
+
url = f"{url_api_v1}/marketdata/last-event/books/top/{data_type}/batch"
|
|
102
|
+
|
|
103
|
+
response = requests.request("GET", url, headers={"authorization": f"Bearer {self.authenticator.token}"})
|
|
104
|
+
|
|
105
|
+
if response.status_code == 200:
|
|
106
|
+
if raw_data:
|
|
107
|
+
return response.json()
|
|
108
|
+
else:
|
|
109
|
+
return pd.DataFrame(response.json())
|
|
110
|
+
else:
|
|
111
|
+
|
|
112
|
+
response = json.loads(response.text)
|
|
113
|
+
raise BadResponse(f'Error: {response.get("error", "")}')
|
|
73
114
|
|
|
74
|
-
def
|
|
115
|
+
def get_status(self, tickers:List[str]=None, raw_data:bool=False):
|
|
116
|
+
|
|
117
|
+
"""
|
|
118
|
+
This method provides the current ticker trading status information.
|
|
119
|
+
|
|
120
|
+
Parameters
|
|
121
|
+
----------------
|
|
122
|
+
tickers: List[str]
|
|
123
|
+
Ticker symbol.
|
|
124
|
+
Field is not required. Default: None
|
|
125
|
+
Example: ['PETR4', 'VALE3', 'DOLM25'].
|
|
126
|
+
If no ticker is provided, it returns trading status information for all available tickers.
|
|
127
|
+
raw_data: bool
|
|
128
|
+
If false, returns data in a dataframe. If true, returns raw data.
|
|
129
|
+
Field is not required. Default: False.
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
if tickers:
|
|
133
|
+
tickers = ','.join(tickers)
|
|
134
|
+
url = f"{url_api_v1}/marketdata/last-event/status/all/batch?tickers={tickers}"
|
|
135
|
+
else:
|
|
136
|
+
url = f"{url_api_v1}/marketdata/last-event/status/all/batch"
|
|
137
|
+
|
|
138
|
+
response = requests.request("GET", url, headers={"authorization": f"Bearer {self.authenticator.token}"})
|
|
139
|
+
if response.status_code == 200:
|
|
140
|
+
if raw_data:
|
|
141
|
+
return response.json()
|
|
142
|
+
else:
|
|
143
|
+
return pd.DataFrame(response.json())
|
|
144
|
+
else:
|
|
145
|
+
response = json.loads(response.text)
|
|
146
|
+
raise BadResponse(f'Error: {response}')
|
|
147
|
+
|
|
148
|
+
def get_available_tickers(self,type:str, data_type:str):
|
|
75
149
|
|
|
76
150
|
"""
|
|
77
151
|
This method provides all the available tickers for the specific data type.
|
|
78
152
|
|
|
79
153
|
Parameters
|
|
80
154
|
----------------
|
|
155
|
+
type: str
|
|
156
|
+
Data Type.
|
|
157
|
+
Field is required.
|
|
158
|
+
Example: 'trades', 'books'
|
|
81
159
|
data_type: str
|
|
82
160
|
Market Data Type.
|
|
83
161
|
Field is required.
|
|
84
|
-
Example: 'equities', 'derivatives'.
|
|
162
|
+
Example: 'equities', 'derivatives', 'options', 'stocks'.
|
|
85
163
|
"""
|
|
86
164
|
|
|
87
|
-
|
|
165
|
+
if type not in self.available_data_types:
|
|
166
|
+
raise Exception(f"Must provide a valid type. Valid data types are: {list(self.available_data_types.keys())}")
|
|
167
|
+
|
|
168
|
+
if data_type not in self.available_data_types[type]:
|
|
169
|
+
raise Exception(f"Must provide a valid data_type. Valid data types are: {self.available_data_types['books']}")
|
|
170
|
+
|
|
171
|
+
url = f"{url_api_v1}/marketdata/last-event/trades/{data_type}/available-tickers" if type == "trades" else \
|
|
172
|
+
f"{url_api_v1}/marketdata/last-event/books/{data_type}/availables"
|
|
88
173
|
|
|
89
|
-
response = requests.request("GET", url, headers=self.
|
|
174
|
+
response = requests.request("GET", url, headers={"authorization": f"Bearer {self.authenticator.token}"})
|
|
90
175
|
if response.status_code == 200:
|
|
91
176
|
return response.json()
|
|
92
177
|
else:
|