cryptodatapy 0.2.5__py3-none-any.whl → 0.2.6__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.
Files changed (36) hide show
  1. cryptodatapy/conf/tickers.csv +0 -1
  2. cryptodatapy/extract/data_vendors/CoinMetrics.ipynb +747 -0
  3. cryptodatapy/extract/data_vendors/coinmetrics_api.py +279 -209
  4. cryptodatapy/extract/data_vendors/cryptocompare_api.py +3 -5
  5. cryptodatapy/extract/data_vendors/datavendor.py +32 -12
  6. cryptodatapy/extract/data_vendors/glassnode_api.py +3 -2
  7. cryptodatapy/extract/data_vendors/tiingo_api.py +3 -2
  8. cryptodatapy/extract/datarequest.py +55 -9
  9. cryptodatapy/extract/libraries/ccxt_api.py +13 -2
  10. cryptodatapy/transform/cc_onchain_data.csv +118423 -0
  11. cryptodatapy/transform/clean.py +17 -15
  12. cryptodatapy/transform/clean_onchain_data.ipynb +4750 -0
  13. cryptodatapy/transform/clean_perp_futures_ohlcv.ipynb +1597 -1178
  14. cryptodatapy/transform/convertparams.py +28 -18
  15. cryptodatapy/transform/credit_data.ipynb +291 -0
  16. cryptodatapy/transform/eqty_data.ipynb +809 -0
  17. cryptodatapy/transform/filter.py +13 -10
  18. cryptodatapy/transform/global_credit_data_daily.parquet +0 -0
  19. cryptodatapy/transform/od.py +1 -0
  20. cryptodatapy/transform/rates_data.ipynb +465 -0
  21. cryptodatapy/transform/us_rates_daily.csv +227752 -0
  22. cryptodatapy/util/datacredentials.py +28 -7
  23. {cryptodatapy-0.2.5.dist-info → cryptodatapy-0.2.6.dist-info}/METADATA +2 -2
  24. {cryptodatapy-0.2.5.dist-info → cryptodatapy-0.2.6.dist-info}/RECORD +26 -28
  25. cryptodatapy/.DS_Store +0 -0
  26. cryptodatapy/.idea/.gitignore +0 -3
  27. cryptodatapy/.idea/cryptodatapy.iml +0 -12
  28. cryptodatapy/.idea/csv-plugin.xml +0 -16
  29. cryptodatapy/.idea/inspectionProfiles/Project_Default.xml +0 -6
  30. cryptodatapy/.idea/inspectionProfiles/profiles_settings.xml +0 -6
  31. cryptodatapy/.idea/misc.xml +0 -4
  32. cryptodatapy/.idea/modules.xml +0 -8
  33. cryptodatapy/.idea/vcs.xml +0 -6
  34. cryptodatapy/extract/libraries/ccxt.ipynb +0 -873
  35. {cryptodatapy-0.2.5.dist-info → cryptodatapy-0.2.6.dist-info}/LICENSE +0 -0
  36. {cryptodatapy-0.2.5.dist-info → cryptodatapy-0.2.6.dist-info}/WHEEL +0 -0
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ from time import sleep
2
3
  from typing import Any, Dict, List, Optional, Union
3
4
 
4
5
  import pandas as pd
@@ -12,6 +13,7 @@ from cryptodatapy.util.datacredentials import DataCredentials
12
13
 
13
14
  # data credentials
14
15
  data_cred = DataCredentials()
16
+
15
17
  # CoinMetrics community API client:
16
18
  client = CoinMetricsClient()
17
19
 
@@ -23,16 +25,17 @@ class CoinMetrics(DataVendor):
23
25
 
24
26
  def __init__(
25
27
  self,
26
- categories=None,
28
+ categories: Union[str, List[str]] = "crypto",
27
29
  exchanges: Optional[List[str]] = None,
28
30
  indexes: Optional[List[str]] = None,
29
31
  assets: Optional[List[str]] = None,
30
32
  markets: Optional[List[str]] = None,
31
- market_types=None,
33
+ market_types: List[str] = ["spot", "perpetual_future", "future", "option"],
32
34
  fields: Optional[List[str]] = None,
33
- frequencies=None,
34
- base_url: Optional[str] = None,
35
- api_key: Optional[str] = None,
35
+ frequencies: List[str] = ["tick", "block", "1s", "1min", "5min", "10min", "15min", "30min",
36
+ "1h", "2h", "4h", "8h", "d", "w", "m", "q"],
37
+ base_url: Optional[str] = data_cred.coinmetrics_base_url,
38
+ api_key: Optional[str] = data_cred.coinmetrics_api_key,
36
39
  max_obs_per_call: Optional[int] = None,
37
40
  rate_limit: Optional[Any] = None,
38
41
  ):
