Skip to content

Commit 56b4a04

Browse files
mcdayoubclickingbuttons
authored andcommitted
aggs endpoints (#128)
* aggs endpoints * aggs endpoints * aggs models optional * aggs models optional * fixed result_keys
1 parent 1770285 commit 56b4a04

File tree

5 files changed

+247
-14
lines changed

5 files changed

+247
-14
lines changed

polygon/rest/aggs.py

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
from email.headerregistry import Group
12
from .base import BaseClient
23
from typing import Optional, Any, Dict, List, Union
3-
from .models import Agg, Sort
4+
from .models import Agg, GroupedDailyAgg, DailyOpenCloseAgg, PreviousCloseAgg, Sort
45
from urllib3 import HTTPResponse
56
from datetime import datetime
67

@@ -22,7 +23,6 @@ def get_aggs(
2223
) -> Union[List[Agg], HTTPResponse]:
2324
"""
2425
Get aggregate bars for a ticker over a given date range in custom time window sizes.
25-
2626
:param ticker: The ticker symbol.
2727
:param multiplier: The size of the timespan multiplier.
2828
:param timespan: The size of the time window.
@@ -34,7 +34,6 @@ def get_aggs(
3434
:param params: Any additional query params
3535
:param raw: Return raw object instead of results object
3636
:return: List of aggregates
37-
:rtype: List[Agg]
3837
"""
3938
if isinstance(from_, datetime):
4039
from_ = int(from_.timestamp() * 1000)
@@ -50,3 +49,82 @@ def get_aggs(
5049
deserializer=Agg.from_dict,
5150
raw=raw,
5251
)
52+
53+
def get_grouped_daily_aggs(
54+
self,
55+
date: str,
56+
adjusted: Optional[bool] = None,
57+
params: Optional[Dict[str, Any]] = None,
58+
raw: bool = False,
59+
) -> Union[List[GroupedDailyAgg], HTTPResponse]:
60+
"""
61+
Get the daily open, high, low, and close (OHLC) for the entire market.
62+
63+
:param date: The beginning date for the aggregate window.
64+
:param adjusted: Whether or not the results are adjusted for splits. By default, results are adjusted. Set this to false to get results that are NOT adjusted for splits.
65+
:param params: Any additional query params
66+
:param raw: Return raw object instead of results object
67+
:return: List of grouped daily aggregates
68+
"""
69+
url = f"/v2/aggs/grouped/locale/us/market/stocks/{date}"
70+
71+
return self._get(
72+
path=url,
73+
params=self._get_params(self.get_grouped_daily_aggs, locals()),
74+
result_key="results",
75+
deserializer=GroupedDailyAgg.from_dict,
76+
raw=raw,
77+
)
78+
79+
def get_daily_open_close_agg(
80+
self,
81+
ticker: str,
82+
date: str,
83+
adjusted: Optional[bool] = None,
84+
params: Optional[Dict[str, Any]] = None,
85+
raw: bool = False,
86+
) -> Union[DailyOpenCloseAgg, HTTPResponse]:
87+
"""
88+
Get the open, close and afterhours prices of a stock symbol on a certain date.
89+
90+
:param ticker: The exchange symbol that this item is traded under.
91+
:param date: The beginning date for the aggregate window.
92+
:param adjusted: Whether or not the results are adjusted for splits. By default, results are adjusted. Set this to false to get results that are NOT adjusted for splits.
93+
:param params: Any additional query params
94+
:param raw: Return raw object instead of results object
95+
:return: Daily open close aggregate
96+
"""
97+
url = f"/v1/open-close/{ticker}/{date}"
98+
99+
return self._get(
100+
path=url,
101+
params=self._get_params(self.get_daily_open_close_agg, locals()),
102+
deserializer=DailyOpenCloseAgg.from_dict,
103+
raw=raw,
104+
)
105+
106+
def get_previous_close_agg(
107+
self,
108+
ticker: str,
109+
adjusted: Optional[bool] = None,
110+
params: Optional[Dict[str, Any]] = None,
111+
raw: bool = False,
112+
) -> Union[PreviousCloseAgg, HTTPResponse]:
113+
"""
114+
Get the previous day's open, high, low, and close (OHLC) for the specified stock ticker.
115+
116+
:param ticker: The ticker symbol of the stock/equity.
117+
:param adjusted: Whether or not the results are adjusted for splits. By default, results are adjusted. Set this to false to get results that are NOT adjusted for splits.
118+
:param params: Any additional query params
119+
:param raw: Return raw object instead of results object
120+
:return: Previous close aggregate
121+
"""
122+
url = f"/v2/aggs/ticker/{ticker}/prev"
123+
124+
return self._get(
125+
path=url,
126+
params=self._get_params(self.get_previous_close_agg, locals()),
127+
result_key="results",
128+
deserializer=PreviousCloseAgg.from_dict,
129+
raw=raw,
130+
)

polygon/rest/base.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ def _get(
6161

6262
if result_key:
6363
obj = obj[result_key]
64+
else:
65+
# If the result_key does not exist, still need to put the results in a list
66+
obj = [obj]
6467

6568
if deserializer:
6669
obj = [deserializer(o) for o in obj]

polygon/rest/models/aggs.py

Lines changed: 90 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,105 @@
44

55
@dataclass
66
class Agg:
7-
timestamp: int
87
open: float
98
high: float
109
low: float
1110
close: float
1211
volume: float
1312
vwap: Optional[float]
13+
timestamp: Optional[int]
1414
transactions: Optional[int]
1515

1616
@staticmethod
1717
def from_dict(d):
1818
return Agg(
19-
timestamp=d["t"],
20-
open=d["o"],
21-
high=d["h"],
22-
low=d["l"],
23-
close=d["c"],
24-
volume=d["v"],
25-
vwap=d.get("vw", None),
26-
transactions=d.get("n", None),
19+
d.get("o", None),
20+
d.get("h", None),
21+
d.get("l", None),
22+
d.get("c", None),
23+
d.get("v", None),
24+
d.get("vw", None),
25+
d.get("t", None),
26+
d.get("n", None),
27+
)
28+
29+
30+
@dataclass
31+
class GroupedDailyAgg:
32+
ticker: str
33+
open: float
34+
high: float
35+
low: float
36+
close: float
37+
volume: float
38+
vwap: Optional[float]
39+
timestamp: Optional[int]
40+
transactions: Optional[int]
41+
42+
@staticmethod
43+
def from_dict(d):
44+
return GroupedDailyAgg(
45+
d.get("T", None),
46+
d.get("o", None),
47+
d.get("h", None),
48+
d.get("l", None),
49+
d.get("c", None),
50+
d.get("v", None),
51+
d.get("vw", None),
52+
d.get("t", None),
53+
d.get("n", None),
54+
)
55+
56+
57+
@dataclass
58+
class DailyOpenCloseAgg:
59+
after_hours: Optional[float]
60+
close: float
61+
from_: str
62+
high: float
63+
low: float
64+
open: float
65+
pre_market: Optional[float]
66+
status: Optional[str]
67+
symbol: str
68+
volume: float
69+
70+
@staticmethod
71+
def from_dict(d):
72+
return DailyOpenCloseAgg(
73+
d.get("afterHours", None),
74+
d.get("close", None),
75+
d.get("from", None),
76+
d.get("high", None),
77+
d.get("low", None),
78+
d.get("open", None),
79+
d.get("preMarket", None),
80+
d.get("status", None),
81+
d.get("symbol", None),
82+
d.get("volume", None),
83+
)
84+
85+
86+
@dataclass
87+
class PreviousCloseAgg:
88+
ticker: str
89+
close: float
90+
high: float
91+
low: float
92+
open: float
93+
timestamp: Optional[float]
94+
volume: float
95+
vwap: Optional[float]
96+
97+
@staticmethod
98+
def from_dict(d):
99+
return PreviousCloseAgg(
100+
d.get("T", None),
101+
d.get("c", None),
102+
d.get("h", None),
103+
d.get("l", None),
104+
d.get("o", None),
105+
d.get("t", None),
106+
d.get("v", None),
107+
d.get("vw", None),
27108
)

tests/mocks.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,19 @@
66
(
77
"/v2/aggs/ticker/AAPL/range/1/day/2005-04-01/2005-04-04",
88
'{"ticker":"AAPL","queryCount":2,"resultsCount":2,"adjusted":true,"results":[{"v":6.42646396e+08,"vw":1.469,"o":1.5032,"c":1.4604,"h":1.5064,"l":1.4489,"t":1112331600000,"n":82132},{"v":5.78172308e+08,"vw":1.4589,"o":1.4639,"c":1.4675,"h":1.4754,"l":1.4343,"t":1112587200000,"n":65543}],"status":"OK","request_id":"12afda77aab3b1936c5fb6ef4241ae42","count":2}',
9-
)
9+
),
10+
(
11+
"/v2/aggs/grouped/locale/us/market/stocks/2005-04-04",
12+
'{"queryCount":1,"resultsCount":1,"adjusted": true,"results": [{"T":"GIK","v":895345,"vw":9.9979,"o":9.99,"c":10.02,"h":10.02,"l":9.9,"t":1602705600000,"n":96}],"status":"OK","request_id":"eae3ded2d6d43f978125b7a8a609fad9","count":1}',
13+
),
14+
(
15+
"/v1/open-close/AAPL/2005-04-01",
16+
'{"status": "OK","from": "2021-04-01","symbol": "AAPL","open": 123.66,"high": 124.18,"low": 122.49,"close": 123,"volume": 75089134,"afterHours": 123,"preMarket": 123.45}',
17+
),
18+
(
19+
"/v2/aggs/ticker/AAPL/prev",
20+
'{"ticker":"AAPL","queryCount":1,"resultsCount":1,"adjusted":true,"results":[{"T":"AAPL","v":9.5595226e+07,"vw":158.6074,"o":162.25,"c":156.8,"h":162.34,"l":156.72,"t":1651003200000,"n":899965}],"status":"OK","request_id":"5e5378d5ecaf3df794bb52e45d015d2e","count":1}',
21+
),
1022
]
1123

