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.
@@ -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.token = Authenticator(self.api_key).token
37
- self.headers = {"authorization": f"authorization {self.token}"}
42
+ self.authenticator = Authenticator(self.api_key)
38
43
 
39
- self.available_data_types = ['equities', 'derivatives']
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.headers)
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 get_available_tickers(self, data_type:str):
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
- url = f"{url_api_v1}/marketdata/last-event/trades/{data_type}/available-tickers"
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.headers)
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:
@@ -1,2 +1,3 @@
1
1
  from .market_data_websocket_client import MarketDataWebSocketClient
2
- from .hfn_websocket_client import HFNWebSocketClient
2
+ from .hfn_websocket_client import HFNWebSocketClient
3
+ from .market_data_feed import MarketDataFeed