Skip to content

Commit 81fc47e

Browse files
authored
Merge pull request #3 from Polygon-io/rest-mvp
Rest mvp
2 parents 844e440 + b213969 commit 81fc47e

17 files changed

+4212
-21
lines changed

.drone.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ steps:
1111
- name: test
1212
image: python:3.7.5-alpine
1313
commands:
14-
- echo "testing"
14+
- pip install -U tox
15+
- tox
1516

1617
trigger:
1718
branch:

.gitignore

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
env/
12+
build/
13+
develop-eggs/
14+
dist/
15+
downloads/
16+
eggs/
17+
.eggs/
18+
lib/
19+
lib64/
20+
parts/
21+
sdist/
22+
var/
23+
*.egg-info/
24+
.installed.cfg
25+
*.egg
26+
27+
# PyInstaller
28+
# Usually these files are written by a python script from a template
29+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
30+
*.manifest
31+
*.spec
32+
33+
# Installer logs
34+
pip-log.txt
35+
pip-delete-this-directory.txt
36+
37+
# Unit test / coverage reports
38+
htmlcov/
39+
.tox/
40+
.coverage
41+
.coverage.*
42+
.cache
43+
nosetests.xml
44+
coverage.xml
45+
*,cover
46+
.hypothesis/
47+
venv/
48+
.python-version
49+
50+
# Translations
51+
*.mo
52+
*.pot
53+
54+
# Django stuff:
55+
*.log
56+
57+
# Sphinx documentation
58+
docs/_build/
59+
60+
# PyBuilder
61+
target/
62+
63+
#Ipython Notebook
64+
.ipynb_checkpoints

LICENSE

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2018 The Python Packaging Authority
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
SOFTWARE.

