Skip to content

Commit 6cb7498

Browse files
authored
Stocks financials (#150)
1 parent bfeb736 commit 6cb7498

File tree

9 files changed

+998
-1
lines changed

9 files changed

+998
-1
lines changed

docs/source/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This documentation is for the Python client only. For details about the response
1313
Quotes
1414
Reference
1515
Trades
16+
vX
1617
Models
1718

1819

docs/source/vX.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.. _vX_header:
2+
3+
vX
4+
==========
5+
6+
======================
7+
List stock financials
8+
======================
9+
.. automethod:: polygon.rest.VXClient.list_stock_financials
10+

polygon/rest/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
ConditionsClient,
1111
ExchangesClient,
1212
)
13+
from .vx import VXClient
1314

1415

1516
class RESTClient(
@@ -24,4 +25,6 @@ class RESTClient(
2425
ConditionsClient,
2526
ExchangesClient,
2627
):
27-
pass
28+
def __init__(self, *args, **kwargs):
29+
super().__init__(*args, **kwargs)
30+
self.vx = VXClient(*args, **kwargs)

polygon/rest/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
from .conditions import *
1010
from .exchanges import *
1111
from .snapshot import *
12+
from .financials import *

polygon/rest/models/financials.py

Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
from typing import Optional, Dict
2+
from dataclasses import dataclass
3+
4+
5+
@dataclass
6+
class DataPoint:
7+
"An individual financial data point."
8+
formula: Optional[str] = None
9+
label: Optional[str] = None
10+
order: Optional[int] = None
11+
unit: Optional[str] = None
12+
value: Optional[int] = None
13+
xpath: Optional[str] = None
14+
15+
@staticmethod
16+
def from_dict(d):
17+
return DataPoint(**d)
18+
19+
20+
@dataclass
21+
class ExchangeGainsLosses:
22+
"Contains exchange gains losses data for a cash flow statement."
23+
formula: Optional[str] = None
24+
label: Optional[str] = None
25+
order: Optional[int] = None
26+
unit: Optional[str] = None
27+
value: Optional[int] = None
28+
xpath: Optional[str] = None
29+
30+
@staticmethod
31+
def from_dict(d):
32+
return ExchangeGainsLosses(**d)
33+
34+
35+
@dataclass
36+
class NetCashFlow:
37+
"Contains net cash flow data for a cash flow statement."
38+
formula: Optional[str] = None
39+
label: Optional[str] = None
40+
order: Optional[int] = None
41+
unit: Optional[str] = None
42+
value: Optional[int] = None
43+
xpath: Optional[str] = None
44+
45+
@staticmethod
46+
def from_dict(d):
47+
return NetCashFlow(**d)
48+
49+
50+
@dataclass
51+
class NetCashFlowFromFinancingActivities:
52+
"Contains net cash flow from financing activities data for a cash flow statement."
53+
formula: Optional[str] = None
54+
label: Optional[str] = None
55+
order: Optional[int] = None
56+
unit: Optional[str] = None
57+
value: Optional[int] = None
58+
xpath: Optional[str] = None
59+
60+
@staticmethod
61+
def from_dict(d):
62+
return NetCashFlowFromFinancingActivities(**d)
63+
64+
65+
@dataclass
66+
class CashFlowStatement:
67+
"Contains cash flow statement data."
68+
exchange_gains_losses: Optional[ExchangeGainsLosses] = None
69+
net_cash_flow: Optional[NetCashFlow] = None
70+
net_cash_flow_from_financing_activities: Optional[
71+
NetCashFlowFromFinancingActivities
72+
] = None
73+
74+
@staticmethod
75+
def from_dict(d):
76+
return CashFlowStatement(
77+
exchange_gains_losses=None
78+
if "exchange_gains_losses" not in d
79+
else [ExchangeGainsLosses.from_dict(d["exchange_gains_losses"])],
80+
net_cash_flow=None
81+
if "net_cash_flow" not in d
82+
else [NetCashFlow.from_dict(d["net_cash_flow"])],
83+
net_cash_flow_from_financing_activities=None
84+
if "net_cash_flow_from_financing_activities" not in d
85+
else [
86+
NetCashFlowFromFinancingActivities.from_dict(
87+
d["net_cash_flow_from_financing_activities"]
88+
)
89+
],
90+
)
91+
92+
93+
@dataclass
94+
class ComprehensiveIncomeLoss:
95+
"Contains comprehensive income loss data for comprehensive income."
96+
formula: Optional[str] = None
97+
label: Optional[str] = None
98+
order: Optional[int] = None
99+
unit: Optional[str] = None
100+
value: Optional[int] = None
101+
xpath: Optional[str] = None
102+
103+
@staticmethod
104+
def from_dict(d):
105+
return ComprehensiveIncomeLoss(**d)
106+
107+
108+
@dataclass
109+
class ComprehensiveIncomeLossAttributableToParent:
110+
"Contains comprehensive income loss attributable to parent data for comprehensive income."
111+
formula: Optional[str] = None
112+
label: Optional[str] = None
113+
order: Optional[int] = None
114+
unit: Optional[str] = None
115+
value: Optional[int] = None
116+
xpath: Optional[str] = None
117+
118+
@staticmethod
119+
def from_dict(d):
120+
return ComprehensiveIncomeLossAttributableToParent(**d)
121+
122+
123+
@dataclass
124+
class OtherComprehensiveIncomeLoss:
125+
"Contains other comprehensive income loss data for comprehensive income."
126+
formula: Optional[str] = None
127+
label: Optional[str] = None
128+
order: Optional[int] = None
129+
unit: Optional[str] = None
130+
value: Optional[int] = None
131+
xpath: Optional[str] = None
132+
133+
@staticmethod
134+
def from_dict(d):
135+
return OtherComprehensiveIncomeLoss(**d)
136+
137+
138+
@dataclass
139+
class ComprehensiveIncome:
140+
"Contains comprehensive income data."
141+
comprehensive_income_loss: Optional[ComprehensiveIncomeLoss] = None
142+
comprehensive_income_loss_attributable_to_parent: Optional[
143+
ComprehensiveIncomeLossAttributableToParent
144+
] = None
145+
other_comprehensive_income_loss: Optional[OtherComprehensiveIncomeLoss] = None
146+
147+
@staticmethod
148+
def from_dict(d):
149+
return ComprehensiveIncome(
150+
comprehensive_income_loss=None
151+
if "comprehensive_income_loss" not in d
152+
else [ComprehensiveIncomeLoss.from_dict(d["comprehensive_income_loss"])],
153+
comprehensive_income_loss_attributable_to_parent=None
154+
if "comprehensive_income_loss_attributable_to_parent" not in d
155+
else [
156+
ComprehensiveIncomeLossAttributableToParent.from_dict(
157+
d["comprehensive_income_loss_attributable_to_parent"]
158+
)
159+
],
160+
other_comprehensive_income_loss=None
161+
if "other_comprehensive_income_loss" not in d
162+
else [
163+
OtherComprehensiveIncomeLoss.from_dict(
164+
d["other_comprehensive_income_loss"]
165+
)
166+
],
167+
)
168+
169+
170+
@dataclass
171+
class BasicEarningsPerShare:
172+
"Contains basic earning per share data for an income statement."
173+
formula: Optional[str] = None
174+
label: Optional[str] = None
175+
order: Optional[int] = None
176+
unit: Optional[str] = None
177+
value: Optional[int] = None
178+
xpath: Optional[str] = None
179+
180+
@staticmethod
181+
def from_dict(d):
182+
return BasicEarningsPerShare(**d)
183+
184+
185+
@dataclass
186+
class CostOfRevenue:
187+
"Contains cost of revenue data for an income statement."
188+
formula: Optional[str] = None
189+
label: Optional[str] = None
190+
order: Optional[int] = None
191+
unit: Optional[str] = None
192+
value: Optional[int] = None
193+
xpath: Optional[str] = None
194+
195+
@staticmethod
196+
def from_dict(d):
197+
return CostOfRevenue(**d)
198+
199+
200+
@dataclass
201+
class GrossProfit:
202+
"Contains gross profit data for an income statement."
203+
formula: Optional[str] = None
204+
label: Optional[str] = None
205+
order: Optional[int] = None
206+
unit: Optional[str] = None
207+
value: Optional[int] = None
208+
xpath: Optional[str] = None
209+
210+
@staticmethod
211+
def from_dict(d):
212+
return GrossProfit(**d)
213+
214+
215+
@dataclass
216+
class OperatingExpenses:
217+
"Contains operating expenses data for an income statement."
218+
formula: Optional[str] = None
219+
label: Optional[str] = None
220+
order: Optional[int] = None
221+
unit: Optional[str] = None
222+
value: Optional[int] = None
223+
xpath: Optional[str] = None
224+
225+
@staticmethod
226+
def from_dict(d):
227+
return OperatingExpenses(**d)
228+
229+
230+
@dataclass
231+
class Revenues:
232+
"Contains revenues data for an income statement."
233+
formula: Optional[str] = None
234+
label: Optional[str] = None
235+
order: Optional[int] = None
236+
unit: Optional[str] = None
237+
value: Optional[int] = None
238+
xpath: Optional[str] = None
239+
240+
@staticmethod
241+
def from_dict(d):
242+
return Revenues(**d)
243+
244+
245+
@dataclass
246+
class IncomeStatement:
247+
"Contains income statement data."
248+
basic_earnings_per_share: Optional[BasicEarningsPerShare] = None
249+
cost_of_revenue: Optional[CostOfRevenue] = None
250+
gross_profit: Optional[GrossProfit] = None
251+
operating_expenses: Optional[OperatingExpenses] = None
252+
revenues: Optional[Revenues] = None
253+
254+
@staticmethod
255+
def from_dict(d):
256+
return IncomeStatement(
257+
basic_earnings_per_share=None
258+
if "basic_earnings_per_share" not in d
259+
else [BasicEarningsPerShare.from_dict(d["basic_earnings_per_share"])],
260+
cost_of_revenue=None
261+
if "cost_of_revenue" not in d
262+
else [CostOfRevenue.from_dict(d["cost_of_revenue"])],
263+
gross_profit=None
264+
if "gross_profit" not in d
265+
else [GrossProfit.from_dict(d["gross_profit"])],
266+
operating_expenses=None
267+
if "operating_expenses" not in d
268+
else [OperatingExpenses.from_dict(d["operating_expenses"])],
269+
revenues=None
270+
if "revenues" not in d
271+
else [Revenues.from_dict(d["revenues"])],
272+
)
273+
274+
275+
@dataclass
276+
class Financials:
277+
"Contains financial data."
278+
balance_sheet: Optional[Dict[str, DataPoint]] = None
279+
cash_flow_statement: Optional[CashFlowStatement] = None
280+
comprehensive_income: Optional[ComprehensiveIncome] = None
281+
income_statement: Optional[IncomeStatement] = None
282+
283+
@staticmethod
284+
def from_dict(d):
285+
return Financials(
286+
balance_sheet=None
287+
if "balance_sheet" not in d
288+
else {k: DataPoint.from_dict(v) for (k, v) in d["balance_sheet"].items()},
289+
cash_flow_statement=None
290+
if "cash_flow_statement" not in d
291+
else [CashFlowStatement.from_dict(d["cash_flow_statement"])],
292+
comprehensive_income=None
293+
if "comprehensive_income" not in d
294+
else [ComprehensiveIncome.from_dict(d["comprehensive_income"])],
295+
income_statement=None
296+
if "income_statement" not in d
297+
else [IncomeStatement.from_dict(d["income_statement"])],
298+
)
299+
300+
301+
@dataclass
302+
class StockFinancial:
303+
"StockFinancial contains historical financial data for a stock ticker."
304+
cik: Optional[str] = None
305+
company_name: Optional[str] = None
306+
end_date: Optional[str] = None
307+
filing_date: Optional[str] = None
308+
financials: Optional[Financials] = None
309+
fiscal_period: Optional[str] = None
310+
fiscal_year: Optional[str] = None
311+
source_filing_file_url: Optional[str] = None
312+
source_filing_url: Optional[str] = None
313+
start_date: Optional[str] = None
314+
315+
@staticmethod
316+
def from_dict(d):
317+
return StockFinancial(
318+
cik=d.get("cik", None),
319+
company_name=d.get("company_name", None),
320+
end_date=d.get("end_date", None),
321+
filing_date=d.get("filing_date", None),
322+
financials=None
323+
if "financials" not in d
324+
else [Financials.from_dict(d["financials"])],
325+
fiscal_period=d.get("fiscal_period", None),
326+
fiscal_year=d.get("fiscal_year", None),
327+
source_filing_file_url=d.get("source_filing_file_url", None),
328+
source_filing_url=d.get("source_filing_url", None),
329+
start_date=d.get("start_date", None),
330+
)

polygon/rest/models/shared.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,8 @@ class SnapshotMarketType(Enum):
7171
STOCKS = "stocks"
7272
FOREX = "forex"
7373
CRYPTO = "crypto"
74+
75+
76+
class Timeframe(Enum):
77+
ANNUAL = "annual"
78+
QUARTERLY = "quarterly"

0 commit comments

Comments
 (0)