1224

tests/test_aggs.py

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
from polygon import RESTClient
2-
from polygon.rest.models import Agg
2+
from polygon.rest.models import (
3+
Agg,
4+
GroupedDailyAgg,
5+
DailyOpenCloseAgg,
6+
PreviousCloseAgg,
7+
)
38
from mocks import BaseTest
49

510

@@ -30,3 +35,57 @@ def test_get_aggs(self):
3035
),
3136
]
3237
self.assertEqual(aggs, expected)
38+
39+
def test_get_grouped_daily_aggs(self):
40+
c = RESTClient("")
41+
aggs = c.get_grouped_daily_aggs("2005-04-04", True)
42+
expected = [
43+
GroupedDailyAgg(
44+
ticker="GIK",
45+
open=9.99,
46+
high=10.02,
47+
low=9.9,
48+
close=10.02,
49+
volume=895345,
50+
vwap=9.9979,
51+
timestamp=1602705600000,
52+
transactions=96,
53+
)
54+
]
55+
self.assertEqual(aggs, expected)
56+
57+
def test_get_daily_open_close_agg(self):
58+
c = RESTClient("")
59+
aggs = c.get_daily_open_close_agg("AAPL", "2005-04-01", True)
60+
expected = [
61+
DailyOpenCloseAgg(
62+
after_hours=123,
63+
close=123,
64+
from_="2021-04-01",
65+
high=124.18,
66+
low=122.49,
67+
open=123.66,
68+
pre_market=123.45,
69+
status="OK",
70+
symbol="AAPL",
71+
volume=75089134,
72+
)
73+
]
74+
self.assertEqual(aggs, expected)
75+
76+
def test_get_previous_close_agg(self):
77+
c = RESTClient("")
78+
aggs = c.get_previous_close_agg("AAPL")
79+
expected = [
80+
PreviousCloseAgg(
81+
ticker="AAPL",
82+
close=156.8,
83+
high=162.34,
84+
low=156.72,
85+
open=162.25,
86+
timestamp=1651003200000,
87+
volume=95595226.0,
88+
vwap=158.6074,
89+
)
90+
]
91+
self.assertEqual(aggs, expected)

0 commit comments

Comments
 (0)