1+ from ..ticker import Ticker
2+ from ..const import _QUERY1_URL_
3+ from ..data import YfData
4+ from typing import Dict , List , Optional
5+
6+ import pandas as _pd
7+
8+ _QUERY_URL_ = f'{ _QUERY1_URL_ } /v1/finance'
9+
10+ class Domain :
11+ def __init__ (self , key : str , session = None , proxy = None ):
12+ self ._key : str = key
13+ self .proxy = proxy
14+ self .session = session
15+ self ._data : YfData = YfData (session = session )
16+
17+ self ._name : Optional [str ] = None
18+ self ._symbol : Optional [str ] = None
19+ self ._overview : Optional [Dict ] = None
20+ self ._top_companies : Optional [_pd .DataFrame ] = None
21+ self ._research_report : Optional [List [Dict [str , str ]]] = None
22+
23+ @property
24+ def key (self ) -> str :
25+ return self ._key
26+
27+ @property
28+ def name (self ) -> str :
29+ self ._ensure_fetched (self ._name )
30+ return self ._name
31+
32+ @property
33+ def symbol (self ) -> str :
34+ self ._ensure_fetched (self ._symbol )
35+ return self ._symbol
36+
37+ @property
38+ def ticker (self ) -> Ticker :
39+ self ._ensure_fetched (self ._symbol )
40+ return Ticker (self ._symbol )
41+
42+ @property
43+ def overview (self ) -> Dict :
44+ self ._ensure_fetched (self ._overview )
45+ return self ._overview
46+
47+ @property
48+ def top_companies (self ) -> Optional [_pd .DataFrame ]:
49+ self ._ensure_fetched (self ._top_companies )
50+ return self ._top_companies
51+
52+ @property
53+ def research_reports (self ) -> List [Dict [str , str ]]:
54+ self ._ensure_fetched (self ._research_reports )
55+ return self ._research_reports
56+
57+ def _fetch (self , query_url , proxy ) -> Dict :
58+ params_dict = {"formatted" : "true" , "withReturns" : "true" , "lang" : "en-US" , "region" : "US" }
59+ result = self ._data .get_raw_json (query_url , user_agent_headers = self ._data .user_agent_headers , params = params_dict , proxy = proxy )
60+ return result
61+
62+ def _parse_and_assign_common (self , data ) -> None :
63+ self ._name = data .get ('name' )
64+ self ._symbol = data .get ('symbol' )
65+ self ._overview = self ._parse_overview (data .get ('overview' , {}))
66+ self ._top_companies = self ._parse_top_companies (data .get ('topCompanies' , {}))
67+ self ._research_reports = data .get ('researchReports' )
68+
69+ def _parse_overview (self , overview ) -> Dict :
70+ return {
71+ "companies_count" : overview .get ('companiesCount' , None ),
72+ "market_cap" : overview .get ('marketCap' , {}).get ('raw' , None ),
73+ "message_board_id" : overview .get ('messageBoardId' , None ),
74+ "description" : overview .get ('description' , None ),
75+ "industries_count" : overview .get ('industriesCount' , None ),
76+ "market_weight" : overview .get ('marketWeight' , {}).get ('raw' , None ),
77+ "employee_count" : overview .get ('employeeCount' , {}).get ('raw' , None )
78+ }
79+
80+ def _parse_top_companies (self , top_companies ) -> Optional [_pd .DataFrame ]:
81+ top_companies_column = ['symbol' , 'name' , 'rating' , 'market weight' ]
82+ top_companies_values = [(c .get ('symbol' ),
83+ c .get ('name' ),
84+ c .get ('rating' ),
85+ c .get ('marketWeight' ,{}).get ('raw' ,None )) for c in top_companies ]
86+
87+ if not top_companies_values :
88+ return None
89+
90+ return _pd .DataFrame (top_companies_values , columns = top_companies_column ).set_index ('symbol' )
91+
92+ def _fetch_and_parse (self ) -> None :
93+ raise NotImplementedError ("_fetch_and_parse() needs to be implemented by children classes" )
94+
95+ def _ensure_fetched (self , attribute ) -> None :
96+ if attribute is None :
97+ self ._fetch_and_parse ()
98+
99+
100+ # map last updated as of 2024.09.18
101+ SECTOR_INDUSTY_MAPPING = {
102+ 'basic-materials' : {'specialty-chemicals' ,
103+ 'gold' ,
104+ 'building-materials' ,
105+ 'copper' ,
106+ 'steel' ,
107+ 'agricultural-inputs' ,
108+ 'chemicals' ,
109+ 'other-industrial-metals-mining' ,
110+ 'lumber-wood-production' ,
111+ 'aluminum' ,
112+ 'other-precious-metals-mining' ,
113+ 'coking-coal' ,
114+ 'paper-paper-products' ,
115+ 'silver' },
116+ 'communication-services' : {'internet-content-information' ,
117+ 'telecom-services' ,
118+ 'entertainment' ,
119+ 'electronic-gaming-multimedia' ,
120+ 'advertising-agencies' ,
121+ 'broadcasting' ,
122+ 'publishing' },
123+ 'consumer-cyclical' : {'internet-retail' ,
124+ 'auto-manufacturers' ,
125+ 'restaurants' ,
126+ 'home-improvement-retail' ,
127+ 'travel-services' ,
128+ 'specialty-retail' ,
129+ 'apparel-retail' ,
130+ 'residential-construction' ,
131+ 'footwear-accessories' ,
132+ 'packaging-containers' ,
133+ 'lodging' ,
134+ 'auto-parts' ,
135+ 'auto-truck-dealerships' ,
136+ 'gambling' ,
137+ 'resorts-casinos' ,
138+ 'leisure' ,
139+ 'apparel-manufacturing' ,
140+ 'personal-services' ,
141+ 'furnishings-fixtures-appliances' ,
142+ 'recreational-vehicles' ,
143+ 'luxury-goods' ,
144+ 'department-stores' ,
145+ 'textile-manufacturing' },
146+ 'consumer-defensive' : {'discount-stores' ,
147+ 'beverages-non-alcoholic' ,
148+ 'household-personal-products' ,
149+ 'packaged-foods' ,
150+ 'tobacco' ,
151+ 'confectioners' ,
152+ 'farm-products' ,
153+ 'food-distribution' ,
154+ 'grocery-stores' ,
155+ 'beverages-brewers' ,
156+ 'education-training-services' ,
157+ 'beverages-wineries-distilleries' },
158+ 'energy' : {'oil-gas-integrated' ,
159+ 'oil-gas-midstream' ,
160+ 'oil-gas-e-p' ,
161+ 'oil-gas-equipment-services' ,
162+ 'oil-gas-refining-marketing' ,
163+ 'uranium' ,
164+ 'oil-gas-drilling' ,
165+ 'thermal-coal' },
166+ 'financial-services' : {'banks-diversified' ,
167+ 'credit-services' ,
168+ 'asset-management' ,
169+ 'insurance-diversified' ,
170+ 'banks-regional' ,
171+ 'capital-markets' ,
172+ 'financial-data-stock-exchanges' ,
173+ 'insurance-property-casualty' ,
174+ 'insurance-brokers' ,
175+ 'insurance-life' ,
176+ 'insurance-specialty' ,
177+ 'mortgage-finance' ,
178+ 'insurance-reinsurance' ,
179+ 'shell-companies' ,
180+ 'financial-conglomerates' },
181+ 'healthcare' : {'drug-manufacturers-general' ,
182+ 'healthcare-plans' ,
183+ 'biotechnology' ,
184+ 'medical-devices' ,
185+ 'diagnostics-research' ,
186+ 'medical-instruments-supplies' ,
187+ 'medical-care-facilities' ,
188+ 'drug-manufacturers-specialty-generic' ,
189+ 'health-information-services' ,
190+ 'medical-distribution' ,
191+ 'pharmaceutical-retailers' },
192+ 'industrials' : {'aerospace-defense' ,
193+ 'specialty-industrial-machinery' ,
194+ 'railroads' ,
195+ 'building-products-equipment' ,
196+ 'farm-heavy-construction-machinery' ,
197+ 'specialty-business-services' ,
198+ 'integrated-freight-logistics' ,
199+ 'waste-management' ,
200+ 'conglomerates' ,
201+ 'industrial-distribution' ,
202+ 'engineering-construction' ,
203+ 'rental-leasing-services' ,
204+ 'consulting-services' ,
205+ 'trucking' ,
206+ 'electrical-equipment-parts' ,
207+ 'airlines' ,
208+ 'tools-accessories' ,
209+ 'pollution-treatment-controls' ,
210+ 'security-protection-services' ,
211+ 'marine-shipping' ,
212+ 'metal-fabrication' ,
213+ 'infrastructure-operations' ,
214+ 'staffing-employment-services' ,
215+ 'airports-air-services' ,
216+ 'business-equipment-supplies' },
217+ 'real-estate' : {'reit-specialty' ,
218+ 'reit-industrial' ,
219+ 'reit-retail' ,
220+ 'reit-residential' ,
221+ 'reit-healthcare-facilities' ,
222+ 'real-estate-services' ,
223+ 'reit-office' ,
224+ 'reit-diversified' ,
225+ 'reit-mortgage' ,
226+ 'reit-hotel-motel' ,
227+ 'real-estate-development' ,
228+ 'real-estate-diversified' },
229+ 'technology' : {'software-infrastructure' ,
230+ 'semiconductors' ,
231+ 'consumer-electronics' ,
232+ 'software-application' ,
233+ 'information-technology-services' ,
234+ 'semiconductor-equipment-materials' ,
235+ 'communication-equipment' ,
236+ 'computer-hardware' ,
237+ 'electronic-components' ,
238+ 'scientific-technical-instruments' ,
239+ 'solar' ,
240+ 'electronics-computer-distribution' },
241+ 'utilities' : {'utilities-regulated-electric' ,
242+ 'utilities-renewable' ,
243+ 'utilities-diversified' ,
244+ 'utilities-regulated-gas' ,
245+ 'utilities-independent-power-producers' ,
246+ 'utilities-regulated-water' }
247+ }
0 commit comments