alpaca-py-nopandas 0.1.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.
Files changed (62) hide show
  1. alpaca/__init__.py +2 -0
  2. alpaca/broker/__init__.py +8 -0
  3. alpaca/broker/client.py +2360 -0
  4. alpaca/broker/enums.py +528 -0
  5. alpaca/broker/models/__init__.py +7 -0
  6. alpaca/broker/models/accounts.py +347 -0
  7. alpaca/broker/models/cip.py +265 -0
  8. alpaca/broker/models/documents.py +159 -0
  9. alpaca/broker/models/funding.py +114 -0
  10. alpaca/broker/models/journals.py +71 -0
  11. alpaca/broker/models/rebalancing.py +80 -0
  12. alpaca/broker/models/trading.py +13 -0
  13. alpaca/broker/requests.py +1135 -0
  14. alpaca/common/__init__.py +6 -0
  15. alpaca/common/constants.py +13 -0
  16. alpaca/common/enums.py +64 -0
  17. alpaca/common/exceptions.py +47 -0
  18. alpaca/common/models.py +21 -0
  19. alpaca/common/requests.py +82 -0
  20. alpaca/common/rest.py +438 -0
  21. alpaca/common/types.py +7 -0
  22. alpaca/common/utils.py +89 -0
  23. alpaca/data/__init__.py +5 -0
  24. alpaca/data/enums.py +184 -0
  25. alpaca/data/historical/__init__.py +13 -0
  26. alpaca/data/historical/corporate_actions.py +76 -0
  27. alpaca/data/historical/crypto.py +299 -0
  28. alpaca/data/historical/news.py +63 -0
  29. alpaca/data/historical/option.py +230 -0
  30. alpaca/data/historical/screener.py +72 -0
  31. alpaca/data/historical/stock.py +226 -0
  32. alpaca/data/historical/utils.py +30 -0
  33. alpaca/data/live/__init__.py +11 -0
  34. alpaca/data/live/crypto.py +168 -0
  35. alpaca/data/live/news.py +62 -0
  36. alpaca/data/live/option.py +88 -0
  37. alpaca/data/live/stock.py +199 -0
  38. alpaca/data/live/websocket.py +390 -0
  39. alpaca/data/mappings.py +84 -0
  40. alpaca/data/models/__init__.py +7 -0
  41. alpaca/data/models/bars.py +83 -0
  42. alpaca/data/models/base.py +45 -0
  43. alpaca/data/models/corporate_actions.py +309 -0
  44. alpaca/data/models/news.py +90 -0
  45. alpaca/data/models/orderbooks.py +59 -0
  46. alpaca/data/models/quotes.py +78 -0
  47. alpaca/data/models/screener.py +68 -0
  48. alpaca/data/models/snapshots.py +132 -0
  49. alpaca/data/models/trades.py +204 -0
  50. alpaca/data/requests.py +580 -0
  51. alpaca/data/timeframe.py +148 -0
  52. alpaca/py.typed +0 -0
  53. alpaca/trading/__init__.py +5 -0
  54. alpaca/trading/client.py +784 -0
  55. alpaca/trading/enums.py +412 -0
  56. alpaca/trading/models.py +697 -0
  57. alpaca/trading/requests.py +604 -0
  58. alpaca/trading/stream.py +225 -0
  59. alpaca_py_nopandas-0.1.0.dist-info/LICENSE +201 -0
  60. alpaca_py_nopandas-0.1.0.dist-info/METADATA +299 -0
  61. alpaca_py_nopandas-0.1.0.dist-info/RECORD +62 -0
  62. alpaca_py_nopandas-0.1.0.dist-info/WHEEL +4 -0
