Skip to content

Commit 8ba8274

Browse files
authored
Merge pull request #124 from alpacahq/feature/polygon-v2-upgrade
Add v2 trade and quote endpoints for Polygon API
2 parents 67c63e2 + 260c00f commit 8ba8274

File tree

3 files changed

+99
-11
lines changed

3 files changed

+99
-11
lines changed

alpaca_trade_api/polygon/entity.py

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ 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 [
151+
'sip_timestamp', 'participant_timestamp', 'trf_timestamp'
152+
]:
153+
return pd.Timestamp(val, tz=NY, unit='ns')
150154
return val
151155
return getattr(super(), key)
152156

@@ -156,14 +160,24 @@ class _TradesOrQuotes(object):
156160

157161
def __init__(self, raw):
158162
def rename_keys(tick, map):
163+
if type(map['t']) is dict:
164+
# Must be a v2 response
165+
return {
166+
map[k]['name']: v for k, v in tick.items()
167+
}
159168
return {
160169
map[k]: v for k, v in tick.items()
161170
}
162171

163172
unit_class = self.__class__._unit
173+
results = {}
174+
if 'ticks' in raw:
175+
results = raw['ticks']
176+
else:
177+
results = raw['results']
164178
super().__init__([
165-
unit_class(rename_keys(tick, raw['map']))
166-
for tick in raw['ticks']
179+
unit_class(rename_keys(result, raw['map']))
180+
for result in results
167181
])
168182
self._raw = raw
169183

@@ -172,16 +186,32 @@ def df(self):
172186
if not hasattr(self, '_df'):
173187
raw = self._raw
174188
columns = self.__class__._columns
189+
results = {}
190+
if 'ticks' in raw:
191+
results = raw['ticks']
192+
else:
193+
results = raw['results']
175194
df = pd.DataFrame(
176-
sorted(raw['ticks'], key=lambda d: d['t']),
195+
sorted(results, key=lambda d: d['t']),
177196
columns=columns,
178197
)
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)
198+
if type(raw['map']['t']) is dict:
199+
# Must be v2 response
200+
df.columns = [raw['map'][c]['name'] for c in df.columns]
201+
df.set_index('sip_timestamp', inplace=True)
202+
df.index = pd.to_datetime(
203+
df.index.astype('int64'),
204+
utc=True,
205+
unit='ns',
206+
).tz_convert(NY)
207+
else:
208+
df.columns = [raw['map'][c] for c in df.columns]
209+
df.set_index('timestamp', inplace=True)
210+
df.index = pd.to_datetime(
211+
df.index.astype('int64'),
212+
utc=True,
213+
unit='ms',
214+
).tz_convert(NY)
185215

186216
df.sort_index(inplace=True)
187217
self._df = df
@@ -198,6 +228,11 @@ class Trades(_TradesOrQuotes, list):
198228
_unit = Trade
199229

200230

231+
class TradesV2(_TradesOrQuotes, list):
232+
_columns = ('t', 'y', 'f', 'q', 'i', 'x', 's', 'c', 'p', 'z')
233+
_unit = Trade
234+
235+
201236
class Quote(_TradeOrQuote, Entity):
202237
pass
203238

@@ -207,6 +242,12 @@ class Quotes(_TradesOrQuotes, list):
207242
_unit = Quote
208243

209244

245+
class QuotesV2(_TradesOrQuotes, list):
246+
_columns = ('t', 'y', 'f', 'q', 'c', 'i', 'p', 'x', 's', 'P', 'X',
247+
'S', 'z')
248+
_unit = Quote
249+
250+
210251
class Exchange(Entity):
211252
pass
212253

alpaca_trade_api/polygon/rest.py

Lines changed: 47 additions & 2 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,
5-
Quote, Quotes,
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 = {}
@@ -52,6 +57,28 @@ def historic_trades(self, symbol, date, offset=None, limit=None):
5257

5358
return Trades(raw)
5459

60+
def historic_trades_v2(
61+
self, symbol, date, timestamp=None, timestamp_limit=None,
62+
reverse=None, limit=None
63+
):
64+
path = '/ticks/stocks/trades/{}/{}'.format(symbol, date)
65+
params = {}
66+
if timestamp is not None:
67+
params['timestamp'] = timestamp
68+
if timestamp_limit is not None:
69+
params['timestampLimit'] = timestamp_limit
70+
if reverse is not None:
71+
params['reverse'] = reverse
72+
if limit is not None:
73+
params['limit'] = limit
74+
raw = self.get(path, params, 'v2')
75+
76+
return TradesV2(raw)
77+
78+
@deprecated(
79+
'historic_quotes v1 is deprecated and will be removed from the ' +
80+
'Polygon API in the future. Please upgrade to historic_quotes_v2.'
81+
)
5582
def historic_quotes(self, symbol, date, offset=None, limit=None):
5683
path = '/historic/quotes/{}/{}'.format(symbol, date)
5784
params = {}
@@ -63,6 +90,24 @@ def historic_quotes(self, symbol, date, offset=None, limit=None):
6390

6491
return Quotes(raw)
6592

93+
def historic_quotes_v2(
94+
self, symbol, date, timestamp=None, timestamp_limit=None,
95+
reverse=None, limit=None
96+
):
97+
path = '/ticks/stocks/nbbo/{}/{}'.format(symbol, date)
98+
params = {}
99+
if timestamp is not None:
100+
params['timestamp'] = timestamp
101+
if timestamp_limit is not None:
102+
params['timestampLimit'] = timestamp_limit
103+
if reverse is not None:
104+
params['reverse'] = reverse
105+
if limit is not None:
106+
params['limit'] = limit
107+
raw = self.get(path, params, 'v2')
108+
109+
return QuotesV2(raw)
110+
66111
def historic_agg(self, size, symbol,
67112
_from=None, to=None, limit=None):
68113
path = '/historic/agg/{}/{}'.format(size, symbol)

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)