Skip to content

Commit 135685b

Browse files
committed
Begin upgrade to Polygon v2 endpoints
1 parent 9915dd0 commit 135685b

File tree

3 files changed

+59
-71
lines changed

3 files changed

+59
-71
lines changed

alpaca_trade_api/polygon/entity.py

Lines changed: 45 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ def __getattr__(self, key):
147147
val = self._raw[key]
148148
if key == 'timestamp':
149149
return pd.Timestamp(val, tz=NY, unit='ms')
150+
elif key in ['sip_timestamp', 'participant_timestamp', 'trf_timestamp']:
151+
return pd.Timestamp(val, tz=NY, unit='ns')
150152
return val
151153
return getattr(super(), key)
152154

@@ -156,14 +158,24 @@ class _TradesOrQuotes(object):
156158

157159
def __init__(self, raw):
158160
def rename_keys(tick, map):
161+
if type(map['t']) is dict:
162+
# Must be a v2 response
163+
return {
164+
map[k]['name']: v for k, v in tick.items()
165+
}
159166
return {
160167
map[k]: v for k, v in tick.items()
161168
}
162169

163170
unit_class = self.__class__._unit
171+
results = {}
172+
if 'ticks' in raw:
173+
results = raw['ticks']
174+
else:
175+
results = raw['results']
164176
super().__init__([
165-
unit_class(rename_keys(tick, raw['map']))
166-
for tick in raw['ticks']
177+
unit_class(rename_keys(result, raw['map']))
178+
for result in results
167179
])
168180
self._raw = raw
169181

@@ -172,16 +184,32 @@ def df(self):
172184
if not hasattr(self, '_df'):
173185
raw = self._raw
174186
columns = self.__class__._columns
187+
results = {}
188+
if 'ticks' in raw:
189+
results = raw['ticks']
190+
else:
191+
results = raw['results']
175192
df = pd.DataFrame(
176-
sorted(raw['ticks'], key=lambda d: d['t']),
193+
sorted(results, key=lambda d: d['t']),
177194
columns=columns,
178195
)
179-
df.columns = [raw['map'][c] for c in df.columns]
180-
df.set_index('timestamp', inplace=True)
181-
df.index = pd.to_datetime(
182-
df.index.astype('int64') * 1000000,
183-
utc=True,
184-
).tz_convert(NY)
196+
if type(raw['map']['t']) is dict:
197+
# Must be v2 response
198+
df.columns = [raw['map'][c]['name'] for c in df.columns]
199+
df.set_index('sip_timestamp', inplace=True)
200+
df.index = pd.to_datetime(
201+
df.index.astype('int64'),
202+
utc=True,
203+
unit='ns',
204+
).tz_convert(NY)
205+
else:
206+
df.columns = [raw['map'][c] for c in df.columns]
207+
df.set_index('timestamp', inplace=True)
208+
df.index = pd.to_datetime(
209+
df.index.astype('int64'),
210+
utc=True,
211+
unit='ms',
212+
).tz_convert(NY)
185213

186214
df.sort_index(inplace=True)
187215
self._df = df
@@ -198,6 +226,11 @@ class Trades(_TradesOrQuotes, list):
198226
_unit = Trade
199227

200228

229+
class TradesV2(_TradesOrQuotes, list):
230+
_columns = ('t', 'y', 'f', 'q', 'i', 'x', 's', 'c', 'p', 'z')
231+
_unit = Trade
232+
233+
201234
class Quote(_TradeOrQuote, Entity):
202235
pass
203236

@@ -207,66 +240,10 @@ class Quotes(_TradesOrQuotes, list):
207240
_unit = Quote
208241

209242

