cryptodatapy 0.2.10__tar.gz → 0.2.12__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 (62) hide show
  1. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/PKG-INFO +5 -5
  2. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/pyproject.toml +3 -3
  3. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/data_vendors/tiingo_api.py +89 -130
  4. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/transform/convertparams.py +162 -71
  5. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/transform/impute.py +2 -1
  6. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/transform/wrangle.py +14 -13
  7. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/LICENSE +0 -0
  8. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/README.md +0 -0
  9. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/__init__.py +0 -0
  10. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/conf/__init__.py +0 -0
  11. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/conf/fields.csv +0 -0
  12. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/conf/tickers.csv +0 -0
  13. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/__init__.py +0 -0
  14. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/br_econ_calendar.csv +0 -0
  15. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/ca_econ_calendar.csv +0 -0
  16. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/cn_econ_calendar.csv +0 -0
  17. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/de_econ_calendar.csv +0 -0
  18. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/ez_econ_calendar.csv +0 -0
  19. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/fr_econ_calendar.csv +0 -0
  20. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/gb_econ_calendar.csv +0 -0
  21. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/get_econ_calendars.py +0 -0
  22. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/id_econ_calendar.csv +0 -0
  23. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/in_econ_calendar.csv +0 -0
  24. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/it_econ_calendar.csv +0 -0
  25. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/jp_econ_calendar.csv +0 -0
  26. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/kr_econ_calendar.csv +0 -0
  27. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/mx_econ_calendar.csv +0 -0
  28. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/ru_econ_calendar.csv +0 -0
  29. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/tr_econ_calendar.csv +0 -0
  30. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/datasets/us_econ_calendar.csv +0 -0
  31. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/__init__.py +0 -0
  32. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/data_vendors/.ipynb_checkpoints/CCXT-checkpoint.ipynb +0 -0
  33. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/data_vendors/.ipynb_checkpoints/DBNomics-checkpoint.ipynb +0 -0
  34. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/data_vendors/.ipynb_checkpoints/InvestPy-checkpoint.ipynb +0 -0
  35. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/data_vendors/.ipynb_checkpoints/NasdaqDataLink-checkpoint.ipynb +0 -0
  36. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/data_vendors/.ipynb_checkpoints/PandasDataReader-checkpoint.ipynb +0 -0
  37. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/data_vendors/__init__.py +0 -0
  38. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/data_vendors/coinmetrics_api.py +0 -0
  39. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/data_vendors/cryptocompare_api.py +0 -0
  40. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/data_vendors/datavendor.py +0 -0
  41. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/data_vendors/glassnode_api.py +0 -0
  42. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/datarequest.py +0 -0
  43. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/exchanges/__init__.py +0 -0
  44. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/exchanges/dydx.py +0 -0
  45. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/exchanges/exchange.py +0 -0
  46. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/getdata.py +0 -0
  47. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/libraries/__init__.py +0 -0
  48. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/libraries/ccxt_api.py +0 -0
  49. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/libraries/dbnomics_api.py +0 -0
  50. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/libraries/investpy_api.py +0 -0
  51. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/libraries/library.py +0 -0
  52. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/libraries/pandasdr_api.py +0 -0
  53. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/web/__init__.py +0 -0
  54. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/web/aqr.py +0 -0
  55. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/extract/web/web.py +0 -0
  56. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/transform/__init__.py +0 -0
  57. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/transform/clean.py +0 -0
  58. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/transform/filter.py +0 -0
  59. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/transform/od.py +0 -0
  60. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/util/__init__.py +0 -0
  61. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/util/datacatalog.py +0 -0
  62. {cryptodatapy-0.2.10 → cryptodatapy-0.2.12}/src/cryptodatapy/util/datacredentials.py +0 -0
@@ -1,17 +1,17 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: cryptodatapy
3
- Version: 0.2.10
3
+ Version: 0.2.12
4
4
  Summary: Cryptoasset data library
5
5
  License: Apache-2.0
6
6
  Author: Systamental
7
- Requires-Python: >=3.8,<4.0
7
+ Requires-Python: >=3.9,<4.0
8
8
  Classifier: License :: OSI Approved :: Apache Software License
9
9
  Classifier: Programming Language :: Python :: 3
10
- Classifier: Programming Language :: Python :: 3.8
11
10
  Classifier: Programming Language :: Python :: 3.9
12
11
  Classifier: Programming Language :: Python :: 3.10
13
12
  Classifier: Programming Language :: Python :: 3.11
14
13
  Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
15
  Requires-Dist: DBnomics (>=1.2.3)
16
16
  Requires-Dist: ccxt (>=1.91.52)
17
17
  Requires-Dist: coinmetrics-api-client (>=2022.6.17) ; python_version >= "3.7"
@@ -20,7 +20,7 @@ Requires-Dist: investpy (>=1.0.8)
20
20
  Requires-Dist: matplotlib (>=3.5.2)
21
21
  Requires-Dist: numpy (>=1.23.2)