@@ -84,40 +87,6 @@ class CoinMetrics(DataVendor):
84
87
  rate_limit,
85
88
  )
86
89
 
87
- if frequencies is None:
88
- self.frequencies = [
89
- "tick",
90
- "block",
91
- "1s",
92
- "1min",
93
- "5min",
94
- "10min",
95
- "15min",
96
- "30min",
97
- "1h",
98
- "2h",
99
- "4h",
100
- "8h",
101
- "d",
102
- "w",
103
- "m",
104
- "q",
105
- ]
106
- if market_types is None:
107
- self.market_types = ["spot", "perpetual_future", "future", "option"]
108
- if categories is None:
109
- self.categories = ["crypto"]
110
- if exchanges is None:
111
- self._exchanges = self.get_exchanges_info(as_list=True)
112
- if indexes is None:
113
- self._indexes = self.get_indexes_info(as_list=True)
114
- if assets is None:
115
- self._assets = self.get_assets_info(as_list=True)
116
- if markets is None:
117
- self._markets = self.get_markets_info(as_list=True)
118
- if fields is None:
119
- self._fields = self.get_fields_info(data_type=None, as_list=True)
120
-
121
90
  @staticmethod
122
91
  def req_meta(data_type: str) -> Dict[str, Any]:
123
92
  """
@@ -161,9 +130,9 @@ class CoinMetrics(DataVendor):
161
130
  # req data
162
131
  exch = self.req_meta(data_type='catalog_exchanges')
163
132
  # wrangle data resp
164
- exch = WrangleInfo(exch).cm_meta_resp(as_list=as_list, index_name='exchange')
133
+ self.exchanges = WrangleInfo(exch).cm_meta_resp(as_list=as_list, index_name='exchange')
165
134
 
166
- return exch
135
+ return self.exchanges
167
136
 
168
137
  def get_indexes_info(self, as_list: bool = False) -> Union[List[str], pd.DataFrame]:
169
138
  """
@@ -182,11 +151,11 @@ class CoinMetrics(DataVendor):
182
151
  # req data
183
152
  indexes = self.req_meta(data_type='catalog_indexes')
184
153
  # wrangle data resp
185
- indexes = WrangleInfo(indexes).cm_meta_resp(as_list=as_list, index_name='ticker')
154
+ self.indexes = WrangleInfo(indexes).cm_meta_resp(as_list=as_list, index_name='ticker')
186
155
 
187
- return indexes
156
+ return self.indexes
188
157
 
189
- def get_assets_info(self, as_list: bool = False, ) -> Union[List[str], pd.DataFrame]:
158
+ def get_assets_info(self, as_list: bool = False) -> Union[List[str], pd.DataFrame]:
190
159
  """
191
160
  Get assets info.
192
161
 
@@ -203,9 +172,9 @@ class CoinMetrics(DataVendor):
203
172
  # req data
204
173
  assets = self.req_meta(data_type='catalog_assets')
205
174
  # wrangle data resp
206
- assets = WrangleInfo(assets).cm_meta_resp(as_list=as_list, index_name='ticker')
175
+ self.assets = WrangleInfo(assets).cm_meta_resp(as_list=as_list, index_name='ticker')
207
176
 
208
- return assets
177
+ return self.assets
209
178
 
210
179
  def get_inst_info(self, as_dict: bool = False) -> Union[Dict[str, List[str]], pd.DataFrame]:
211
180
  """
@@ -243,11 +212,11 @@ class CoinMetrics(DataVendor):
243
212
  List or dataframe with info on available markets, by exchange.
244
213
  """
245
214
  # req data
246
- mkts = self.req_meta(data_type='catalog_markets')
215
+ markets = self.req_meta(data_type='catalog_markets')
247
216
  # wrangle data resp
248
- mkts = WrangleInfo(mkts).cm_meta_resp(as_list=as_list)
217
+ self.markets = WrangleInfo(markets).cm_meta_resp(as_list=as_list)
249
218
 
250
- return mkts
219
+ return self.markets
251
220
 
252
221
  def get_onchain_fields_info(self, as_list: bool = False) -> Union[List[str], pd.DataFrame]:
253
222
  """
@@ -289,29 +258,29 @@ class CoinMetrics(DataVendor):
289
258
  # req data