alpaca/common/utils.py ADDED
@@ -0,0 +1,89 @@
1
+ from typing import Union, Optional
2
+ from uuid import UUID
3
+ from datetime import datetime
4
+
5
+
6
+ def validate_uuid_id_param(
7
+ id: Union[UUID, str],
8
+ var_name: Optional[str] = None,
9
+ ) -> UUID:
10
+ """
11
+ A small helper function to eliminate duplicate checks of various id parameters to ensure they are
12
+ valid UUIDs. Upcasts str instances that are valid UUIDs into UUID instances.
13
+
14
+ Args:
15
+ id (Union[UUID, str]): The parameter to be validated
16
+ var_name (Optional[str]): the name of the parameter you'd like to generate in the error message. Defaults to
17
+ using `account_id` due to it being the most commonly needed case
18
+
19
+ Returns:
20
+ UUID: The valid UUID instance
21
+ """
22
+
23
+ if var_name is None:
24
+ var_name = "account_id"
25
+
26
+ # should raise ValueError
27
+ if type(id) == str:
28
+ id = UUID(id)
29
+ elif type(id) != UUID:
30
+ raise ValueError(f"{var_name} must be a UUID or a UUID str")
31
+
32
+ return id
33
+
34
+
35
+ def validate_symbol_or_asset_id(
36
+ symbol_or_asset_id: Union[UUID, str]
37
+ ) -> Union[UUID, str]:
38
+ """
39
+ A helper function to eliminate duplicate checks of symbols or asset ids.
40
+
41
+ If the argument given is a string, assumed to be a symbol name. If a UUID object, assumed to be an asset id.
42
+ ValueError if neither type.
43
+
44
+ Args:
45
+ symbol_or_asset_id: String representing a symbol name or a UUID representing an asset id.
46
+
47
+ Returns:
48
+ String if symbol, UUID if asset id.
49
+ """
50
+ if isinstance(symbol_or_asset_id, (UUID, str)):
51
+ return symbol_or_asset_id
52
+ raise ValueError(
53
+ "symbol_or_asset_id must be a UUID of an asset id or a string of a symbol."
54
+ )
55
+
56
+
57
+ def validate_symbol_or_contract_id(
58
+ symbol_or_contract_id: Union[UUID, str]
59
+ ) -> Union[UUID, str]:
60
+ """
61
+ A helper function to eliminate duplicate checks of symbols or contract id.
62
+
63
+ If the argument given is a string, assumed to be a symbol name. If a UUID object, assumed to be a contract id.
64
+ ValueError if neither type.
65
+
66
+ Args:
67
+ symbol_or_contract_id: String representing a symbol name or a UUID representing a contract id.
68
+
69
+ Returns:
70
+ String if symbol, UUID if contract id.
71
+ """
72
+ if isinstance(symbol_or_contract_id, (UUID, str)):
73
+ return symbol_or_contract_id
74
+ raise ValueError(
75
+ "symbol_or_contract_id must be a UUID of a contract id or a string of a symbol."
76
+ )
77
+
78
+
79
+ def tz_aware(dt: datetime) -> bool:
80
+ """
81
+ Returns if a given datetime is timezone aware
82
+
83
+ Args:
84
+ dt: the datetime to bo checked
85
+
86
+ Returns: timezone awareness
87
+
88
+ """
89
+ return dt.tzinfo is not None and dt.tzinfo.utcoffset(dt) is not None
@@ -0,0 +1,5 @@
1
+ from alpaca.data.enums import *
2
+ from alpaca.data.models import *
3
+ from alpaca.data.timeframe import *
4
+ from alpaca.data.requests import *
5
+ from alpaca.data.historical import *
alpaca/data/enums.py ADDED
@@ -0,0 +1,184 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Exchange(str, Enum):
5
+ """The exchanges that provide data feeds to Alpaca.
6
+
7
+ Attributes:
8
+ Z (str): Cboe BZ
9
+ I (str): International Securities Exchange
10
+ M (str): Chicago Stock Exchange
11
+ U (str): Members Exchange
12
+ L (str): Long Term Stock Exchange
13
+ W (str): CBOE
14
+ X (str): NASDAQ OMX PSX
15
+ B (str): NASDAQ OMX BX
16
+ D (str): FINRA ADF
17
+ J (str): Cboe EDGA
18
+ P (str): NYSE Arca
19
+ Q (str): NASDAQ OMX
20
+ S (str): NASDAQ Small Cap
21
+ V (str): IEX
22
+ A (str): NYSE American (AMEX)
23
+ E (str): Market Independent
24
+ N (str): New York Stock Exchange
25
+ T (str): NASDAQ Int
26
+ Y (str): Cboe BYX
27
+ C (str): National Stock Exchange
28
+ H (str): MIAX
29
+ K (str): Cboe EDGX
30
+ """
31
+
32
+ Z = "Z"
33
+ I = "I"
34
+ M = "M"
35
+ U = "U"
36
+ L = "L"
37
+ W = "W"
38
+ X = "X"
39
+ B = "B"
40
+ D = "D"
41
+ J = "J"
42
+ P = "P"
43
+ Q = "Q"
44
+ S = "S"
45
+ V = "V"
46
+ A = "A"
47
+ E = "E"
48
+ N = "N"
49
+ T = "T"
50
+ Y = "Y"
51
+ C = "C"
52
+ H = "H"
53
+ K = "K"
54
+
55
+
56
+ class DataFeed(str, Enum):
57
+ """Equity market data feeds. OTC and SIP are available with premium data subscriptions.
58
+
59
+ Attributes:
60
+ IEX (str): Investor's exchange data feed
61
+ SIP (str): Securities Information Processor feed
62
+ DELAYED_SIP (str): SIP data with a 15 minute delay
63
+ OTC (str): Over the counter feed
64
+ BOATS (str): Blue Ocean, overnight US trading data
65
+ OVERNIGHT (str): derived overnight US trading data
66
+ """
67
+
68
+ IEX = "iex"
69
+ SIP = "sip"
70
+ DELAYED_SIP = "delayed_sip"
71
+ OTC = "otc"
72
+ BOATS = "boats"
73
+ OVERNIGHT = "overnight"
74
+
75
+
76
+ class Adjustment(str, Enum):
77
+ """Data normalization based on types of corporate actions.
78
+
79
+ Attributes:
80
+ RAW (str): Unadjusted data
81
+ SPLIT (str): Stock-split adjusted data
82
+ DIVIDEND (str): Dividend adjusted data
83
+ ALL (str): Data adjusted for all corporate actions
84
+ """
85
+
86
+ RAW = "raw"
87
+ SPLIT = "split"
88
+ DIVIDEND = "dividend"
89
+ ALL = "all"
90
+
91
+
92
+ class CryptoFeed(str, Enum):
93
+ """
94
+ Crypto location
95
+
96
+ Attributes:
97
+ US (str): United States crypto feed
98
+ """
99
+
100
+ US = "us"
101
+
102
+
103
+ class OptionsFeed(str, Enum):
104
+ """
105
+ The source feed of the data.
106
+ `opra` requires subscription
107
+
108
+ Attributes:
109
+ OPRA (str): Options Price Reporting Authority
110
+ INDICATIVE (str): Indicative data
111
+ """
112
+
113
+ OPRA = "opra"
114
+ INDICATIVE = "indicative"
115
+
116
+
117
+ class MostActivesBy(str, Enum):
118
+ """
119
+ Most actives possible filters.
120
+
121
+ Attributes:
122
+ volume (str):
123
+ Retrieve most actives by trading volume.
124
+ trades (str):
125
+ Retrieve most actives by number of trades.
126
+ """
127
+
128
+ VOLUME = "volume"
129
+ TRADES = "trades"
130
+
131
+
132
+ class MarketType(str, Enum):
133
+ """
134
+ Most actives possible filters.
135
+
136
+ Attributes:
137
+ stocks (str)
138
+ crypto (str)
139
+ """
140
+
141
+ STOCKS = "stocks"
142
+ CRYPTO = "crypto"
143
+
144
+
145
+ class NewsImageSize(str, Enum):
146
+ THUMB = "thumb"
147
+ SMALL = "small"
148
+ LARGE = "large"
149
+
150
+
151
+ class CorporateActionsType(str, Enum):
152
+ """
153
+ The type of corporate action.
154
+ ref. https://docs.alpaca.markets/reference/corporateactions-1
155
+
156
+ Attributes:
157
+ REVERSE_SPLIT (str): Reverse split
158
+ FORWARD_SPLIT (str): Forward split
159
+ UNIT_SPLIT (str): Unit split
160
+ CASH_DIVIDEND (str): Cash dividend
161
+ STOCK_DIVIDEND (str): Stock dividend
162
+ SPIN_OFF (str): Spin off
163
+ CASH_MERGER (str): Cash merger
164
+ STOCK_MERGER (str): Stock merger
165
+ STOCK_AND_CASH_MERGER (str): Stock and cash merger
166
+ REDEMPTION (str): Redemption
167
+ NAME_CHANGE (str): Name change
168
+ WORTHLESS_REMOVAL (str): Worthless removal
169
+ RIGHTS_DISTRIBUTION (str): Rights distribution
170
+ """
171
+
172
+ REVERSE_SPLIT = "reverse_split"
173
+ FORWARD_SPLIT = "forward_split"
174
+ UNIT_SPLIT = "unit_split"
175
+ CASH_DIVIDEND = "cash_dividend"
176
+ STOCK_DIVIDEND = "stock_dividend"
177
+ SPIN_OFF = "spin_off"
178
+ CASH_MERGER = "cash_merger"
179
+ STOCK_MERGER = "stock_merger"
180
+ STOCK_AND_CASH_MERGER = "stock_and_cash_merger"
181
+ REDEMPTION = "redemption"
182
+ NAME_CHANGE = "name_change"
183
+ WORTHLESS_REMOVAL = "worthless_removal"
184
+ RIGHTS_DISTRIBUTION = "rights_distribution"
@@ -0,0 +1,13 @@
1
+ from alpaca.data.historical.crypto import CryptoHistoricalDataClient
2
+ from alpaca.data.historical.news import NewsClient
3
+ from alpaca.data.historical.option import OptionHistoricalDataClient
4
+ from alpaca.data.historical.screener import ScreenerClient
5
+ from alpaca.data.historical.stock import StockHistoricalDataClient
6
+
7
+ __all__ = [
8
+ "CryptoHistoricalDataClient",
9
+ "StockHistoricalDataClient",
10
+ "NewsClient",
11
+ "OptionHistoricalDataClient",
12
+ "ScreenerClient",
13
+ ]
@@ -0,0 +1,76 @@
1
+ from typing import Optional, Union
2
+
3
+ from alpaca.common.enums import BaseURL
4
+ from alpaca.common.rest import RESTClient
5
+ from alpaca.common.types import RawData
6
+ from alpaca.data.models.corporate_actions import CorporateActionsSet
7
+ from alpaca.data.requests import CorporateActionsRequest
8
+
9
+
10
+ class CorporateActionsClient(RESTClient):
11
+ """
12
+ The REST client for interacting with Alpaca Corporate Actions API endpoints.
13
+ """
14
+
15
+ def __init__(
16
+ self,
17
+ api_key: Optional[str] = None,
18
+ secret_key: Optional[str] = None,
19
+ oauth_token: Optional[str] = None,
20
+ use_basic_auth: bool = False,
21
+ raw_data: bool = False,
22
+ url_override: Optional[str] = None,
23
+ ) -> None:
24
+ """
25
+ Instantiates a Corporate Actions Client.
26
+
27
+ Args:
28
+ api_key (Optional[str], optional): Alpaca API key. Defaults to None.
29
+ secret_key (Optional[str], optional): Alpaca API secret key. Defaults to None.
30
+ oauth_token (Optional[str]): The oauth token if authenticating via OAuth. Defaults to None.
31
+ use_basic_auth (bool, optional): If true, API requests will use basic authorization headers.
32
+ raw_data (bool, optional): If true, API responses will not be wrapped and raw responses will be returned from
33
+ methods. Defaults to False. This has not been implemented yet.
34
+ url_override (Optional[str], optional): If specified allows you to override the base url the client points
35
+ to for proxy/testing.
36
+ """
37
+ super().__init__(
38
+ api_key=api_key,
39
+ secret_key=secret_key,
40
+ oauth_token=oauth_token,
41
+ use_basic_auth=use_basic_auth,
42
+ api_version="v1",
43
+ base_url=url_override if url_override is not None else BaseURL.DATA,
44
+ sandbox=False,
45
+ raw_data=raw_data,
46
+ )
47
+
48
+ def get_corporate_actions(
49
+ self, request_params: CorporateActionsRequest
50
+ ) -> Union[RawData, CorporateActionsSet]:
51
+ """Returns corporate actions data
52
+
53
+ Args:
54
+ request_params (CorporateActionsRequest): The request params to filter the corporate actions data
55
+ """
56
+ params = request_params.to_request_fields()
57
+
58
+ if request_params.symbols:
59
+ params["symbols"] = ",".join(request_params.symbols)
60
+ if request_params.cusips:
61
+ params["cusips"] = ",".join(request_params.cusips)
62
+ if request_params.types:
63
+ params["types"] = ",".join(request_params.types)
64
+ if request_params.ids:
65
+ params["ids"] = ",".join(request_params.ids)
66
+
67
+ response = self._get_marketdata(
68
+ path="/corporate-actions",
69
+ params=params,
70
+ page_limit=1000,
71
+ page_size=1000,
72
+ )
73
+ if self._use_raw_data:
74
+ return response
75
+
76
+ return CorporateActionsSet(response)
@@ -0,0 +1,299 @@
1
+ from typing import Dict, Optional, Union
2
+
3
+ from alpaca.common.enums import BaseURL
4
+ from alpaca.common.rest import RESTClient
5
+ from alpaca.common.types import Credentials, RawData
6
+ from alpaca.data import Bar, Snapshot
7
+ from alpaca.data.enums import CryptoFeed
8
+ from alpaca.data.historical.utils import (
9
+ parse_obj_as_symbol_dict,
10
+ )
11
+ from alpaca.data.models import BarSet, Orderbook, Quote, QuoteSet, Trade, TradeSet
12
+ from alpaca.data.requests import (
13
+ CryptoBarsRequest,
14
+ CryptoLatestBarRequest,
15
+ CryptoLatestOrderbookRequest,
16
+ CryptoLatestQuoteRequest,
17
+ CryptoLatestTradeRequest,
18
+ CryptoQuoteRequest,
19
+ CryptoSnapshotRequest,
20
+ CryptoTradesRequest,
21
+ )
22
+
23
+
24
+ class CryptoHistoricalDataClient(RESTClient):
25
+ """
26
+ A REST client for retrieving crypto market data.
27
+
28
+ This client does not need any authentication to use.
29
+ You can instantiate it with or without API keys.
30
+
31
+ However, authenticating increases your data rate limit.
32
+
33
+ Learn more about crypto historical data here:
34
+ https://alpaca.markets/docs/api-references/market-data-api/crypto-pricing-data/historical/
35
+ """
36
+
37
+ def __init__(
38
+ self,
39
+ api_key: Optional[str] = None,
40
+ secret_key: Optional[str] = None,
41
+ oauth_token: Optional[str] = None,
42
+ raw_data: bool = False,
43
+ url_override: Optional[str] = None,
44
+ use_basic_auth: bool = False,
45
+ sandbox: bool = False,
46
+ ) -> None:
47
+ """
48
+ Instantiates a Historical Data Client for Crypto Data.
49
+
50
+ Args:
51
+ api_key (Optional[str], optional): Alpaca API key. Defaults to None.
52
+ secret_key (Optional[str], optional): Alpaca API secret key. Defaults to None.
53
+ oauth_token (Optional[str]): The oauth token if authenticating via OAuth. Defaults to None.
54
+ raw_data (bool, optional): If true, API responses will not be wrapped and raw responses will be returned from
55
+ methods. Defaults to False. This has not been implemented yet.
56
+ url_override (Optional[str], optional): If specified allows you to override the base url the client points
57
+ to for proxy/testing.
58
+ use_basic_auth (bool, optional): If true, API requests will use basic authorization headers. Set to true if using
59
+ broker api sandbox credentials
60
+ sandbox (bool): True if using sandbox mode. Defaults to False.
61
+ """
62
+
63
+ base_url = (
64
+ url_override
65
+ if url_override is not None
66
+ else BaseURL.DATA_SANDBOX if sandbox else BaseURL.DATA
67
+ )
68
+
69
+ super().__init__(
70
+ api_key=api_key,
71
+ secret_key=secret_key,
72
+ oauth_token=oauth_token,
73
+ api_version="v1beta3",
74
+ base_url=base_url,
75
+ sandbox=sandbox,
76
+ raw_data=raw_data,
77
+ use_basic_auth=use_basic_auth,
78
+ )
79
+
80
+ def get_crypto_bars(
81
+ self, request_params: CryptoBarsRequest, feed: CryptoFeed = CryptoFeed.US
82
+ ) -> Union[BarSet, RawData]:
83
+ """Gets bar/candle data for a cryptocurrency or list of cryptocurrencies.
84
+
85
+ Args:
86
+ request_params (CryptoBarsRequest): The parameters for the request.
87
+ feed (CryptoFeed): The data feed for crypto bars.
88
+
89
+ Returns:
90
+ Union[BarSet, RawData]: The crypto bar data either in raw or wrapped form
91
+ """
92
+
93
+ # paginated get request for crypto market data api
94
+ raw_bars = self._get_marketdata(
95
+ path=f"/crypto/{feed.value}/bars",
96
+ params=request_params.to_request_fields(),
97
+ page_size=10_000,
98
+ )
99
+
100
+ if self._use_raw_data:
101
+ return raw_bars
102
+
103
+ return BarSet(raw_bars)
104
+
105
+ def get_crypto_quotes(
106
+ self, request_params: CryptoQuoteRequest, feed: CryptoFeed = CryptoFeed.US
107
+ ) -> Union[QuoteSet, RawData]:
108
+ """Returns the quote data for a cryptocurrency or list of cryptocurrencies.
109
+
110
+ Args:
111
+ request_params (CryptoQuoteRequest): The parameters for the request.
112
+ feed (CryptoFeed): The data feed for crypto quotes.
113
+
114
+ Returns:
115
+ Union[QuoteSet, RawData]: The crypto quote data either in raw or wrapped form
116
+ """
117
+
118
+ # paginated get request for market data api
119
+ raw_quotes = self._get_marketdata(
120
+ path=f"/crypto/{feed.value}/quotes",
121
+ params=request_params.to_request_fields(),
122
+ page_size=10_000,
123
+ )
124
+
125
+ if self._use_raw_data:
126
+ return raw_quotes
127
+
128
+ return QuoteSet(raw_quotes)
129
+
130
+ def get_crypto_trades(
131
+ self, request_params: CryptoTradesRequest, feed: CryptoFeed = CryptoFeed.US
132
+ ) -> Union[TradeSet, RawData]:
133
+ """Returns the price and sales history over a given time period for a cryptocurrency
134
+ or list of cryptocurrencies.
135
+
136
+ Args:
137
+ request_params (CryptoTradesRequest): The parameters for the request.
138
+ feed (CryptoFeed): The data feed for crypto trades.
139
+
140
+ Returns:
141
+ Union[TradeSet, RawData]: The trade data either in raw or wrapped form
142
+ """
143
+
144
+ # paginated get request for market data api
145
+ raw_trades = self._get_marketdata(
146
+ path=f"/crypto/{feed.value}/trades",
147
+ params=request_params.to_request_fields(),
148
+ page_size=10_000,
149
+ )
150
+
151
+ if self._use_raw_data:
152
+ return raw_trades
153
+
154
+ return TradeSet(raw_trades)
155
+
156
+ def get_crypto_latest_trade(
157
+ self, request_params: CryptoLatestTradeRequest, feed: CryptoFeed = CryptoFeed.US
158
+ ) -> Union[Dict[str, Trade], RawData]:
159
+ """Returns the latest trade for a coin.
160
+
161
+ Args:
162
+ request_params (CryptoLatestTradeRequest): The parameters for the request.
163
+ feed (CryptoFeed): The data feed for the latest crypto trade.
164
+
165
+ Returns:
166
+ Union[Dict[str, Trade], RawData]: The latest trade in raw or wrapped format
167
+ """
168
+
169
+ raw_trades = self._get_marketdata(
170
+ path=f"/crypto/{feed.value}/latest/trades",
171
+ params=request_params.to_request_fields(),
172
+ )
173
+
174
+ if self._use_raw_data:
175
+ return raw_trades
176
+
177
+ return parse_obj_as_symbol_dict(Trade, raw_trades)
178
+
179
+ def get_crypto_latest_quote(
180
+ self, request_params: CryptoLatestQuoteRequest, feed: CryptoFeed = CryptoFeed.US
181
+ ) -> Union[Dict[str, Quote], RawData]:
182
+ """Returns the latest quote for a coin.
183
+
184
+ Args:
185
+ request_params (CryptoLatestQuoteRequest): The parameters for the request.
186
+ feed (CryptoFeed): The data feed for the latest crypto quote.
187
+
188
+ Returns:
189
+ Union[Dict[str, Quote], RawData]: The latest quote in raw or wrapped format
190
+ """
191
+
192
+ raw_quotes = self._get_marketdata(
193
+ path=f"/crypto/{feed.value}/latest/quotes",
194
+ params=request_params.to_request_fields(),
195
+ )
196
+
197
+ if self._use_raw_data:
198
+ return raw_quotes
199
+
200
+ return parse_obj_as_symbol_dict(Quote, raw_quotes)
201
+
202
+ def get_crypto_latest_bar(
203
+ self, request_params: CryptoLatestBarRequest, feed: CryptoFeed = CryptoFeed.US
204
+ ) -> Union[Dict[str, Bar], RawData]:
205
+ """Returns the latest minute bar for a coin.
206
+
207
+ Args:
208
+ request_params (CryptoLatestBarRequest): The parameters for the request.
209
+ feed (CryptoFeed): The data feed for the latest crypto bar.
210
+
211
+ Returns:
212
+ Union[Dict[str, Bar], RawData]: The latest bar in raw or wrapped format
213
+ """
214
+
215
+ raw_bars = self._get_marketdata(
216
+ path=f"/crypto/{feed.value}/latest/bars",
217
+ params=request_params.to_request_fields(),
218
+ )
219
+
220
+ if self._use_raw_data:
221
+ return raw_bars
222
+
223
+ return parse_obj_as_symbol_dict(Bar, raw_bars)
224
+
225
+ def get_crypto_latest_orderbook(
226
+ self,
227
+ request_params: CryptoLatestOrderbookRequest,
228
+ feed: CryptoFeed = CryptoFeed.US,
229
+ ) -> Union[Dict[str, Orderbook], RawData]:
230
+ """
231
+ Returns the latest orderbook state for the queried crypto symbols.
232
+
233
+ Args:
234
+ request_params (CryptoOrderbookRequest): The parameters for the orderbook request.
235
+ feed (CryptoFeed): The data feed for the latest crypto orderbook.
236
+
237
+ Returns:
238
+ Union[Dict[str, Orderbook], RawData]: The orderbook data either in raw or wrapped form.
239
+ """
240
+
241
+ raw_orderbooks = self._get_marketdata(
242
+ path=f"/crypto/{feed.value}/latest/orderbooks",
243
+ params=request_params.to_request_fields(),
244
+ )
245
+
246
+ if self._use_raw_data:
247
+ return raw_orderbooks
248
+
249
+ return parse_obj_as_symbol_dict(Orderbook, raw_orderbooks)
250
+
251
+ def get_crypto_snapshot(
252
+ self, request_params: CryptoSnapshotRequest, feed: CryptoFeed = CryptoFeed.US
253
+ ) -> Union[Snapshot, RawData]:
254
+ """Returns snapshots of queried crypto symbols. Snapshots contain latest trade, latest quote, latest minute bar,
255
+ latest daily bar and previous daily bar data for the queried symbols.
256
+
257
+ Args:
258
+ request_params (CryptoSnapshotRequest): The parameters for the snapshot request.
259
+ feed (CryptoFeed): The data feed for crypto snapshots.
260
+
261
+ Returns:
262
+ Union[SnapshotSet, RawData]: The snapshot data either in raw or wrapped form
263
+ """
264
+
265
+ raw_snapshots = self._get_marketdata(
266
+ path=f"/crypto/{feed.value}/snapshots",
267
+ params=request_params.to_request_fields(),
268
+ )
269
+
270
+ if self._use_raw_data:
271
+ return raw_snapshots
272
+
273
+ return parse_obj_as_symbol_dict(Snapshot, raw_snapshots)
274
+
275
+ # We override the _validate_credentials static method for crypto,
276
+ # because crypto does not actually require authentication.
277
+ @staticmethod
278
+ def _validate_credentials(
279
+ api_key: Optional[str] = None,
280
+ secret_key: Optional[str] = None,
281
+ oauth_token: Optional[str] = None,
282
+ ) -> Credentials:
283
+ """Gathers API credentials from parameters and environment variables, and validates them.
284
+ Args:
285
+ api_key (Optional[str]): The API key for authentication. Defaults to None.
286
+ secret_key (Optional[str]): The secret key for authentication. Defaults to None.
287
+ oauth_token (Optional[str]): The oauth token if authenticating via OAuth. Defaults to None.
288
+ Raises:
289
+ ValueError: If the combination of keys and tokens provided are not valid.
290
+ Returns:
291
+ Credentials: The set of validated authentication keys
292
+ """
293
+
294
+ if oauth_token and (api_key or secret_key):
295
+ raise ValueError(
296
+ "Either an oauth_token or an api_key may be supplied, but not both"
297
+ )
298
+
299
+ return api_key, secret_key, oauth_token