22
22
  Requires-Dist: openpyxl (>=3.1.2)
23
- Requires-Dist: pandas (>=1.4.4)
23
+ Requires-Dist: pandas (>=2.2.3)
24
24
  Requires-Dist: pandas-datareader (>=0.10.0)
25
25
  Requires-Dist: prophet (>=1.1) ; python_version >= "3.7"
26
26
  Requires-Dist: pyarrow (>=17.0.0)
@@ -1,13 +1,13 @@
1
1
  [tool.poetry]
2
2
  name = "cryptodatapy"
3
- version = "0.2.10"
3
+ version = "0.2.12"
4
4
  description = "Cryptoasset data library"
5
5
  authors = ["Systamental"]
6
6
  license = "Apache License 2.0"
7
7
  readme = "README.md"
8
8
 
9
9
  [tool.poetry.dependencies]
10
- python = ">=3.8,<4.0"
10
+ python = ">=3.9,<4.0"
11
11
  matplotlib = ">=3.5.2"
12
12
  requests = {version = ">=2.28.0", python = ">=3.7"}
13
13
  coinmetrics-api-client = {version = ">=2022.6.17", python = ">=3.7"}
@@ -19,7 +19,7 @@ statsmodels = ">=0.13.2"
19
19
  prophet = {version = ">=1.1", python = ">=3.7"}
20
20
  selenium = ">=4.4.3"
21
21
  numpy = ">=1.23.2"
22
- pandas = ">=1.4.4"
22
+ pandas = ">=2.2.3"
23
23
  pandas-datareader = ">=0.10.0"
24
24
  responses = ">=0.21.0"
25
25
  yfinance = ">=0.2.14"
@@ -20,14 +20,15 @@ class Tiingo(DataVendor):
20
20
 