290
259
  ohlcv_fields = ['price_open', 'price_close', 'price_high', 'price_low', 'vwap', 'volume', 'candle_usd_volume',
291
260
  'candle_trades_count'] # get market fields
292
- inst_fields = list(self.get_inst_info(as_dict=True).values())[0] # inst fields
261
+ inst_fields = [v for k, v in self.get_inst_info(as_dict=True).items()][0] # inst fields
293
262
  onchain_fields = self.get_onchain_fields_info() # get onchain fields
294
263
 
295
264
  # fields df
296
265
  if data_type == "market":
297
- fields = onchain_fields[onchain_fields.category == "Market"]
266
+ self.fields = onchain_fields[onchain_fields.category == "Market"]
298
267
  elif data_type == "off-chain":
299
- fields = inst_fields
268
+ self.fields = inst_fields
300
269
  else:
301
- fields = onchain_fields
270
+ self.fields = onchain_fields
302
271
 
303
272
  # fields list
304
273
  if as_list:
305
274
  if data_type == "market":
306
- fields = ohlcv_fields + list(fields.index)
275
+ self.fields = ohlcv_fields + list(self.fields.index)
307
276
  elif data_type == "on-chain":
308
- fields = list(fields.index)
277
+ self.fields = list(self.fields.index)
309
278
  elif data_type == "off-chain":
310
- fields = inst_fields
279
+ self.fields = inst_fields
311
280
  else:
312
- fields = ohlcv_fields + list(fields.index) + inst_fields
281
+ self.fields = ohlcv_fields + list(self.fields.index) + inst_fields
313
282
 
314
- return fields
283
+ return self.fields
315
284
 
316
285
  def get_onchain_tickers_list(self, data_req: DataRequest) -> List[str]:
317
286
  """
@@ -332,12 +301,15 @@ class CoinMetrics(DataVendor):
332
301
  # fields param
333
302
  fields = cm_data_req["fields"]
334
303
 
304
+ # fields info
305
+ self.get_fields_info()
335
306
  # fields dict
336
307
  fields_dict = {}
337
308
  for field in fields:
338
- df = self.get_fields_info().loc[field] # get fields info
339
- # add to dict
340
- fields_dict[field] = df["frequencies"][0]["assets"]
309
+ if field in self.fields.index:
310
+ df = self.fields.loc[field] # get fields metadata
311
+ # add to dict
312
+ fields_dict[field] = df["frequencies"][0]["assets"]
341
313
 
342
314
  # asset list
343
315
  asset_list = list(set.intersection(*(set(val) for val in fields_dict.values())))
@@ -354,51 +326,67 @@ class CoinMetrics(DataVendor):
354
326
  """
355
327
  return None
356
328
 
357
- @staticmethod
358
- def req_data(data_type: str, **kwargs) -> pd.DataFrame:
329
+ def get_metadata(self) -> None:
330
+ """
331
+ Get CoinMetrics metadata.
332
+ """
333
+ if self.exchanges is None:
334
+ self.get_exchanges_info(as_list=True)
335
+ if self.indexes is None:
336
+ self.get_indexes_info(as_list=True)
337
+ if self.assets is None:
338
+ self.get_assets_info(as_list=True)
339
+ if self.markets is None:
340
+ self.get_markets_info(as_list=True)
341
+ if self.fields is None:
342
+ self.get_fields_info(as_list=True)
343
+
344
+ def req_data(self, data_type: str, params: Dict[str, Union[str, int]]) -> pd.DataFrame:
359
345
  """
360
346
  Sends data request to Python client.
361
347
 
362
348
  Parameters
363
349
  ----------
364
- data_type: str, {'get_index_levels', 'get_institution_metrics', 'get_market_candles', 'get_asset_metrics',
365
- 'get_market_open_interest', 'get_market_funding_rates', 'get_market_trades',
366
- 'get_market_quotes'}
350
+ data_type: str
367
351
  Data type to retrieve.
368
-
369
- Other Parameters
370
- ----------------
371
- indexes: list
372
- List of indexes.
373
- assets: list
374
- List of assets.
375
- markets: list
376
- List of markets.
377
- metrics: list
378
- List of metrics.
379
- frequency: str
380
- Frequency of data observations.
381
- start_time: str, pd.Timestamp, datetime
382
- Start datetime.
383
- end_time: str, pd.Timestamp, datetime
384
- End datetime.
385
- timezone: str
386
- Timezone.
352
+ params: dict
353
+ Dictionary containing parameter values for get request.
387
354
 
388
355
  Returns
389
356
  -------
390
357
  df: pd.DataFrame
391
358
  Dataframe with datetime, ticker/identifier, and field/col values.
392
359
  """