210-
class _TradeOrQuoteV2(object):
211-
def __init__(self, raw):
212-
self._raw = raw
213-
214-
def __getattr__(self, key):
215-
if key in self._raw:
216-
val = self._raw[key]
217-
if key in ['t', 'y', 'f']:
218-
return pd.Timestamp(val, tz=NY, unit='ns')
219-
return val
220-
return getattr(super(), key)
221-
222-
223-
class _TradesOrQuotesV2(object):
224-
def __init__(self, raw):
225-
unit_class = self.__class__._unit
226-
super().__init__([
227-
unit_class(result)
228-
for result in raw['results']
229-
])
230-
self._raw = raw
231-
232-
@property
233-
def df(self):
234-
if not hasattr(self, '_df'):
235-
raw = self._raw
236-
columns = self.__class__._columns
237-
df = pd.DataFrame(
238-
sorted(raw['results'], key=lambda d: d['t']),
239-
columns=columns,
240-
)
241-
df.set_index('t', inplace=True)
242-
df.index = pd.to_datetime(
243-
df.index.astype('int64') * 1000000,
244-
utc=True, unit='ns'
245-
).tz_convert(NY)
246-
247-
df.sort_index(inplace=True)
248-
self._df = df
249-
250-
return self._df
251-
252-
253-
class TradeV2(_TradeOrQuoteV2, Entity):
254-
pass
255-
256-
257-
class TradesV2(_TradesOrQuotesV2, list):
258-
_columns = ('T', 't', 'y', 'f', 'q', 'i', 'x', 's', 'c', 'p', 'z')
259-
_unit = TradeV2
260-
261-
262-
class QuoteV2(_TradeOrQuoteV2, Entity):
263-
pass
264-
265-
266-
class QuotesV2(_TradesOrQuotesV2, list):
267-
_columns = ('T', 't', 'y', 'f', 'q', 'c', 'i', 'p', 'x', 's', 'P', 'X',
243+
class QuotesV2(_TradesOrQuotes, list):
244+
_columns = ('t', 'y', 'f', 'q', 'c', 'i', 'p', 'x', 's', 'P', 'X',
268245
'S', 'z')
269-
_unit = QuoteV2
246+
_unit = Quote
270247

271248

272249
class Exchange(Entity):

alpaca_trade_api/polygon/rest.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import requests
22
from .entity import (
33
Aggs, Aggsv2, Aggsv2Set,
4-
Trade, Trades, TradeV2, TradesV2,
5-
Quote, Quotes, QuoteV2, QuotesV2,
4+
Trade, Trades, TradesV2,
5+
Quote, Quotes, QuotesV2,
66
Exchange, SymbolTypeMap, ConditionMap,
77
Company, Dividends, Splits, Earnings, Financials, NewsList, Ticker
88
)
99
from alpaca_trade_api.common import get_polygon_credentials
10+
from deprecated import deprecated
1011

1112

1213
def _is_list_like(o):
@@ -41,6 +42,10 @@ def symbol_type_map(self):
4142
path = '/meta/symbol-types'
4243
return SymbolTypeMap(self.get(path))
4344

45+
@deprecated(
46+
'historic_trades v1 is deprecated and will be removed from the ' +
47+
'Polygon API in the future. Please upgrade to historic_trades_v2.'
48+
)
4449
def historic_trades(self, symbol, date, offset=None, limit=None):
4550
path = '/historic/trades/{}/{}'.format(symbol, date)
4651
params = {}
@@ -69,6 +74,10 @@ def historic_trades_v2(self, symbol, date, timestamp=None,
6974

7075
return TradesV2(raw)
7176

77+
@deprecated(
78+
'historic_quotes v1 is deprecated and will be removed from the ' +
79+
'Polygon API in the future. Please upgrade to historic_quotes_v2.'
80+
)
7281
def historic_quotes(self, symbol, date, offset=None, limit=None):
7382
path = '/historic/quotes/{}/{}'.format(symbol, date)
7483
params = {}
@@ -95,7 +104,7 @@ def historic_quotes_v2(self, symbol, date, timestamp=None,
95104
params['limit'] = limit
96105
raw = self.get(path, params, 'v2')
97106

98-
return Trades(raw)
107+
return QuotesV2(raw)
99108

100109
def historic_agg(self, size, symbol,
101110
_from=None, to=None, limit=None):

setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
'urllib3<1.25',
3232
'websocket-client',
3333
'websockets>=8.0',
34+
'deprecated',
3435
],
3536
tests_require=[
3637
'pytest',
@@ -39,6 +40,7 @@
3940
'coverage>=4.4.1',
4041
'mock>=1.0.1',
4142
'flake8',
43+
'deprecated',
4244
],
4345
setup_requires=['pytest-runner', 'flake8'],
4446
)

0 commit comments

Comments
 (0)