cryptodatapy 0.2.8__py3-none-any.whl → 0.2.10__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.
- cryptodatapy/extract/datarequest.py +0 -1
- cryptodatapy/extract/exchanges/__init__.py +2 -0
- cryptodatapy/extract/exchanges/dydx.py +137 -0
- cryptodatapy/extract/exchanges/exchange.py +439 -0
- cryptodatapy/extract/getdata.py +68 -0
- cryptodatapy/extract/libraries/ccxt_api.py +706 -150
- cryptodatapy/extract/libraries/library.py +1 -3
- cryptodatapy/extract/web/web.py +62 -0
- cryptodatapy/transform/convertparams.py +5 -6
- cryptodatapy/transform/filter.py +7 -8
- cryptodatapy/transform/wrangle.py +2 -1
- {cryptodatapy-0.2.8.dist-info → cryptodatapy-0.2.10.dist-info}/METADATA +1 -1
- {cryptodatapy-0.2.8.dist-info → cryptodatapy-0.2.10.dist-info}/RECORD +15 -26
- cryptodatapy/conf/fx_tickers.csv +0 -31
- cryptodatapy/extract/data_vendors/CoinMetrics.ipynb +0 -747
- cryptodatapy/extract/libraries/Untitled.ipynb +0 -199
- cryptodatapy/extract/libraries/ccxt.ipynb +0 -747
- cryptodatapy/extract/libraries/yfinance_api.py +0 -511
- cryptodatapy/transform/cc_onchain_data.csv +0 -118423
- cryptodatapy/transform/clean_onchain_data.ipynb +0 -4750
- cryptodatapy/transform/clean_perp_futures_ohlcv.ipynb +0 -2819
- cryptodatapy/transform/cmdty_data.ipynb +0 -402
- cryptodatapy/transform/credit_data.ipynb +0 -291
- cryptodatapy/transform/eqty_data.ipynb +0 -836
- cryptodatapy/transform/global_credit_data_daily.parquet +0 -0
- cryptodatapy/transform/rates_data.ipynb +0 -465
- cryptodatapy/transform/us_rates_daily.csv +0 -227752
- {cryptodatapy-0.2.8.dist-info → cryptodatapy-0.2.10.dist-info}/LICENSE +0 -0
- {cryptodatapy-0.2.8.dist-info → cryptodatapy-0.2.10.dist-info}/WHEEL +0 -0
@@ -1,511 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
from typing import Any, Dict, List, Optional
|
3
|
-
|
4
|
-
import pandas as pd
|
5
|
-
import yfinance as yf
|
6
|
-
|
7
|
-
from cryptodatapy.extract.datarequest import DataRequest
|
8
|
-
from cryptodatapy.extract.libraries.library import Library
|
9
|
-
from cryptodatapy.transform.convertparams import ConvertParams
|
10
|
-
from cryptodatapy.transform.wrangle import WrangleData
|
11
|
-
|
12
|
-
|
13
|
-
class YahooFinance(Library):
|
14
|
-
"""
|
15
|
-
Retrieves data from yfinance API.
|
16
|
-
"""
|
17
|
-
def __init__(
|
18
|
-
self,
|
19
|
-
categories=None,
|
20
|
-
exchanges: Optional[List[str]] = None,
|
21
|
-
indexes: Optional[Dict[str, List[str]]] = None,
|
22
|
-
assets: Optional[Dict[str, List[str]]] = None,
|
23
|
-
markets: Optional[Dict[str, List[str]]] = None,
|
24
|
-
market_types=None,
|
25
|
-
fields: Optional[Dict[str, List[str]]] = None,
|
26
|
-
frequencies=None,
|
27
|
-
base_url: Optional[str] = None,
|
28
|
-
api_key=None,
|
29
|
-
max_obs_per_call: Optional[int] = None,
|
30
|
-
rate_limit: Optional[Any] = None,
|
31
|
-
):
|
32
|
-
"""
|
33
|
-
Constructor
|
34
|
-
|
35
|
-
Parameters
|
36
|
-
----------
|
37
|
-
categories: list or str, {'crypto', 'fx', 'rates', 'eqty', 'cmdty', 'credit', 'macro', 'alt'}
|
38
|
-
List or string of available categories, e.g. ['crypto', 'fx', 'alt'].
|
39
|
-
exchanges: list, optional, default None
|
40
|
-
List of available exchanges, e.g. ['Binance', 'Coinbase', 'Kraken', 'FTX', ...].
|
41
|
-
indexes: dictionary, optional, default None
|
42
|
-
Dictionary of available indexes, by cat-indexes key-value pairs, e.g. [{'eqty': ['SPX', 'N225'],
|
43
|
-
'rates': [.... , ...}.
|
44
|
-
assets: dictionary, optional, default None
|
45
|
-
Dictionary of available assets, by cat-assets key-value pairs, e.g. {'rates': ['Germany 2Y', 'Japan 10Y',
|
46
|
-
...], 'eqty: ['SPY', 'TLT', ...], ...}.
|
47
|
-
markets: dictionary, optional, default None
|
48
|
-
Dictionary of available markets, by cat-markets key-value pairs, e.g. [{'fx': ['EUR/USD', 'USD/JPY', ...],
|
49
|
-
'crypto': ['BTC/ETH', 'ETH/USDT', ...}.
|
50
|
-
market_types: list
|
51
|
-
List of available market types e.g. [spot', 'perpetual_future', 'future', 'option'].
|
52
|
-
fields: dictionary, optional, default None
|
53
|
-
Dictionary of available fields, by cat-fields key-value pairs, e.g. {'cmdty': ['date', 'open', 'high',
|
54
|
-
'low', 'close', 'volume'], 'macro': ['actual', 'previous', 'expected', 'surprise']}
|
55
|
-
frequencies: dictionary
|
56
|
-
Dictionary of available frequencies, by cat-frequencies key-value pairs, e.g. {'fx':
|
57
|
-
['d', 'w', 'm', 'q', 'y'], 'rates': ['d', 'w', 'm', 'q', 'y'], 'eqty': ['d', 'w', 'm', 'q', 'y'], ...}.
|
58
|
-
base_url: str, optional, default None
|
59
|
-
Base url used for GET requests. If not provided, default is set to base_url stored in DataCredentials.
|
60
|
-
api_key: dictionary
|
61
|
-
Api keys for data source by source-api key key-value pairs, e.g. {'av-daily' :'dcf13983adf7dfa79a0df',
|
62
|
-
'fred' : dcf13983adf7dfa79a0df', ...}.
|
63
|
-
If not provided, default is set to api_key stored in DataCredentials.
|
64
|
-
max_obs_per_call: int, optional, default None
|
65
|
-
Maximum number of observations returned per API call. If not provided, default is set to
|
66
|
-
api_limit stored in DataCredentials.
|
67
|
-
rate_limit: Any, optional, default None
|
68
|
-
Number of API calls made and left, by time frequency.
|
69
|
-
"""
|
70
|
-
Library.__init__(
|
71
|
-
self,
|
72
|
-
categories,
|
73
|
-
exchanges,
|
74
|
-
indexes,
|
75
|
-
assets,
|
76
|
-
markets,
|
77
|
-
market_types,
|
78
|
-
fields,
|
79
|
-
frequencies,
|
80
|
-
base_url,
|
81
|
-
api_key,
|
82
|
-
max_obs_per_call,
|
83
|
-
rate_limit,
|
84
|
-
)
|
85
|
-
|
86
|
-
|
87
|
-
def get_exchanges_info(self):
|
88
|
-
"""
|
89
|
-
Gets info for available exchanges from the Yahoo Finance API.
|
90
|
-
"""
|
91
|
-
pass
|
92
|
-
|
93
|
-
def get_indexes_info(self):
|
94
|
-
"""
|
95
|
-
Gets info for available indexes from the Yahoo Finance API.
|
96
|
-
"""
|
97
|
-
pass
|
98
|
-
|
99
|
-
def get_assets_info(self):
|
100
|
-
"""
|
101
|
-
Gets info for available assets from the Yahoo Finance API.
|
102
|
-
"""
|
103
|
-
pass
|
104
|
-
|
105
|
-
def get_markets_info(self):
|
106
|
-
"""
|
107
|
-
Gets info for available markets from the Yahoo Finance API.
|
108
|
-
"""
|
109
|
-
pass
|
110
|
-
|
111
|
-
def get_fields_info(self, data_type: Optional[str]):
|
112
|
-
"""
|
113
|
-
Gets info for available fields from the Yahoo Finance API.
|
114
|
-
"""
|
115
|
-
pass
|
116
|
-
|
117
|
-
def get_rate_limit_info(self):
|
118
|
-
"""
|
119
|
-
Gets the number of API calls made and remaining.
|
120
|
-
"""
|
121
|
-
pass
|
122
|
-
|
123
|
-
def get_data(self, data_req: DataRequest) -> pd.DataFrame:
|
124
|
-
"""
|
125
|
-
Submits get data request to Yahoo Finance API.
|
126
|
-
"""
|
127
|
-
# data_resp = yf.download(
|
128
|
-
# tickers=data_req.tickers,
|
129
|
-
# period
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
# self.categories = categories
|
134
|
-
# self.exchanges = exchanges
|
135
|
-
# self.assets = assets
|
136
|
-
# self.indexes = indexes
|
137
|
-
# self.markets = markets
|
138
|
-
# self.market_types = market_types
|
139
|
-
# self.fields = fields
|
140
|
-
# self.frequencies = frequencies
|
141
|
-
# self.base_url = base_url
|
142
|
-
# self.api_key = api_key
|
143
|
-
# self.max_obs_per_call = max_obs_per_call
|
144
|
-
# self.rate_limit = rate_limit
|
145
|
-
#
|
146
|
-
# @property
|
147
|
-
# def categories(self):
|
148
|
-
# """
|
149
|
-
# Returns a list of available categories for the data vendor.
|
150
|
-
# """
|
151
|
-
# return self._categories
|
152
|
-
#
|
153
|
-
# @categories.setter
|
154
|
-
# def categories(self, categories: Union[str, List[str]]):
|
155
|
-
# """
|
156
|
-
# Sets a list of available categories for the data vendor.
|
157
|
-
# """
|
158
|
-
# valid_categories = [
|
159
|
-
# "crypto",
|
160
|
-
# "fx",
|
161
|
-
# "eqty",
|
162
|
-
# "cmdty",
|
163
|
-
# "index",
|
164
|
-
# "rates",
|
165
|
-
# "bonds",
|
166
|
-
# "credit",
|
167
|
-
# "macro",
|
168
|
-
# "alt",
|
169
|
-
# ]
|
170
|
-
# cat = []
|
171
|
-
#
|
172
|
-
# if categories is None:
|
173
|
-
# self._categories = categories
|
174
|
-
# else:
|
175
|
-
# if not isinstance(categories, str) and not isinstance(categories, list):
|
176
|
-
# raise TypeError("Categories must be a string or list of strings.")
|
177
|
-
# if isinstance(categories, str):
|
178
|
-
# categories = [categories]
|
179
|
-
# for category in categories:
|
180
|
-
# if category in valid_categories:
|
181
|
-
# cat.append(category)
|
182
|
-
# else:
|
183
|
-
# raise ValueError(
|
184
|
-
# f"{category} is invalid. Valid categories are: {valid_categories}"
|
185
|
-
# )
|
186
|
-
# self._categories = cat
|
187
|
-
#
|
188
|
-
# @property
|
189
|
-
# def exchanges(self):
|
190
|
-
# """
|
191
|
-
# Returns a list of available exchanges for the data vendor.
|
192
|
-
# """
|
193
|
-
# return self._exchanges
|
194
|
-
#
|
195
|
-
# @exchanges.setter
|
196
|
-
# def exchanges(
|
197
|
-
# self, exchanges: Optional[Union[str, List[str], Dict[str, List[str]]]]
|
198
|
-
# ):
|
199
|
-
# """
|
200
|
-
# Sets a list of available exchanges for the data vendor.
|
201
|
-
# """
|
202
|
-
# if (
|
203
|
-
# exchanges is None
|
204
|
-
# or isinstance(exchanges, list)
|
205
|
-
# or isinstance(exchanges, dict)
|
206
|
-
# or isinstance(exchanges, pd.DataFrame)
|
207
|
-
# ):
|
208
|
-
# self._exchanges = exchanges
|
209
|
-
# elif isinstance(exchanges, str):
|
210
|
-
# self._exchanges = [exchanges]
|
211
|
-
# else:
|
212
|
-
# raise TypeError(
|
213
|
-
# "Exchanges must be a string, list of strings (exchanges), "
|
214
|
-
# " dict with {cat: List[str]} key-value pairs or a dataframe."
|
215
|
-
# )
|
216
|
-
#
|
217
|
-
# @abstractmethod
|
218
|
-
# def get_exchanges_info(self):
|
219
|
-
# """
|
220
|
-
# Gets info for available exchanges from the data vendor.
|
221
|
-
# """
|
222
|
-
# # to be implemented by subclasses
|
223
|
-
#
|
224
|
-
# @property
|
225
|
-
# def indexes(self):
|
226
|
-
# """
|
227
|
-
# Returns a list of available indices for the data vendor.
|
228
|
-
# """
|
229
|
-
# return self._indexes
|
230
|
-
#
|
231
|
-
# @indexes.setter
|
232
|
-
# def indexes(self, indexes: Optional[Union[str, List[str], Dict[str, List[str]]]]):
|
233
|
-
# """
|
234
|
-
# Sets a list of available indexes for the data vendor.
|
235
|
-
# """
|
236
|
-
# if indexes is None or isinstance(indexes, list) or isinstance(indexes, dict):
|
237
|
-
# self._indexes = indexes
|
238
|
-
# elif isinstance(indexes, str):
|
239
|
-
# self._indexes = [indexes]
|
240
|
-
# else:
|
241
|
-
# raise TypeError(
|
242
|
-
# "Indexes must be a string (ticker), list of strings (tickers) or"
|
243
|
-
# " a dict with {cat: List[str]} key-value pairs."
|
244
|
-
# )
|
245
|
-
#
|
246
|
-
# @abstractmethod
|
247
|
-
# def get_indexes_info(self):
|
248
|
-
# """
|
249
|
-
# Gets info for available indexes from the data vendor.
|
250
|
-
# """
|
251
|
-
# # to be implemented by subclasses
|
252
|
-
#
|
253
|
-
# @property
|
254
|
-
# def assets(self):
|
255
|
-
# """
|
256
|
-
# Returns a list of available assets for the data vendor.
|
257
|
-
# """
|
258
|
-
# return self._assets
|
259
|
-
#
|
260
|
-
# @assets.setter
|
261
|
-
# def assets(self, assets: Optional[Union[str, List[str], Dict[str, List[str]]]]):
|
262
|
-
# """
|
263
|
-
# Sets a list of available assets for the data vendor.
|
264
|
-
# """
|
265
|
-
# if (
|
266
|
-
# assets is None
|
267
|
-
# or isinstance(assets, list)
|
268
|
-
# or isinstance(assets, dict)
|
269
|
-
# or isinstance(assets, pd.DataFrame)
|
270
|
-
# ):
|
271
|
-
# self._assets = assets
|
272
|
-
# elif isinstance(assets, str):
|
273
|
-
# self._assets = [assets]
|
274
|
-
# else:
|
275
|
-
# raise TypeError(
|
276
|
-
# "Assets must be a string (ticker), list of strings (tickers),"
|
277
|
-
# " a dict with {cat: List[str]} key-value pairs or dataframe."
|
278
|
-
# )
|
279
|
-
#
|
280
|
-
# @abstractmethod
|
281
|
-
# def get_assets_info(self):
|
282
|
-
# """
|
283
|
-
# Gets info for available assets from the data vendor.
|
284
|
-
# """
|
285
|
-
# # to be implemented by subclasses
|
286
|
-
#
|
287
|
-
# @property
|
288
|
-
# def markets(self):
|
289
|
-
# """
|
290
|
-
# Returns a list of available markets for the data vendor.
|
291
|
-
# """
|
292
|
-
# return self._markets
|
293
|
-
#
|
294
|
-
# @markets.setter
|
295
|
-
# def markets(self, markets: Optional[Union[str, List[str], Dict[str, List[str]]]]):
|
296
|
-
# """
|
297
|
-
# Sets a list of available markets for the data vendor.
|
298
|
-
# """
|
299
|
-
# if (
|
300
|
-
# markets is None
|
301
|
-
# or isinstance(markets, list)
|
302
|
-
# or isinstance(markets, dict)
|
303
|
-
# or isinstance(markets, pd.DataFrame)
|
304
|
-
# ):
|
305
|
-
# self._markets = markets
|
306
|
-
# elif isinstance(markets, str):
|
307
|
-
# self._markets = [markets]
|
308
|
-
# else:
|
309
|
-
# raise TypeError(
|
310
|
-
# "Markets must be a string (ticker), list of strings (tickers),"
|
311
|
-
# " a dict with {cat: List[str]} key-value pairs or dataframe."
|
312
|
-
# )
|
313
|
-
#
|
314
|
-
# @abstractmethod
|
315
|
-
# def get_markets_info(self):
|
316
|
-
# """
|
317
|
-
# Gets info for available markets from the data vendor.
|
318
|
-
# """
|
319
|
-
# # to be implemented by subclasses
|
320
|
-
#
|
321
|
-
# @property
|
322
|
-
# def market_types(self):
|
323
|
-
# """
|
324
|
-
# Returns a list of available market types for the data vendor.
|
325
|
-
# """
|
326
|
-
# return self._market_types
|
327
|
-
#
|
328
|
-
# @market_types.setter
|
329
|
-
# def market_types(self, market_types: Optional[Union[str, List[str]]]):
|
330
|
-
# """
|
331
|
-
# Sets a list of available market types for the data vendor.
|
332
|
-
# """
|
333
|
-
# valid_mkt_types, mkt_types_list = [
|
334
|
-
# None,
|
335
|
-
# "spot",
|
336
|
-
# "etf",
|
337
|
-
# "perpetual_future",
|
338
|
-
# "future",
|
339
|
-
# "swap",
|
340
|
-
# "option",
|
341
|
-
# ], []
|
342
|
-
#
|
343
|
-
# if market_types is None:
|
344
|
-
# self._market_types = market_types
|
345
|
-
# elif isinstance(market_types, str) and market_types in valid_mkt_types:
|
346
|
-
# self._market_types = [market_types]
|
347
|
-
# elif isinstance(market_types, list):
|
348
|
-
# for mkt in market_types:
|
349
|
-
# if mkt in valid_mkt_types:
|
350
|
-
# mkt_types_list.append(mkt)
|
351
|
-
# else:
|
352
|
-
# raise ValueError(
|
353
|
-
# f"{mkt} is invalid. Valid market types are: {valid_mkt_types}"
|
354
|
-
# )
|
355
|
-
# self._market_types = mkt_types_list
|
356
|
-
# else:
|
357
|
-
# raise TypeError("Market types must be a string or list of strings.")
|
358
|
-
#
|
359
|
-
# @property
|
360
|
-
# def fields(self):
|
361
|
-
# """
|
362
|
-
# Returns a list of available fields for the data vendor.
|
363
|
-
# """
|
364
|
-
# return self._fields
|
365
|
-
#
|
366
|
-
# @fields.setter
|
367
|
-
# def fields(self, fields: Optional[Union[str, List[str], Dict[str, List[str]]]]):
|
368
|
-
# """
|
369
|
-
# Sets a list of available fields for the data vendor.
|
370
|
-
# """
|
371
|
-
# if fields is None or isinstance(fields, list) or isinstance(fields, dict):
|
372
|
-
# self._fields = fields
|
373
|
-
# elif isinstance(fields, str):
|
374
|
-
# self._fields = [fields]
|
375
|
-
# else:
|
376
|
-
# raise TypeError(
|
377
|
-
# "Fields must be a string (field), list of strings (fields) or"
|
378
|
-
# " a dict with {cat: List[str]} key-value pairs."
|
379
|
-
# )
|
380
|
-
#
|
381
|
-
# @abstractmethod
|
382
|
-
# def get_fields_info(self, data_type: Optional[str]):
|
383
|
-
# """
|
384
|
-
# Gets info for available fields from the data vendor.
|
385
|
-
# """
|
386
|
-
# # to be implemented by subclasses
|
387
|
-
#
|
388
|
-
# @property
|
389
|
-
# def frequencies(self):
|
390
|
-
# """
|
391
|
-
# Returns a list of available data frequencies for the data vendor.
|
392
|
-
# """
|
393
|
-
# return self._frequencies
|
394
|
-
#
|
395
|
-
# @frequencies.setter
|
396
|
-
# def frequencies(
|
397
|
-
# self, frequencies: Optional[Union[str, List[str], Dict[str, List[str]]]]
|
398
|
-
# ):
|
399
|
-
# """
|
400
|
-
# Sets a list of available data frequencies for the data vendor.
|
401
|
-
# """
|
402
|
-
# if (
|
403
|
-
# frequencies is None
|
404
|
-
# or isinstance(frequencies, list)
|
405
|
-
# or isinstance(frequencies, dict)
|
406
|
-
# ):
|
407
|
-
# self._frequencies = frequencies
|
408
|
-
# elif isinstance(frequencies, str):
|
409
|
-
# self._frequencies = [frequencies]
|
410
|
-
# else:
|
411
|
-
# raise TypeError(
|
412
|
-
# "Frequencies must be a string (frequency), list of strings (frequencies) or"
|
413
|
-
# " a dict with {cat: List[str]} key-value pairs."
|
414
|
-
# )
|
415
|
-
#
|
416
|
-
# @property
|
417
|
-
# def base_url(self):
|
418
|
-
# """
|
419
|
-
# Returns the base url for the data vendor.
|
420
|
-
# """
|
421
|
-
# return self._base_url
|
422
|
-
#
|
423
|
-
# @base_url.setter
|
424
|
-
# def base_url(self, url: Optional[str]):
|
425
|
-
# """
|
426
|
-
# Sets the base url for the data vendor.
|
427
|
-
# """
|
428
|
-
# if url is None or isinstance(url, str):
|
429
|
-
# self._base_url = url
|
430
|
-
# else:
|
431
|
-
# raise TypeError(
|
432
|
-
# "Base url must be a string containing the data vendor's base URL to which endpoint paths"
|
433
|
-
# " are appended."
|
434
|
-
# )
|
435
|
-
#
|
436
|
-
# @property
|
437
|
-
# def api_key(self):
|
438
|
-
# """
|
439
|
-
# Returns the api key for the data vendor.
|
440
|
-
# """
|
441
|
-
# return self._api_key
|
442
|
-
#
|
443
|
-
# @api_key.setter
|
444
|
-
# def api_key(self, api_key: Optional[str]):
|
445
|
-
# """
|
446
|
-
# Sets the api key for the data vendor.
|
447
|
-
# """
|
448
|
-
# if api_key is None or isinstance(api_key, str) or isinstance(api_key, dict):
|
449
|
-
# self._api_key = api_key
|
450
|
-
# else:
|
451
|
-
# raise TypeError(
|
452
|
-
# "Api key must be a string or dict with data source-api key key-value pairs."
|
453
|
-
# )
|
454
|
-
#
|
455
|
-
# @property
|
456
|
-
# def max_obs_per_call(self):
|
457
|
-
# """
|
458
|
-
# Returns the maximum observations per API call for the data vendor.
|
459
|
-
# """
|
460
|
-
# return self._max_obs_per_call
|
461
|
-
#
|
462
|
-
# @max_obs_per_call.setter
|
463
|
-
# def max_obs_per_call(self, limit: Optional[Union[int, str]]):
|
464
|
-
# """
|
465
|
-
# Sets the maximum number of observations per API call for the data vendor.
|
466
|
-
# """
|
467
|
-
# if limit is None:
|
468
|
-
# self._max_obs_per_call = limit
|
469
|
-
# elif isinstance(limit, int) or isinstance(limit, str):
|
470
|
-
# self._max_obs_per_call = int(limit)
|
471
|
-
# else:
|
472
|
-
# raise TypeError(
|
473
|
-
# "Maximum number of observations per API call must be an integer or string."
|
474
|
-
# )
|
475
|
-
#
|
476
|
-
# @property
|
477
|
-
# def rate_limit(self):
|
478
|
-
# """
|
479
|
-
# Returns the number of API calls made and remaining.
|
480
|
-
# """
|
481
|
-
# return self._rate_limit
|
482
|
-
#
|
483
|
-
# @rate_limit.setter
|
484
|
-
# def rate_limit(self, limit: Optional[Any]):
|
485
|
-
# """
|
486
|
-
# Sets the number of API calls made and remaining.
|
487
|
-
# """
|
488
|
-
# self._rate_limit = limit
|
489
|
-
#
|
490
|
-
# @abstractmethod
|
491
|
-
# def get_rate_limit_info(self):
|
492
|
-
# """
|
493
|
-
# Gets the number of API calls made and remaining.
|
494
|
-
# """
|
495
|
-
# # to be implemented by subclasses
|
496
|
-
#
|
497
|
-
# @abstractmethod
|
498
|
-
# def get_data(self, data_req) -> pd.DataFrame:
|
499
|
-
# """
|
500
|
-
# Submits get data request to API.
|
501
|
-
# """
|
502
|
-
# # to be implemented by subclasses
|
503
|
-
#
|
504
|
-
# @staticmethod
|
505
|
-
# @abstractmethod
|
506
|
-
# def wrangle_data_resp(data_req: DataRequest, data_resp: Union[Dict[str, Any], pd.DataFrame]) \
|
507
|
-
# -> pd.DataFrame:
|
508
|
-
# """
|
509
|
-
# Wrangles data response from data vendor API into tidy format.
|
510
|
-
# """
|
511
|
-
# # to be implemented by subclasses
|