393
- try:
394
- df = getattr(client, data_type)(**kwargs).to_dataframe()
395
- assert not df.empty
360
+ # url
361
+ url = self.base_url + data_type
396
362
 
397
- except Exception as e:
398
- logging.warning(f"Failed to {data_type}.")
399
- logging.warning(e)
363
+ # data request
364
+ data_resp = DataRequest().get_req(url=url, params=params)
400
365
 
366
+ # raise error if data is None
367
+ if data_resp is None:
368
+ raise Exception("Failed to fetch data after multiple attempts.")
369
+ # retrieve data
401
370
  else:
371
+ # data
372
+ data, next_page_url = data_resp.get('data', []), data_resp.get('next_page_url')
373
+
374
+ # while loop
375
+ while next_page_url:
376
+ # wait to avoid exceeding rate limit
377
+ sleep(0.6)
378
+
379
+ # request next page
380
+ next_page_data_resp = DataRequest(pause=0.6).get_req(url=next_page_url, params=None)
381
+ next_page_data, next_page_url = next_page_data_resp.get('data', []), next_page_data_resp.get(
382
+ 'next_page_url')
383
+
384
+ # add data to list
385
+ data.extend(next_page_data)
386
+
387
+ # convert to df
388
+ df = pd.DataFrame(data)
389
+
402
390
  return df
403
391
 
404
392
  @staticmethod
@@ -424,7 +412,7 @@ class CoinMetrics(DataVendor):
424
412
 
425
413
  return df
426
414
 
427
- def get_tidy_data(self, data_req: DataRequest, data_type: str, **kwargs) -> pd.DataFrame:
415
+ def get_tidy_data(self, data_req: DataRequest, data_type: str, params: dict) -> pd.DataFrame:
428
416
  """
429
417
  Gets data and wrangles it into tidy data format.
430
418
 
@@ -436,7 +424,8 @@ class CoinMetrics(DataVendor):
436
424
  'get_market_open_interest', 'get_market_funding_rates', 'get_market_trades',
437
425
  'get_market_quotes'}
438
426
  Data type to retrieve.
439
- **kwargs: other parameters
427
+ params: dict
428
+ Dictionary containing parameter values for get request.
440
429
 
441
430
  Returns
442
431
  -------
@@ -444,15 +433,15 @@ class CoinMetrics(DataVendor):
444
433
  Dataframe with DatetimeIndex (level 0), ticker (level 1) and values for fields/col, in tidy data format.
445
434
  """
446
435
  # get entire data history
447
- df = self.req_data(data_type, **kwargs)
436
+ df = self.req_data(data_type, params)
448
437
  # wrangle df
449
438
  df = self.wrangle_data_resp(data_req, df)
450
439
 
451
440
  return df
452
441
 
453
- def filter_tickers(self, data_req: DataRequest, data_type: str) -> List[str]:
442
+ def check_tickers(self, data_req: DataRequest, data_type: str) -> List[str]:
454
443
  """
455
- Filters tickers to only those with data available.
444
+ Checks tickers for data availability.
456
445
 
457
446
  Parameters
458
447
  ----------
@@ -465,47 +454,45 @@ class CoinMetrics(DataVendor):
465
454
  Returns
466
455
  -------
467
456
  tickers: list
468
- List of filtered tickers.
457
+ List of available tickers.
469
458
  """
470
459
  # convert params
471
460
  cm_data_req = ConvertParams(data_req).to_coinmetrics()
472
461
  # tickers
473
462
  tickers = []
474
463
 
475
- # check if tickers indexes
464
+ # check indexes
476
465
  if data_type == 'indexes':
477
- idx_list, tickers = self.indexes, []
478
- for ticker in cm_data_req["tickers"]:
479
- if ticker.upper() in idx_list:
480
- tickers.append(ticker) # keep only avail tickers
466
+ self.get_indexes_info(as_list=True)
467
+ # avail tickers
468
+ tickers = [ticker for ticker in cm_data_req["tickers"] if ticker.upper() in self.indexes]
481
469
 
482
- # check if tickers assets
470
+ # check markets
483
471
  elif data_type == 'market_candles' or data_type == 'open_interest' or \
484
472
  data_type == 'funding_rates' or data_type == 'trades' or data_type == 'quotes':