README.md

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
[![Build Status](https://drone.polygon.io/api/badges/Polygon-io/polygon-client-python/status.svg)](https://drone.polygon.io/Polygon-io/polygon-client-python)
22

3-
# A Python client library for Polgyon's WebSocket and RESTful APIs
4-
5-
Currently this repo only supports the WebSocket API
3+
# A Python client library for Polygon's WebSocket and RESTful APIs
64

75
## Getting Started
86

97
For a basic product overview, check out our [setup and use documentation](https://polygon.io/sockets)
108

9+
### Install
10+
11+
`pip install polygon-api-client`
1112

12-
## Simple Demo
13+
## Simple WebSocket Demo
1314
```python
1415
import time
1516

1617

17-
from polygon_client import WebSocketClient, STOCKS_CLUSTER
18+
from polygon import WebSocketClient, STOCKS_CLUSTER
1819

1920

2021
def my_customer_process_message(message):
@@ -36,3 +37,27 @@ if __name__ == "__main__":
3637
main()
3738

3839
```
40+
41+
## Simple REST Demo
42+
```python
43+
from polygon import RESTClient
44+
45+
46+
def main():
47+
key = "your api key"
48+
client = RESTClient(key)
49+
50+
resp = client.stocks_equities_daily_open_close("AAPL", "2018-3-2")
51+
print(f"On: {resp.from_} Apple opened at {resp.open} and closed at {resp.close}")
52+
53+
54+
if __name__ == '__main__':
55+
main()
56+
```
57+
58+
59+
## Notes about the REST Client
60+
61+
We use swagger as our API spec and we used this swagger to generate most of the code that defines the REST client.
62+
We made this decision due to the size of our API, many endpoints and object definitions, and to accommodate future changes.
63+

polygon/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from .websocket import WebSocketClient, STOCKS_CLUSTER, FOREX_CLUSTER, CRYPTO_CLUSTER
2+
from .rest import RESTClient

polygon/rest/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .client import RESTClient

polygon/rest/client.py

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
from typing import Dict, Type
2+
3+
import requests
4+
5+
from polygon.rest import models
6+
from polygon.rest.models import unmarshal
7+
8+
9+
class RESTClient:
10+
""" This is a custom generated class """
11+
DEFAULT_HOST = "api.polygon.io"
12+
13+
def __init__(self, auth_key: str):
14+
self.auth_key = auth_key
15+
self.url = "https://" + self.DEFAULT_HOST
16+
17+
self._session = requests.Session()
18+
self._session.params["apiKey"] = self.auth_key
19+
20+
def _handle_response(self, response_type: str, endpoint: str, params: Dict[str, str]) -> Type[models.AnyDefinition]:
21+
resp: requests.Response = self._session.get(endpoint, params=params)
22+
if resp.status_code == 200:
23+
return unmarshal.unmarshal_json(response_type, resp.json())
24+
else:
25+
resp.raise_for_status()
26+
27+
def reference_tickers(self, **query_params) -> models.ReferenceTickersApiResponse:
28+
endpoint = f"{self.url}/v2/reference/tickers"
29+
return self._handle_response("ReferenceTickersApiResponse", endpoint, query_params)
30+
31+
def reference_ticker_types(self, **query_params) -> models.ReferenceTickerTypesApiResponse:
32+
endpoint = f"{self.url}/v2/reference/types"
33+
return self._handle_response("ReferenceTickerTypesApiResponse", endpoint, query_params)
34+
35+
def reference_ticker_details(self, symbol, **query_params) -> models.ReferenceTickerDetailsApiResponse:
36+
endpoint = f"{self.url}/v1/meta/symbols/{symbol}/company"
37+
return self._handle_response("ReferenceTickerDetailsApiResponse", endpoint, query_params)
38+
39+
def reference_ticker_news(self, symbol, **query_params) -> models.ReferenceTickerNewsApiResponse:
40+
endpoint = f"{self.url}/v1/meta/symbols/{symbol}/news"
41+
return self._handle_response("ReferenceTickerNewsApiResponse", endpoint, query_params)
42+
43+
def reference_markets(self, **query_params) -> models.ReferenceMarketsApiResponse:
44+
endpoint = f"{self.url}/v2/reference/markets"
45+
return self._handle_response("ReferenceMarketsApiResponse", endpoint, query_params)
46+
47+
def reference_locales(self, **query_params) -> models.ReferenceLocalesApiResponse:
48+
endpoint = f"{self.url}/v2/reference/locales"
49+
return self._handle_response("ReferenceLocalesApiResponse", endpoint, query_params)
50+
51+
def reference_stock_splits(self, symbol, **query_params) -> models.ReferenceStockSplitsApiResponse:
52+
endpoint = f"{self.url}/v2/reference/splits/{symbol}"
53+
return self._handle_response("ReferenceStockSplitsApiResponse", endpoint, query_params)
54+
55+
def reference_stock_dividends(self, symbol, **query_params) -> models.ReferenceStockDividendsApiResponse:
56+
endpoint = f"{self.url}/v2/reference/dividends/{symbol}"
57+
return self._handle_response("ReferenceStockDividendsApiResponse", endpoint, query_params)
58+
59+
def reference_stock_financials(self, symbol, **query_params) -> models.ReferenceStockFinancialsApiResponse:
60+
endpoint = f"{self.url}/v2/reference/financials/{symbol}"
61+
return self._handle_response("ReferenceStockFinancialsApiResponse", endpoint, query_params)
62+
63+
def reference_market_status(self, **query_params) -> models.ReferenceMarketStatusApiResponse:
64+
endpoint = f"{self.url}/v1/marketstatus/now"
65+
return self._handle_response("ReferenceMarketStatusApiResponse", endpoint, query_params)
66+
67+
def reference_market_holidays(self, **query_params) -> models.ReferenceMarketHolidaysApiResponse:
68+
endpoint = f"{self.url}/v1/marketstatus/upcoming"
69+
return self._handle_response("ReferenceMarketHolidaysApiResponse", endpoint, query_params)
70+
71+
def stocks_equities_exchanges(self, **query_params) -> models.StocksEquitiesExchangesApiResponse:
72+
endpoint = f"{self.url}/v1/meta/exchanges"
73+
return self._handle_response("StocksEquitiesExchangesApiResponse", endpoint, query_params)
74+
75+
def stocks_equities_historic_trades(self, symbol, date,
76+
**query_params) -> models.StocksEquitiesHistoricTradesApiResponse:
77+
endpoint = f"{self.url}/v1/historic/trades/{symbol}/{date}"
78+
return self._handle_response("StocksEquitiesHistoricTradesApiResponse", endpoint, query_params)
79+
80+
def historic_trades_v2(self, ticker, date, **query_params) -> models.HistoricTradesV2ApiResponse:
81+
endpoint = f"{self.url}/v2/ticks/stocks/trades/{ticker}/{date}"
82+
return self._handle_response("HistoricTradesV2ApiResponse", endpoint, query_params)
83+
84+
def stocks_equities_historic_quotes(self, symbol, date,
85+
**query_params) -> models.StocksEquitiesHistoricQuotesApiResponse:
86+
endpoint = f"{self.url}/v1/historic/quotes/{symbol}/{date}"
87+
return self._handle_response("StocksEquitiesHistoricQuotesApiResponse", endpoint, query_params)
88+
89+
def historic_n___bbo_quotes_v2(self, ticker, date, **query_params) -> models.HistoricNBboQuotesV2ApiResponse:
90+
endpoint = f"{self.url}/v2/ticks/stocks/nbbo/{ticker}/{date}"
91+
return self._handle_response("HistoricNBboQuotesV2ApiResponse", endpoint, query_params)
92+
93+
def stocks_equities_last_trade_for_a_symbol(self, symbol,
94+
**query_params) -> models.StocksEquitiesLastTradeForASymbolApiResponse:
95+
endpoint = f"{self.url}/v1/last/stocks/{symbol}"
96+
return self._handle_response("StocksEquitiesLastTradeForASymbolApiResponse", endpoint, query_params)
97+
98+
def stocks_equities_last_quote_for_a_symbol(self, symbol,
99+
**query_params) -> models.StocksEquitiesLastQuoteForASymbolApiResponse:
100+
endpoint = f"{self.url}/v1/last_quote/stocks/{symbol}"
101+
return self._handle_response("StocksEquitiesLastQuoteForASymbolApiResponse", endpoint, query_params)
102+
103+
def stocks_equities_daily_open_close(self, symbol, date,
104+
**query_params) -> models.StocksEquitiesDailyOpenCloseApiResponse:
105+
endpoint = f"{self.url}/v1/open-close/{symbol}/{date}"
106+
return self._handle_response("StocksEquitiesDailyOpenCloseApiResponse", endpoint, query_params)
107+
108+
def stocks_equities_condition_mappings(self, ticktype,
109+
**query_params) -> models.StocksEquitiesConditionMappingsApiResponse:
110+
endpoint = f"{self.url}/v1/meta/conditions/{ticktype}"
111+
return self._handle_response("StocksEquitiesConditionMappingsApiResponse", endpoint, query_params)
112+
113+
def stocks_equities_snapshot_all_tickers(self,
114+
**query_params) -> models.StocksEquitiesSnapshotAllTickersApiResponse:
115+
endpoint = f"{self.url}/v2/snapshot/locale/us/markets/stocks/tickers"
116+
return self._handle_response("StocksEquitiesSnapshotAllTickersApiResponse", endpoint, query_params)
117+
118+
def stocks_equities_snapshot_single_ticker(self, ticker,
119+
**query_params) -> models.StocksEquitiesSnapshotSingleTickerApiResponse:
120+
endpoint = f"{self.url}/v2/snapshot/locale/us/markets/stocks/tickers/{ticker}"
121+
return self._handle_response("StocksEquitiesSnapshotSingleTickerApiResponse", endpoint, query_params)
122+
123+
def stocks_equities_snapshot_gainers_losers(self, direction,
124+
**query_params) -> models.StocksEquitiesSnapshotGainersLosersApiResponse:
125+
endpoint = f"{self.url}/v2/snapshot/locale/us/markets/stocks/{direction}"
126+
return self._handle_response("StocksEquitiesSnapshotGainersLosersApiResponse", endpoint, query_params)
127+
128+
def stocks_equities_previous_close(self, ticker, **query_params) -> models.StocksEquitiesPreviousCloseApiResponse:
129+
endpoint = f"{self.url}/v2/aggs/ticker/{ticker}/prev"
130+
return self._handle_response("StocksEquitiesPreviousCloseApiResponse", endpoint, query_params)
131+
132+
def stocks_equities_aggregates(self, ticker, multiplier, timespan, from_, to,
133+
**query_params) -> models.StocksEquitiesAggregatesApiResponse:
134+
endpoint = f"{self.url}/v2/aggs/ticker/{ticker}/range/{multiplier}/{timespan}/{from_}/{to}"
135+
return self._handle_response("StocksEquitiesAggregatesApiResponse", endpoint, query_params)
136+
137+
def stocks_equities_grouped_daily(self, locale, market, date,
138+
**query_params) -> models.StocksEquitiesGroupedDailyApiResponse:
139+
endpoint = f"{self.url}/v2/aggs/grouped/locale/{locale}/market/{market}/{date}"
140+
return self._handle_response("StocksEquitiesGroupedDailyApiResponse", endpoint, query_params)
141+
142+
def forex_currencies_historic_forex_ticks(self, from_, to, date,
143+
**query_params) -> models.ForexCurrenciesHistoricForexTicksApiResponse:
144+
endpoint = f"{self.url}/v1/historic/forex/{from_}/{to}/{date}"
145+
return self._handle_response("ForexCurrenciesHistoricForexTicksApiResponse", endpoint, query_params)
146+
147+
def forex_currencies_real_time_currency_conversion(self, from_, to,
148+
**query_params) -> models.ForexCurrenciesRealTimeCurrencyConversionApiResponse:
149+
endpoint = f"{self.url}/v1/conversion/{from_}/{to}"
150+
return self._handle_response("ForexCurrenciesRealTimeCurrencyConversionApiResponse", endpoint, query_params)
151+
152+
def forex_currencies_last_quote_for_a_currency_pair(self, from_, to,
153+
**query_params) -> models.ForexCurrenciesLastQuoteForACurrencyPairApiResponse:
154+
endpoint = f"{self.url}/v1/last_quote/currencies/{from_}/{to}"
155+
return self._handle_response("ForexCurrenciesLastQuoteForACurrencyPairApiResponse", endpoint, query_params)
156+
157+
def forex_currencies_snapshot_all_tickers(self,
158+
**query_params) -> models.ForexCurrenciesSnapshotAllTickersApiResponse:
159+
endpoint = f"{self.url}/v2/snapshot/locale/global/markets/forex/tickers"
160+
return self._handle_response("ForexCurrenciesSnapshotAllTickersApiResponse", endpoint, query_params)
161+
162+
def forex_currencies_snapshot_gainers_losers(self, direction,
163+
**query_params) -> models.ForexCurrenciesSnapshotGainersLosersApiResponse:
164+
endpoint = f"{self.url}/v2/snapshot/locale/global/markets/forex/{direction}"
165+
return self._handle_response("ForexCurrenciesSnapshotGainersLosersApiResponse", endpoint, query_params)
166+
167+
def crypto_crypto_exchanges(self, **query_params) -> models.CryptoCryptoExchangesApiResponse:
168+
endpoint = f"{self.url}/v1/meta/crypto-exchanges"
169+
return self._handle_response("CryptoCryptoExchangesApiResponse", endpoint, query_params)
170+
171+
def crypto_last_trade_for_a_crypto_pair(self, from_, to,
172+
**query_params) -> models.CryptoLastTradeForACryptoPairApiResponse:
173+
endpoint = f"{self.url}/v1/last/crypto/{from_}/{to}"
174+
return self._handle_response("CryptoLastTradeForACryptoPairApiResponse", endpoint, query_params)
175+
176+
def crypto_daily_open_close(self, from_, to, date, **query_params) -> models.CryptoDailyOpenCloseApiResponse:
177+
endpoint = f"{self.url}/v1/open-close/crypto/{from_}/{to}/{date}"
178+
return self._handle_response("CryptoDailyOpenCloseApiResponse", endpoint, query_params)
179+
180+
def crypto_historic_crypto_trades(self, from_, to, date,
181+
**query_params) -> models.CryptoHistoricCryptoTradesApiResponse:
182+
endpoint = f"{self.url}/v1/historic/crypto/{from_}/{to}/{date}"
183+
return self._handle_response("CryptoHistoricCryptoTradesApiResponse", endpoint, query_params)
184+
185+
def crypto_snapshot_all_tickers(self, **query_params) -> models.CryptoSnapshotAllTickersApiResponse:
186+
endpoint = f"{self.url}/v2/snapshot/locale/global/markets/crypto/tickers"
187+
return self._handle_response("CryptoSnapshotAllTickersApiResponse", endpoint, query_params)
188+
189+
def crypto_snapshot_single_ticker(self, ticker, **query_params) -> models.CryptoSnapshotSingleTickerApiResponse:
190+
endpoint = f"{self.url}/v2/snapshot/locale/global/markets/crypto/tickers/{ticker}"
191+
return self._handle_response("CryptoSnapshotSingleTickerApiResponse", endpoint, query_params)
192+
193+
def crypto_snapshot_single_ticker_full_book(self, ticker,
194+
**query_params) -> models.CryptoSnapshotSingleTickerFullBookApiResponse:
195+
endpoint = f"{self.url}/v2/snapshot/locale/global/markets/crypto/tickers/{ticker}/book"
196+
return self._handle_response("CryptoSnapshotSingleTickerFullBookApiResponse", endpoint, query_params)
197+
198+
def crypto_snapshot_gainers_losers(self, direction,
199+
**query_params) -> models.CryptoSnapshotGainersLosersApiResponse:
200+
endpoint = f"{self.url}/v2/snapshot/locale/global/markets/crypto/{direction}"
201+
return self._handle_response("CryptoSnapshotGainersLosersApiResponse", endpoint, query_params)

0 commit comments

Comments
 (0)