21
21
  def __init__(
22
22
  self,
23
- categories=None,
23
+ categories: List[str] = ["crypto", "fx", "eqty"],
24
24
  exchanges: Optional[Dict[str, List[str]]] = None,
25
25
  indexes: Optional[Dict[str, List[str]]] = None,
26
26
  assets: Optional[Dict[str, List[str]]] = None,
27
27
  markets: Optional[Dict[str, List[str]]] = None,
28
- market_types=None,
28
+ market_types: List[str] = ["spot"],
29
29
  fields: Dict[str, List[str]] = None,
30
- frequencies=None,
30
+ frequencies: List[str] = ["1min", "5min", "10min", "15min", "30min", "1h",
31
+ "2h", "4h", "8h", "d", "w", "m", "q", "y"],
31
32
  base_url: str = data_cred.tiingo_base_url,
32
33
  api_key: str = data_cred.tiingo_api_key,
33
34
  max_obs_per_call: Optional[int] = None,
@@ -71,53 +72,18 @@ class Tiingo(DataVendor):
71
72
  rate_limit: pd.DataFrame, optional, Default None
72
73
  Number of API calls made and left, by time frequency.
73
74
  """
74
- DataVendor.__init__(
75
- self,
76
- categories,
77
- exchanges,
78
- indexes,
79
- assets,
80
- markets,
81
- market_types,
82
- fields,
83
- frequencies,
84
- base_url,
85
- api_key,
86
- max_obs_per_call,
87
- rate_limit,
75
+ super().__init__(
76
+ categories, exchanges, indexes, assets, markets, market_types,
77
+ fields, frequencies, base_url, api_key, max_obs_per_call, rate_limit
88
78
  )
89
79
 
90
- if frequencies is None:
91
- self.frequencies = [
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
- "y",
106
- ]
107
- if market_types is None:
108
- self.market_types = ["spot"]
109
- if categories is None:
110
- self.categories = ["crypto", "fx", "eqty"]
111
80
  if api_key is None:
112
81
  raise TypeError("Set your Tiingo api key in environment variables as 'TIINGO_API_KEY' or "
113
82
  "add it as an argument when instantiating the class. To get an api key, visit: "
114
83
  "https://www.tiingo.com/")
115
- if exchanges is None:
116
- self.exchanges = self.get_exchanges_info()
117
- if assets is None:
118
- self.assets = self.get_assets_info(as_list=True)
119
- if fields is None:
120
- self.fields = self.get_fields_info()
84
+
85
+ self.data_req = None
86
+ self.data = pd.DataFrame()
121
87
 
122
88
  def get_exchanges_info(
123
89
  self, cat: Optional[str] = None
@@ -266,8 +232,10 @@ class Tiingo(DataVendor):
266
232
  """
267
233
  # data req
268
234
  data_resp = self.req_crypto()
235
+
269
236
  # wrangle data resp
270
237
  crypto = pd.DataFrame(data_resp).set_index('ticker')
238
+
271
239
  # as list
272
240
  if as_list:
273
241
  crypto = crypto.index.to_list()
@@ -302,15 +270,15 @@ class Tiingo(DataVendor):
302
270
  crypto = crypto.index.to_list()
303
271
 
304
272
  # add to dict
305
- assets_info = {'eqty': eqty,
273
+ self.assets = {'eqty': eqty,
306
274
  'crypto': crypto,
307
275
  'fx': f"For more information, see FX documentation: {fx_url}."}
308
276
 
309
277
  # filter cat
310
278
  if cat is not None:
311
- assets_info = assets_info[cat]
279
+ self.assets = self.assets[cat]
312
280
 
313
- return assets_info
281
+ return self.assets
314
282
 
315
283
  def get_markets_info(self) -> None:
316
284
  """
@@ -357,16 +325,17 @@ class Tiingo(DataVendor):
357
325
  fx_fields_list = ["open", "high", "low", "close"]
358
326
 
359
327
  # fields dict
360
- fields = {
328
+ self.fields = {
361
329
  "crypto": crypto_fields_list,
362
330
  "fx": fx_fields_list,
363
331
  "eqty": equities_fields_list,
364
332
  }
333
+
365
334
  # fields obj
366
335
  if cat is not None:
367
- fields = fields[cat]
336
+ self.fields = self.fields[cat]
368
337
 
369
- return fields
338
+ return self.fields
370
339
 
371
340
  def get_rate_limit_info(self) -> None:
372
341
  """
@@ -394,21 +363,20 @@ class Tiingo(DataVendor):
394
363
 
395
364
  """
396
365
  # convert data req params
397
- tg_data_req = ConvertParams(data_req).to_tiingo()
366
+ self.data_req = ConvertParams(data_req).to_tiingo()
398
367
 
399
368
  url, params, headers = None, {}, {}
400
369
 
401
370
  # eqty daily
402
371
  if data_type == 'eqty':
403
- url = self.base_url + f"daily/prices"
372
+ url = self.base_url + f"daily/{ticker}/prices"
404
373
  headers = {
405
374
  "Content-Type": "application/json",
406
375
  "Authorization": f"Token {self.api_key}",
407
376
  }
408
377
  params = {
409
- "tickers": ticker,
410
- "startDate": tg_data_req["start_date"],
411
- "endDate": tg_data_req["end_date"],
378
+ "startDate": self.data_req.source_start_date,
379
+ "endDate": self.data_req.source_end_date
412
380
  }
413
381
 
414
382
  # eqty intraday
@@ -419,9 +387,9 @@ class Tiingo(DataVendor):
419
387
  "Authorization": f"Token {self.api_key}",
420
388
  }
421
389
  params = {
422
- "startDate": tg_data_req["start_date"],
423
- "endDate": tg_data_req["end_date"],
424
- "resampleFreq": tg_data_req["freq"],
390
+ "startDate": self.data_req.source_start_date,
391
+ "endDate": self.data_req.source_end_date,
392
+ "resampleFreq": self.data_req.source_freq
425
393
  }
426
394
 
427
395
  # crypto
@@ -433,14 +401,13 @@ class Tiingo(DataVendor):
433
401
  }
434
402
  params = {
435
403
  "tickers": ticker,
436
- "startDate": tg_data_req["start_date"],
437
- "endDate": tg_data_req["end_date"],
438
- "resampleFreq": tg_data_req["freq"],
404
+ "startDate": self.data_req.source_start_date,
405
+ "endDate": self.data_req.source_end_date,
406
+ "resampleFreq": self.data_req.source_freq
439
407
  }
440
408
 
441
409
  # fx
442
410
  elif data_type == 'fx':
443
- # url = f"https://api.tiingo.com/tiingo/fx/{ticker}/prices"
444
411
  url = self.base_url + f"fx/prices"
445
412
  headers = {
446
413
  "Content-Type": "application/json",
@@ -448,9 +415,9 @@ class Tiingo(DataVendor):
448
415
  }
449
416
  params = {
450
417
  "tickers": ticker,
451
- "startDate": tg_data_req["start_date"],
452
- "endDate": tg_data_req["end_date"],
453
- "resampleFreq": tg_data_req["freq"],
418
+ "startDate": self.data_req.source_start_date,
419
+ "endDate": self.data_req.source_end_date,
420
+ "resampleFreq": self.data_req.source_freq
454
421
  }
455
422
 
456
423
  return {'url': url, 'params': params, 'headers': headers}
@@ -526,6 +493,7 @@ class Tiingo(DataVendor):
526
493
  """
527
494
  # get entire data history
528
495
  df = self.req_data(data_req, data_type, ticker)
496
+
529
497
  # wrangle df
530
498
  df = self.wrangle_data_resp(data_req, df, data_type)
531
499
 
@@ -549,19 +517,17 @@ class Tiingo(DataVendor):
549
517
  Dataframe with DatetimeIndex (level 0), ticker (level 1) and values for fields (cols), in tidy data format.
550
518
  """
551
519
  # convert data request parameters to CryptoCompare format
552
- tg_data_req = ConvertParams(data_req).to_tiingo()
520
+ self.data_req = ConvertParams(data_req).to_tiingo()
553
521
 
554
522
  # empty df to add data
555
523
  df = pd.DataFrame()
556
524
 
557
525
  if data_type == 'crypto':
558
- # loop through mkts
559
- for mkt, ticker in zip(tg_data_req['mkts'], data_req.tickers):
526
+ for market, ticker in zip(self.data_req.source_markets, self.data_req.tickers):
560
527
  try:
561
- df0 = self.get_tidy_data(data_req, data_type, mkt)
562
- print(df0)
563
- except Exception:
564
- logging.info(f"Failed to get {data_type} data for {ticker} after many attempts.")
528
+ df0 = self.get_tidy_data(self.data_req, data_type, market)
529
+ except Exception as e:
530
+ logging.info(f"Failed to get {data_type} data for {ticker} after many attempts: {e}.")
565
531
  else:
566
532
  # add ticker to index
567
533
  df0['ticker'] = ticker.upper()
@@ -570,29 +536,27 @@ class Tiingo(DataVendor):
570
536
  df = pd.concat([df, df0])
571
537
 
572
538
  elif data_type == 'fx':
573
- # loop through mkts
574
- for mkt, ticker in zip(tg_data_req['mkts'], data_req.tickers):
539
+ for market, ticker in zip(self.data_req.source_markets, self.data_req.tickers):
575
540
  try:
576
- df0 = self.get_tidy_data(data_req, data_type, mkt)
577
- except Exception:
578
- logging.info(f"Failed to get {data_type} data for {mkt} after many attempts.")
541
+ df0 = self.get_tidy_data(self.data_req, data_type, market)
542
+ except Exception as e:
543
+ logging.info(f"Failed to get {data_type} data for {market} after many attempts: {e}.")
579
544
  else:
580
545
  # add ticker to index
581
- df0['ticker'] = mkt.upper()
546
+ df0['ticker'] = market.upper()
582
547
  df0.set_index(['ticker'], append=True, inplace=True)
583
548
  # concat df and df1
584
549
  df = pd.concat([df, df0])
585
550
 
586
551
  else:
587
- # loop through mkts
588
- for tg_ticker, dr_ticker in zip(tg_data_req['tickers'], data_req.tickers):
552
+ for ticker in self.data_req.tickers:
589
553
  try:
590
- df0 = self.get_tidy_data(data_req, data_type, tg_ticker)
591
- except Exception:
592
- logging.info(f"Failed to get {data_type} data for {dr_ticker} after many attempts.")
554
+ df0 = self.get_tidy_data(self.data_req, data_type, ticker)
555
+ except Exception as e:
556
+ logging.info(f"Failed to get {data_type} data for {ticker} after many attempts: {e}.")
593
557
  else:
594
558
  # add ticker to index
595
- df0['ticker'] = dr_ticker.upper()
559
+ df0['ticker'] = ticker.upper()
596
560
  df0.set_index(['ticker'], append=True, inplace=True)
597
561
  # concat df and df1
598
562
  df = pd.concat([df, df0])
@@ -614,19 +578,17 @@ class Tiingo(DataVendor):
614
578
  DataFrame with DatetimeIndex (level 0), ticker (level 1) and equities OHLCV values (cols).
615
579
  """
616
580
  # convert data request parameters to CryptoCompare format
617
- tg_data_req = ConvertParams(data_req).to_tiingo()
581
+ self.data_req = ConvertParams(data_req).to_tiingo()
618
582
 
619
- # check tickers
620
- if any([ticker.upper() in self.assets['eqty'] for ticker in tg_data_req['tickers']]) and \
621
- any([field in self.fields['eqty'] for field in data_req.fields]):
622
- try:
623
- df = self.get_all_tickers(data_req, data_type='eqty')
583
+ # get eqty data
584
+ try:
585
+ df = self.get_all_tickers(self.data_req, data_type='eqty')
624
586
 
625
- except Exception as e:
626
- logging.warning(e)
587
+ except Exception as e:
588
+ logging.warning(e)
627
589
 
628
- else:
629
- return df
590
+ else:
591
+ return df
630
592
 
631
593
  def get_eqty_iex(self, data_req: DataRequest) -> pd.DataFrame:
632
594
  """
@@ -643,19 +605,17 @@ class Tiingo(DataVendor):
643
605
  DataFrame with DatetimeIndex (level 0), ticker (level 1) and equities OHLCV values (cols).
644
606
  """
645
607
  # convert data request parameters to CryptoCompare format
646
- tg_data_req = ConvertParams(data_req).to_tiingo()
608
+ self.data_req = ConvertParams(data_req).to_tiingo()
647
609
 
648
- # check tickers
649
- if any([ticker.upper() in self.assets['eqty'] for ticker in tg_data_req['tickers']]) and \
650
- any([field in self.fields['eqty'] for field in data_req.fields]):
651
- try:
652
- df = self.get_all_tickers(data_req, data_type='iex')
610
+ # get iex data
611
+ try:
612
+ df = self.get_all_tickers(self.data_req, data_type='iex')
653
613
 
654
- except Exception as e:
655
- logging.warning(e)
614
+ except Exception as e:
615
+ logging.warning(e)
656
616
 
657
- else:
658
- return df
617
+ else:
618
+ return df
659
619
 
660
620
  def get_crypto(self, data_req: DataRequest) -> pd.DataFrame:
661
621
  """
@@ -672,20 +632,17 @@ class Tiingo(DataVendor):
672
632
  DataFrame with DatetimeIndex (level 0), ticker (level 1) and crypto OHLCV values (cols).
673
633
  """
674
634
  # convert data request parameters to CryptoCompare format
675
- tg_data_req = ConvertParams(data_req).to_tiingo()
635
+ self.data_req = ConvertParams(data_req).to_tiingo()
676
636
 
677
- # check tickers
678
- if any([ticker in self.assets['crypto'] for ticker in tg_data_req['mkts']]) and \
679
- any([field in self.fields['crypto'] for field in data_req.fields]):
680
-
681
- try:
682
- df = self.get_all_tickers(data_req, data_type='crypto')
637
+ # get crypto data
638
+ try:
639
+ df = self.get_all_tickers(self.data_req, data_type='crypto')
683
640
 
684
- except Exception as e:
685
- logging.warning(e)
641
+ except Exception as e:
642
+ logging.warning(e)
686
643
 
687
- else:
688
- return df
644
+ else:
645
+ return df
689
646
 
690
647
  def get_fx(self, data_req: DataRequest) -> pd.DataFrame:
691
648
  """
@@ -702,19 +659,17 @@ class Tiingo(DataVendor):
702
659
  DataFrame with DatetimeIndex (level 0), ticker (level 1) and FX OHLC values (cols).
703
660
  """
704
661
  # convert data request parameters to CryptoCompare format
705
- tg_data_req = ConvertParams(data_req).to_tiingo()
662
+ self.data_req = ConvertParams(data_req).to_tiingo()
706
663
 
707
- # check tickers
708
- if any([field in self.fields['fx'] for field in data_req.fields]):
709
-
710
- try:
711
- df = self.get_all_tickers(data_req, data_type='fx')
664
+ # get fx data
665
+ try:
666
+ df = self.get_all_tickers(self.data_req, data_type='fx')
712
667
 
713
- except Exception as e:
714
- logging.warning(e)
668
+ except Exception as e:
669
+ logging.warning(e)
715
670
 
716
- else:
717
- return df
671
+ else:
672
+ return df
718
673
 
719
674
  def check_params(self, data_req: DataRequest) -> None:
720
675
  """
@@ -722,23 +677,27 @@ class Tiingo(DataVendor):
722
677
  and improve efficiency.
723
678
 
724
679
  """
725
- tg_data_req = ConvertParams(data_req).to_tiingo()
680
+ self.data_req = ConvertParams(data_req).to_tiingo()
681
+
682
+ # get metada
683
+ self.get_assets_info(as_list=True)
684
+ self.get_fields_info()
726
685
 
727
686
  # check cat
728
- if data_req.cat is None:
687
+ if self.data_req.cat is None:
729
688
  raise ValueError(
730
689
  f"Cat cannot be None. Please provide category. Categories include: {self.categories}."
731
690
  )
732
691
 
733
692
  # check assets
734
- if not any([ticker.upper() in self.assets[data_req.cat] for ticker in tg_data_req['tickers']]) and \
693
+ if not any([ticker.upper() in self.assets[self.data_req.cat] for ticker in self.data_req.tickers]) and \
735
694
  data_req.cat != 'fx':
736
695
  raise ValueError(
737
696
  f"Selected tickers are not available. Use assets attribute to see available tickers."
738
697
  )
739
698
 
740
- # check fields
741
- if not any([field in self.fields[data_req.cat] for field in data_req.fields]):
699
+ # check fields
700
+ if not any([field in self.fields[data_req.cat] for field in self.data_req.fields]):
742
701
  raise ValueError(
743
702
  f"Selected fields are not available. Use fields attribute to see available fields."
744
703
  )
@@ -339,34 +339,31 @@ class ConvertParams:
339
339
  "source_fields": self.data_req.source_fields,
340
340
  }
341
341
 
342
- def to_tiingo(self) -> Dict[str, Union[list, str, int, float, datetime, None]]:
342
+ def to_tiingo(self) -> DataRequest:
343
343
  """
344
344
  Convert tickers from CryptoDataPy to Tiingo format.
345
345
  """
346
- # convert tickers
347
- if self.data_req.source_tickers is not None:
348
- tickers = self.data_req.source_tickers
349
- self.data_req.tickers = self.data_req.source_tickers
350
- else:
351
- tickers = [ticker.lower() for ticker in self.data_req.tickers]
352
- # convert freq
353
- if self.data_req.source_freq is not None:
354
- freq = self.data_req.source_freq
355
- self.data_req.freq = self.data_req.source_freq
356
- else:
346
+ # tickers
347
+ if self.data_req.source_tickers is None:
348
+ self.data_req.source_tickers = [ticker.lower() for ticker in self.data_req.tickers]
349
+
350
+ # freq
351
+ if self.data_req.source_freq is None:
357
352
  if self.data_req.freq is None:
358
- freq = "1day"
353
+ self.data_req.source_freq = "1day"
359
354
  elif self.data_req.freq[-3:] == "min":
360
- freq = self.data_req.freq
355
+ self.data_req.source_freq = self.data_req.freq
361
356
  elif self.data_req.freq[-1] == "h":
362
- freq = "1hour"
357
+ self.data_req.source_freq = "1hour"
363
358
  else:
364
- freq = "1day"
365
- # convert quote ccy
359
+ self.data_req.source_freq = "1day"
360
+
361
+ # quote ccy
366
362
  if self.data_req.quote_ccy is None:
367
- quote_ccy = "usd"
363
+ self.data_req.quote_ccy = "usd"
368
364
  else:
369
- quote_ccy = self.data_req.quote_ccy.lower()
365
+ self.data_req.quote_ccy = self.data_req.quote_ccy.lower()
366
+
370
367
  # convert exch
371
368
  if (
372
369
  self.data_req.exch is None
@@ -374,64 +371,40 @@ class ConvertParams:
374
371
  and self.data_req.freq
375
372
  in ["1min", "5min", "10min", "15min", "30min", "1h", "2h", "4h", "8h"]
376
373
  ):
377
- exch = "iex"
378
- else:
379
- exch = self.data_req.exch
380
- # convert tickers to mkts
381
- mkts_list = []
382
- if self.data_req.source_tickers is not None:
383
- mkts_list = self.data_req.source_tickers
384
- self.data_req.tickers = self.data_req.source_tickers
385
- else:
386
- if self.data_req.cat == "fx":
387
- fx_list = self.convert_fx_tickers(quote_ccy=quote_ccy)
388
- mkts_list = [ticker.lower().replace("/", "") for ticker in fx_list]
389
- elif self.data_req.cat == "crypto":
390
- mkts_list = [
391
- ticker.lower() + quote_ccy for ticker in self.data_req.tickers
392
- ]
393
- # convert start date
394
- if self.data_req.start_date is None and self.data_req.cat == 'crypto':
395
- start_date = datetime(2010, 1, 1, 0, 0)
374
+ self.data_req.exch = "iex"
375
+
376
+ # markets
377
+ if self.data_req.source_markets is None:
378
+ if self.data_req.cat == 'fx':
379
+ fx_list = self.convert_fx_tickers(quote_ccy=self.data_req.quote_ccy)
380
+ self.data_req.source_markets = [ticker.lower().replace("/", "") for ticker in fx_list]
381
+ elif self.data_req.cat == 'crypto':
382
+ self.data_req.source_markets = [ticker.lower() +
383
+ self.data_req.quote_ccy for ticker in self.data_req.tickers]
384
+
385
+ # start date
386
+ if self.data_req.start_date is None:
387
+ self.data_req.source_start_date = '1990-01-01'
396
388
  else:
397
- start_date = self.data_req.start_date
398
- # convert end date
389
+ self.data_req.source_start_date = self.data_req.start_date
390
+
391
+ # end date
399
392
  if self.data_req.end_date is None:
400
- end_date = pd.Timestamp.utcnow()
393
+ self.data_req.source_end_date = str(pd.Timestamp.utcnow().date())
401
394
  else:
402
- end_date = self.data_req.end_date
403
- # convert fields
404
- if self.data_req.source_fields is not None:
405
- fields = self.data_req.source_fields
406
- self.data_req.fields = self.data_req.source_fields
407
- else:
408
- fields = self.convert_fields(data_source='tiingo')
395
+ self.data_req.source_end_date = self.data_req.end_date
396
+
397
+ # fields
398
+ if self.data_req.source_fields is None:
399
+ self.data_req.source_fields = self.convert_fields(data_source='tiingo')
400
+
409
401
  # tz
410
402
  if self.data_req.cat == 'eqty' or self.data_req.cat == 'fx':
411
- tz = "America/New_York"
403
+ self.data_req.tz = "America/New_York"
412
404
  else:
413
- tz = "UTC"
405
+ self.data_req.tz = "UTC"
414
406
 
415
- return {
416
- "tickers": tickers,
417
- "freq": freq,
418
- "quote_ccy": quote_ccy,
419
- "exch": exch,
420
- "ctys": None,
421
- "mkt_type": self.data_req.mkt_type,
422
- "mkts": mkts_list,
423
- "start_date": start_date,
424
- "end_date": end_date,
425
- "fields": fields,
426
- "tz": tz,
427
- "inst": None,
428
- "cat": self.data_req.cat,
429
- "trials": self.data_req.trials,
430
- "pause": self.data_req.pause,
431
- "source_tickers": self.data_req.source_tickers,
432
- "source_freq": self.data_req.source_freq,
433
- "source_fields": self.data_req.source_fields,
434
- }
407
+ return self.data_req
435
408
 
436
409
  def to_ccxt(self) -> DataRequest:
437
410
  """
@@ -1020,7 +993,7 @@ class ConvertParams:
1020
993
  List of fields in data source format.
1021
994
 
1022
995
  """
1023
- # get fields
996
+ # x fields
1024
997
  with resources.path("cryptodatapy.conf", "fields.csv") as f:
1025
998
  fields_dict_path = f
1026
999
  fields_df, fields_list = (
@@ -1045,3 +1018,121 @@ class ConvertParams:
1045
1018
  )
1046
1019
 
1047
1020
  return fields_list
1021
+
1022
+ def to_dydx_dict(self) -> Dict[str, Union[list, str, int, float, None]]:
1023
+ """
1024
+ Convert parameters from CryptoDataPy to dYdX format.
1025
+ """
1026
+ if self.data_req.source_tickers is not None:
1027
+ tickers = self.data_req.source_tickers
1028
+ self.data_req.tickers = self.data_req.source_tickers
1029
+ else:
1030
+ tickers = [ticker.upper() for ticker in self.data_req.tickers]
1031
+
1032
+ # convert markets (if needed)
1033
+ markets = [f"{ticker}-USD" for ticker in tickers]
1034
+
1035
+ # convert freq
1036
+ if self.data_req.source_freq is not None:
1037
+ freq = self.data_req.source_freq
1038
+ self.data_req.freq = self.data_req.source_freq
1039
+ else:
1040
+ if self.data_req.freq is None:
1041
+ freq = "1DAY"
1042
+ elif self.data_req.freq == "1min":
1043
+ freq = "1MIN"
1044
+ elif self.data_req.freq == "5min":
1045
+ freq = "5MINS"
1046
+ elif self.data_req.freq == "15min":
1047
+ freq = "15MINS"
1048
+ elif self.data_req.freq == "30min":
1049
+ freq = "30MINS"
1050
+ elif self.data_req.freq == "1h":
1051
+ freq = "1HOUR"
1052
+ elif self.data_req.freq == "4h":
1053
+ freq = "4HOURS"
1054
+ elif self.data_req.freq in ["1d", "d"]:
1055
+ freq = "1DAY"
1056
+ else:
1057
+ freq = "1DAY" # Default to daily
1058
+
1059
+ # convert fields
1060
+ if self.data_req.source_fields is not None:
1061
+ fields = self.data_req.source_fields
1062
+ self.data_req.fields = self.data_req.source_fields
1063
+ else:
1064
+ # Map our standard fields to dYdX field names
1065
+ field_mapping = {
1066
+ 'open': 'open',
1067
+ 'high': 'high',
1068
+ 'low': 'low',
1069
+ 'close': 'close',
1070
+ 'volume': 'baseTokenVolume',
1071
+ 'funding_rate': 'nextFundingRate',
1072
+ 'oi': 'openInterest'
1073
+ }
1074
+
1075
+ fields = []
1076
+ for field in self.data_req.fields:
1077
+ if field in field_mapping:
1078
+ fields.append(field_mapping[field])
1079
+ else:
1080
+ logging.warning(f"Field {field} not available in dYdX API")
1081
+ return {
1082
+ "tickers": tickers, # List of market tickers
1083
+ "freq": freq, # Converted frequency
1084
+ "quote_ccy": self.data_req.quote_ccy,
1085
+ "exch": "dydx",
1086
+ "mkt_type": self.data_req.mkt_type,
1087
+ "mkts": markets, # Market identifiers
1088
+ "start_date": self.data_req.start_date,
1089
+ "end_date": self.data_req.end_date,
1090
+ "fields": fields, # Converted field names
1091
+ "tz": self.data_req.tz or "UTC",
1092
+ "cat": "crypto",
1093
+ "trials": self.data_req.trials,
1094
+ "pause": self.data_req.pause,
1095
+ "source_tickers": self.data_req.source_tickers,
1096
+ "source_freq": self.data_req.source_freq,
1097
+ "source_fields": self.data_req.source_fields,
1098
+ }
1099
+
1100
+ def to_dydx(self) -> DataRequest:
1101
+
1102
+ # tickers
1103
+ if self.data_req.source_tickers is None:
1104
+ self.data_req.source_tickers = [ticker.upper() for ticker in self.data_req.tickers]
1105
+
1106
+ # markets
1107
+ if self.data_req.source_markets is None:
1108
+ self.data_req.source_markets = [f"{ticker}-USD"
1109
+ for ticker in self.data_req.source_tickers]
1110
+
1111
+ if self.data_req.source_freq is None:
1112
+ if self.data_req.freq is None:
1113
+ self.data_req.source_freq = "1DAY"
1114
+ elif self.data_req.freq == "1min":
1115
+ self.data_req.source_freq = "1MIN"
1116
+ elif self.data_req.freq == "5min":
1117
+ self.data_req.source_freq = "5MINS"
1118
+ elif self.data_req.freq == "15min":
1119
+ self.data_req.source_freq = "15MINS"
1120
+ elif self.data_req.freq == "30min":
1121
+ self.data_req.source_freq = "30MINS"
1122
+ elif self.data_req.freq == "1h":
1123
+ self.data_req.source_freq = "1HOUR"
1124
+ elif self.data_req.freq == "4h":
1125
+ self.data_req.source_freq = "4HOURS"
1126
+ elif self.data_req.freq in ["1d", "d"]:
1127
+ self.data_req.source_freq = "1DAY"
1128
+
1129
+ field_mapping = {
1130
+ 'open': 'open',
1131
+ 'high': 'high',
1132
+ 'low': 'low',
1133
+ 'close': 'close',
1134
+ 'volume': 'baseTokenVolume',
1135
+ 'funding_rate': 'nextFundingRate',
1136
+ 'oi': 'openInterest'
1137
+ }
1138
+ return self.data_req
@@ -121,7 +121,8 @@ class Impute:
121
121
  self.imputed_df = pd.DataFrame(imp_yhat, index=self.filtered_df.index, columns=self.filtered_df.columns)
122
122
 
123
123
  # type conversion
124
- self.imputed_df = self.imputed_df.apply(pd.to_numeric, errors="ignore").convert_dtypes()
124
+ self.imputed_df = self.imputed_df.convert_dtypes()
125
+
125
126
 
126
127
  # plot
127
128
  if self.plot:
@@ -640,27 +640,34 @@ class WrangleData:
640
640
 
641
641
  """
642
642
  # create df
643
- if data_type == 'eqty' or data_type == 'crypto':
643
+ if data_type == 'crypto':
644
644
  self.data_resp = pd.DataFrame(self.data_resp[0]['priceData'])
645
645
  else:
646
646
  self.data_resp = pd.DataFrame(self.data_resp)
647
+
647
648
  # convert fields to lib
648
649
  self.convert_fields_to_lib(data_source='tiingo')
650
+
649
651
  # convert to datetime
650
652
  self.data_resp['date'] = pd.to_datetime(self.data_resp['date'])
653
+
651
654
  # set index
652
655
  self.data_resp = self.data_resp.set_index('date').sort_index()
653
656
  self.data_resp.index = self.data_resp.index.tz_localize(None)
657
+
654
658
  # resample
655
659
  self.data_resp = self.data_resp.resample(self.data_req.freq).last()
660
+
656
661
  # reformat index
657
662
  if self.data_req.freq in ['d', 'w', 'm', 'q']:
658
663
  self.data_resp.reset_index(inplace=True)
659
664
  self.data_resp.date = pd.to_datetime(self.data_resp.date.dt.date)
660
665
  # reset index
661
666
  self.data_resp.set_index('date', inplace=True)
667
+
662
668
  # type conversion
663
- self.data_resp = self.data_resp.apply(pd.to_numeric, errors='coerce').convert_dtypes()
669
+ self.data_resp = self.data_resp.convert_dtypes()
670
+
664
671
  # remove bad data
665
672
  self.data_resp = self.data_resp[~self.data_resp.index.duplicated()] # duplicate rows
666
673
  self.data_resp = self.data_resp.dropna(how='all').dropna(how='all', axis=1) # entire row or col NaNs
@@ -911,13 +918,10 @@ class WrangleData:
911
918
  # tickers
912
919
  tickers_dict = {source_ticker: ticker for source_ticker, ticker in zip(self.data_req.source_tickers,
913
920
  self.data_req.tickers)}
914
- if len(self.data_req.tickers) == 1:
915
- self.data_resp['Ticker'] = self.data_req.tickers[0]
916
- else:
917
- self.data_resp = self.data_resp.stack()
918
- self.data_resp.index.names = ['Date', 'Ticker']
919
- self.data_resp.index = self.data_resp.index.set_levels(self.data_resp.index.levels[1].map(tickers_dict),
920
- level=1)
921
+ self.data_resp = self.data_resp.stack(future_stack=True)
922
+ self.data_resp.columns.name = None
923
+ self.data_resp.index = self.data_resp.index.set_levels(self.data_resp.index.levels[1].map(tickers_dict),
924
+ level=1)
921
925
  self.data_resp.reset_index(inplace=True)
922
926
 
923
927
  # fields
@@ -932,11 +936,8 @@ class WrangleData:
932
936
  resample(self.data_req.freq, level='date').\
933
937
  last().swaplevel('ticker', 'date').sort_index()
934
938
 
935
- # re-order cols
936
- self.data_resp = self.data_resp.loc[:, ['open', 'high', 'low', 'close', 'close_adj', 'volume']]
937
-
938
939
  # type conversion
939
- self.data_resp = self.data_resp.apply(pd.to_numeric, errors='coerce').convert_dtypes()
940
+ self.data_resp = self.data_resp.convert_dtypes()
940
941
 
941
942
  # remove bad data
942
943
  self.data_resp = self.data_resp[self.data_resp != 0] # 0 values
File without changes
File without changes