485
- asset_list, tickers = self.assets, []
486
- for asset, ticker in zip(cm_data_req["tickers"], cm_data_req["mkts"]):
487
- if asset in asset_list:
488
- tickers.append(ticker) # keep only avail asset tickers
473
+ self.get_assets_info(as_list=True)
474
+ # avail tickers
475
+ tickers = [ticker for asset, ticker in zip(cm_data_req["tickers"], cm_data_req["mkts"]) if
476
+ asset in self.assets]
489
477
 
490
- # check if tickers assets
478
+ # check assets
491
479
  elif data_type == 'asset_metrics':
492
- asset_list, tickers = self.assets, []
493
- for ticker in cm_data_req["tickers"]:
494
- if ticker in asset_list:
495
- tickers.append(ticker) # keep only asset tickers
480
+ self.get_assets_info(as_list=True)
481
+ # avail tickers
482
+ tickers = [ticker for ticker in cm_data_req["tickers"] if ticker in self.assets]
496
483
 
497
- # raise error if no tickers are indexes
484
+ # raise error if no tickers available
498
485
  if len(tickers) == 0:
499
486
  raise ValueError(
500
- f"{data_req.tickers} are not valid tickers for requested data type."
501
- f" Use attributes to get a list of available indexes and assets."
487
+ f"{data_req.tickers} are not valid tickers for the requested data type."
488
+ f" Use get_metadata to get a list of available indexes and assets."
502
489
  )
503
490
 
504
491
  return tickers
505
492
 
506
- def filter_fields(self, data_req: DataRequest, data_type: str) -> List[str]:
493
+ def check_fields(self, data_req: DataRequest, data_type: str) -> List[str]:
507
494
  """
508
- Filters fields to only those with data available.
495
+ Checks fields for data availability.
509
496
 
510
497
  Parameters
511
498
  ----------
@@ -518,31 +505,30 @@ class CoinMetrics(DataVendor):
518
505
  Returns
519
506
  -------
520
507
  fields: list
521
- List of filtered fields.
508
+ List of avaialble fields.
522
509
  """
523
510
  # convert params
524
511
  cm_data_req = ConvertParams(data_req).to_coinmetrics()
525
512
  # fields
526
513
  fields = []
527
514
 
528
- # check if fields inst
515
+ # check instution
529
516
  if data_type == 'institutions':
530
- fields, inst_list = ([], list(self.get_inst_info(as_dict=True).values())[0])
531
- for field in cm_data_req["fields"]:
532
- if field in inst_list:
533
- fields.append(field) # keep only inst fields
517
+ # avail inst
518
+ inst_list = [val for key, val in self.get_inst_info(as_dict=True).items()][0]
519
+ fields = [field for field in cm_data_req["fields"] if field in inst_list]
534
520
 
521
+ # check on-chain metrics
535
522
  elif data_type == 'asset_metrics':
536
- onchain_list, fields = (self.get_fields_info(data_type="on-chain", as_list=True), [])
537
- for field in cm_data_req["fields"]:
538
- if field in onchain_list:
539
- fields.append(field) # keep only on-chain fields
523
+ self.get_fields_info(data_type='on-chain', as_list=True)
524
+ # avail fields
525
+ fields = [field for field in cm_data_req["fields"] if field in self.fields]
540
526
 
541
527
  # raise error if fields is empty
542
528
  if len(fields) == 0:
543
529
  raise ValueError(
544
- f"{data_req.fields} are not valid institution fields."
545
- f" Use the fields property to get a list of available source fields."
530
+ f"{data_req.fields} are not valid fields."
531
+ f" Use the get_fields_info or get_inst_info methods to get available source fields."
546
532
  )
547
533
 
548
534
  return fields
@@ -550,7 +536,7 @@ class CoinMetrics(DataVendor):
550
536
  @staticmethod
551
537
  def check_params(data_req: DataRequest, data_type: str) -> None:
552
538
  """
553
- Checks if valid parameters for request.
539
+ Checks data request parameters.
554
540
 
555
541
  Parameters
556
542
  ----------
@@ -611,14 +597,22 @@ class CoinMetrics(DataVendor):
611
597
  f" 'option' market types. Change 'mkt_type' in data request and try again."
612
598
  )
613
599
 
614
- # trades & quotes
615
- elif data_type == 'trades' or data_type == 'quotes':
616
- if cm_data_req["freq"] != "tick":
600
+ # trades
601
+ elif data_type == 'trades':
602
+ if cm_data_req["freq"] != "raw":
617
603
  raise ValueError(
618
604
  f"{data_type} data is only available at the 'tick' frequency."
619
605
  f" Change data request frequency and try again."
620
606
  )
621
607
 
608
+ # quotes
609
+ elif data_type == 'quotes':
610
+ if cm_data_req["freq"] not in ["raw", "1s", "1m", "1h", "1d"]:
611
+ raise ValueError(
612
+ f"{data_type} data is only available at the 'tick', '1s', '1m', '1h' and '1d' frequencies."
613
+ f" Change data request frequency and try again."
614
+ )
615
+
622
616
  return None
623
617
 
624
618
  def get_indexes(self, data_req: DataRequest) -> pd.DataFrame:
@@ -638,20 +632,27 @@ class CoinMetrics(DataVendor):
638
632
  # convert data request parameters to Coin Metrics format
639
633
  cm_data_req = ConvertParams(data_req).to_coinmetrics()
640
634
 
641
- # check freq
635
+ # check params
642
636
  self.check_params(data_req, data_type='indexes')
643
637
 
644
- # filter tickers
645
- tickers = self.filter_tickers(data_req, data_type='indexes')
638
+ # check tickers
639
+ tickers = self.check_tickers(data_req, data_type='indexes')
640
+ sleep(0.6)
641
+
642
+ # params
643
+ params = {
644
+ 'indexes': ','.join(tickers),
645
+ 'frequency': cm_data_req['freq'],
646
+ 'start_time': cm_data_req["start_date"],
647
+ 'end_time': cm_data_req["end_date"],
648
+ 'pretty': True,
649
+ 'page_size': 10000,
650
+ }
646
651
 
647
- # get indexes
652
+ # get tidy data
648
653
  df = self.get_tidy_data(data_req,
649
- data_type='get_index_levels',
650
- indexes=tickers,
651
- frequency=cm_data_req["freq"],
652
- start_time=cm_data_req["start_date"],
653
- end_time=cm_data_req["end_date"],
654
- )
654
+ data_type='/timeseries/index-levels',
655
+ params=params)
655
656
 
656
657
  return df
657
658
 
@@ -672,21 +673,28 @@ class CoinMetrics(DataVendor):
672
673
  # convert data request parameters to Coin Metrics format
673
674
  cm_data_req = ConvertParams(data_req).to_coinmetrics()
674
675
 
675
- # check freq
676
+ # check params
676
677
  self.check_params(data_req, data_type='institutions')
677
678
 
678
- # filter fields
679
- fields = self.filter_fields(data_req, data_type='institutions')
679
+ # check fields
680
+ fields = self.check_fields(data_req, data_type='institutions')
681
+ sleep(0.6)
682
+
683
+ # params
684
+ params = {
685
+ 'institutions': cm_data_req["inst"],
686
+ 'metrics': ','.join(fields),
687
+ 'frequency': cm_data_req['freq'],
688
+ 'start_time': cm_data_req["start_date"],
689
+ 'end_time': cm_data_req["end_date"],
690
+ 'pretty': True,
691
+ 'page_size': 10000,
692
+ }
680
693
 
681
694
  # get tidy data
682
695
  df = self.get_tidy_data(data_req,
683
- data_type='get_institution_metrics',
684
- institutions=cm_data_req["inst"],
685
- metrics=fields,
686
- frequency=cm_data_req["freq"],
687
- start_time=cm_data_req["start_date"],
688
- end_time=cm_data_req["end_date"],
689
- )
696
+ data_type='/timeseries/institution-metrics',
697
+ params=params)
690
698
 
691
699
  return df
692
700
 
@@ -710,17 +718,24 @@ class CoinMetrics(DataVendor):
710
718
  # check freq
711
719
  self.check_params(data_req, data_type='market_candles')
712
720
 
713
- # filter tickers
714
- tickers = self.filter_tickers(data_req, data_type='market_candles')
721
+ # check tickers
722
+ tickers = self.check_tickers(data_req, data_type='market_candles')
723
+ sleep(0.6)
724
+
725
+ # params
726
+ params = {
727
+ 'markets': ','.join(tickers),
728
+ 'frequency': cm_data_req['freq'],
729
+ 'start_time': cm_data_req["start_date"],
730
+ 'end_time': cm_data_req["end_date"],
731
+ 'pretty': True,
732
+ 'page_size': 10000,
733
+ }
715
734
 
716
735
  # get tidy data
717
736
  df = self.get_tidy_data(data_req,
718
- data_type='get_market_candles',
719
- markets=tickers,
720
- frequency=cm_data_req["freq"],
721
- start_time=cm_data_req["start_date"],
722
- end_time=cm_data_req["end_date"],
723
- )
737
+ data_type='/timeseries/market-candles',
738
+ params=params)
724
739
 
725
740
  return df
726
741
 
@@ -741,22 +756,35 @@ class CoinMetrics(DataVendor):
741
756
  # convert data request parameters to Coin Metrics format
742
757
  cm_data_req = ConvertParams(data_req).to_coinmetrics()
743
758
 
744
- # check freq
759
+ # check params
745
760
  self.check_params(data_req, data_type='asset_metrics')
746
761
 
747
- # filter tickers
748
- tickers = self.filter_tickers(data_req, data_type='asset_metrics')
749
- # filter fields
750
- fields = self.filter_fields(data_req, data_type='asset_metrics')
762
+ # check tickers
763
+ tickers = self.check_tickers(data_req, data_type='asset_metrics')
764
+ sleep(0.6)
765
+
766
+ # check fields
767
+ fields = self.check_fields(data_req, data_type='asset_metrics')
768
+ sleep(0.6)
769
+
770
+ # params
771
+ params = {
772
+ 'assets': ','.join(tickers),
773
+ 'metrics': ','.join(fields),
774
+ 'frequency': cm_data_req['freq'],
775
+ 'start_time': cm_data_req["start_date"],
776
+ 'end_time': cm_data_req["end_date"],
777
+ 'pretty': True,
778
+ 'page_size': 10000,
779
+ 'ignore_forbidden_errors': True,
780
+ 'ignore_unsupported_errors': True
781
+
782
+ }
751
783
 
752
784
  # get tidy data
753
785
  df = self.get_tidy_data(data_req,
754
- data_type='get_asset_metrics',
755
- assets=tickers,
756
- metrics=fields,
757
- frequency=cm_data_req["freq"],
758
- start_time=cm_data_req["start_date"],
759
- end_time=cm_data_req["end_date"],
786
+ data_type='/timeseries/asset-metrics',
787
+ params=params
760
788
  )
761
789
 
762
790
  return df
@@ -778,18 +806,26 @@ class CoinMetrics(DataVendor):
778
806
  # convert data request parameters to Coin Metrics format
779
807
  cm_data_req = ConvertParams(data_req).to_coinmetrics()
780
808
 
781
- # check mkt type
809
+ # check params
782
810
  self.check_params(data_req, data_type='open_interest')
783
811
 
784
- # filter tickers
785
- tickers = self.filter_tickers(data_req, data_type='open_interest')
812
+ # check tickers
813
+ tickers = self.check_tickers(data_req, data_type='open_interest')
814
+ sleep(0.6)
815
+
816
+ # params
817
+ params = {
818
+ 'markets': ','.join(tickers),
819
+ 'start_time': cm_data_req["start_date"],
820
+ 'end_time': cm_data_req["end_date"],
821
+ 'pretty': True,
822
+ 'page_size': 10000,
823
+ }
786
824
 
787
- # get indexes
825
+ # get tidy data
788
826
  df = self.get_tidy_data(data_req,
789
- data_type='get_market_open_interest',
790
- markets=tickers,
791
- start_time=cm_data_req["start_date"],
792
- end_time=cm_data_req["end_date"],
827
+ data_type='/timeseries/market-openinterest',
828
+ params=params
793
829
  )
794
830
 
795
831
  return df
@@ -811,18 +847,26 @@ class CoinMetrics(DataVendor):
811
847
  # convert data request parameters to Coin Metrics format
812
848
  cm_data_req = ConvertParams(data_req).to_coinmetrics()
813
849
 
814
- # check mkt type
850
+ # check params
815
851
  self.check_params(data_req, data_type='funding_rates')
816
852
 
817
- # filter tickers
818
- tickers = self.filter_tickers(data_req, data_type='funding_rates')
853
+ # check tickers
854
+ tickers = self.check_tickers(data_req, data_type='funding_rates')
855
+ sleep(0.6)
819
856
 
820
- # get indexes
857
+ # params
858
+ params = {
859
+ 'markets': ','.join(tickers),
860
+ 'start_time': cm_data_req["start_date"],
861
+ 'end_time': cm_data_req["end_date"],
862
+ 'pretty': True,
863
+ 'page_size': 10000,
864
+ }
865
+
866
+ # get tidy data
821
867
  df = self.get_tidy_data(data_req,
822
- data_type='get_market_funding_rates',
823
- markets=tickers,
824
- start_time=cm_data_req["start_date"],
825
- end_time=cm_data_req["end_date"],
868
+ data_type='/timeseries/market-funding-rates',
869
+ params=params
826
870
  )
827
871
 
828
872
  return df
@@ -844,17 +888,26 @@ class CoinMetrics(DataVendor):
844
888
  # convert data request parameters to Coin Metrics format
845
889
  cm_data_req = ConvertParams(data_req).to_coinmetrics()
846
890
 
847
- # check mkt type
891
+ # check params
848
892
  self.check_params(data_req, data_type='trades')
849
893
 
850
- # filter tickers
851
- tickers = self.filter_tickers(data_req, data_type='trades')
894
+ # check tickers
895
+ tickers = self.check_tickers(data_req, data_type='trades')
896
+ sleep(0.6)
897
+
898
+ # params
899
+ params = {
900
+ 'markets': ','.join(tickers),
901
+ 'start_time': cm_data_req["start_date"],
902
+ 'end_time': cm_data_req["end_date"],
903
+ 'pretty': True,
904
+ 'page_size': 10000,
905
+ }
852
906
 
853
- # get indexes
907
+ # get tidy data
854
908
  df = self.get_tidy_data(data_req,
855
- data_type='get_market_trades',
856
- markets=tickers,
857
- start_time=cm_data_req["start_date"]
909
+ data_type='/timeseries/market-trades',
910
+ params=params
858
911
  )
859
912
 
860
913
  return df
@@ -876,17 +929,27 @@ class CoinMetrics(DataVendor):
876
929
  # convert data request parameters to Coin Metrics format
877
930
  cm_data_req = ConvertParams(data_req).to_coinmetrics()
878
931
 
879
- # check mkt type
932
+ # check params
880
933
  self.check_params(data_req, data_type='quotes')
881
934
 
882
- # filter tickers
883
- tickers = self.filter_tickers(data_req, data_type='quotes')
935
+ # check tickers
936
+ tickers = self.check_tickers(data_req, data_type='quotes')
937
+ sleep(0.6)
938
+
939
+ # params
940
+ params = {
941
+ 'markets': ','.join(tickers),
942
+ 'granularity': cm_data_req['freq'],
943
+ 'start_time': cm_data_req["start_date"],
944
+ 'end_time': cm_data_req["end_date"],
945
+ 'pretty': True,
946
+ 'page_size': 10000,
947
+ }
884
948
 
885
- # get indexes
949
+ # get tidy data
886
950
  df = self.get_tidy_data(data_req,
887
- data_type='get_market_quotes',
888
- markets=tickers,
889
- start_time=cm_data_req["start_date"]
951
+ data_type='/timeseries/market-quotes',
952
+ params=params
890
953
  )
891
954
 
892
955
  return df
@@ -910,20 +973,25 @@ class CoinMetrics(DataVendor):
910
973
  cm_data_req = ConvertParams(data_req).to_coinmetrics()
911
974
 
912
975
  # check if fields available
913
- if not all([field in self.fields for field in cm_data_req["fields"]]):
914
- raise ValueError(
915
- "Some selected fields are not available. Check available fields with"
916
- " fields property and try again."
917
- )
918
-
919
- # fields list
976
+ self.get_fields_info(as_list=True)
977
+ sleep(0.6)
978
+ # if not all([field in self.fields for field in cm_data_req["fields"]]):
979
+ # raise ValueError(
980
+ # "Some selected fields are not available. Check available fields with"
981
+ # " get_fields_info method and try again."
982
+ # )
983
+
984
+ # field lists
920
985
  ohlcv_list = ['price_open', 'price_close', 'price_high', 'price_low', 'vwap', 'volume',
921
986
  'candle_usd_volume', 'candle_trades_count']
922
987
  oc_list = [field for field in self.fields if field not in ohlcv_list]
988
+
923
989
  # empty df
924
990
  df = pd.DataFrame()
925
991
 
926
992
  # get indexes data
993
+ self.get_indexes_info(as_list=True)
994
+ sleep(0.6)
927
995
  if any([ticker.upper() in self.indexes for ticker in cm_data_req["tickers"]]) and any(
928
996
  [field in ohlcv_list for field in cm_data_req["fields"]]
929
997
  ):
@@ -931,6 +999,8 @@ class CoinMetrics(DataVendor):
931
999
  df = pd.concat([df, df0])
932
1000
 
933
1001
  # get OHLCV data
1002
+ self.get_assets_info(as_list=True)
1003
+ sleep(0.6)
934
1004
  if any([ticker in self.assets for ticker in cm_data_req["tickers"]]) and any(
935
1005
  [field in ohlcv_list for field in cm_data_req["fields"]]
936
1006
  ):