Files
Buffteks-Website/venv/lib/python3.12/site-packages/yfinance/domain/domain.py
2025-05-08 21:10:14 -05:00

199 lines
6.7 KiB
Python

from abc import ABC, abstractmethod
from ..ticker import Ticker
from ..const import _QUERY1_URL_, _SENTINEL_
from ..data import YfData
from ..utils import print_once
from typing import Dict, List, Optional
import pandas as _pd
_QUERY_URL_ = f'{_QUERY1_URL_}/v1/finance'
class Domain(ABC):
"""
Abstract base class representing a domain entity in financial data, with key attributes
and methods for fetching and parsing data. Derived classes must implement the `_fetch_and_parse()` method.
"""
def __init__(self, key: str, session=None, proxy=_SENTINEL_):
"""
Initializes the Domain object with a key, session, and proxy.
Args:
key (str): Unique key identifying the domain entity.
session (Optional[requests.Session]): Session object for HTTP requests. Defaults to None.
"""
self._key: str = key
self.session = session
self._data: YfData = YfData(session=session)
if proxy is not _SENTINEL_:
print_once("YF deprecation warning: set proxy via new config function: yf.set_config(proxy=proxy)")
self._data._set_proxy(proxy)
self._name: Optional[str] = None
self._symbol: Optional[str] = None
self._overview: Optional[Dict] = None
self._top_companies: Optional[_pd.DataFrame] = None
self._research_reports: Optional[List[Dict[str, str]]] = None
@property
def key(self) -> str:
"""
Retrieves the key of the domain entity.
Returns:
str: The unique key of the domain entity.
"""
return self._key
@property
def name(self) -> str:
"""
Retrieves the name of the domain entity.
Returns:
str: The name of the domain entity.
"""
self._ensure_fetched(self._name)
return self._name
@property
def symbol(self) -> str:
"""
Retrieves the symbol of the domain entity.
Returns:
str: The symbol representing the domain entity.
"""
self._ensure_fetched(self._symbol)
return self._symbol
@property
def ticker(self) -> Ticker:
"""
Retrieves a Ticker object based on the domain entity's symbol.
Returns:
Ticker: A Ticker object associated with the domain entity.
"""
self._ensure_fetched(self._symbol)
return Ticker(self._symbol)
@property
def overview(self) -> Dict:
"""
Retrieves the overview information of the domain entity.
Returns:
Dict: A dictionary containing an overview of the domain entity.
"""
self._ensure_fetched(self._overview)
return self._overview
@property
def top_companies(self) -> Optional[_pd.DataFrame]:
"""
Retrieves the top companies within the domain entity.
Returns:
pandas.DataFrame: A DataFrame containing the top companies in the domain.
"""
self._ensure_fetched(self._top_companies)
return self._top_companies
@property
def research_reports(self) -> List[Dict[str, str]]:
"""
Retrieves research reports related to the domain entity.
Returns:
List[Dict[str, str]]: A list of research reports, where each report is a dictionary with metadata.
"""
self._ensure_fetched(self._research_reports)
return self._research_reports
def _fetch(self, query_url) -> Dict:
"""
Fetches data from the given query URL.
Args:
query_url (str): The URL used for the data query.
Returns:
Dict: The JSON response data from the request.
"""
params_dict = {"formatted": "true", "withReturns": "true", "lang": "en-US", "region": "US"}
result = self._data.get_raw_json(query_url, params=params_dict)
return result
def _parse_and_assign_common(self, data) -> None:
"""
Parses and assigns common data fields such as name, symbol, overview, and top companies.
Args:
data (Dict): The raw data received from the API.
"""
self._name = data.get('name')
self._symbol = data.get('symbol')
self._overview = self._parse_overview(data.get('overview', {}))
self._top_companies = self._parse_top_companies(data.get('topCompanies', {}))
self._research_reports = data.get('researchReports')
def _parse_overview(self, overview) -> Dict:
"""
Parses the overview data for the domain entity.
Args:
overview (Dict): The raw overview data.
Returns:
Dict: A dictionary containing parsed overview information.
"""
return {
"companies_count": overview.get('companiesCount', None),
"market_cap": overview.get('marketCap', {}).get('raw', None),
"message_board_id": overview.get('messageBoardId', None),
"description": overview.get('description', None),
"industries_count": overview.get('industriesCount', None),
"market_weight": overview.get('marketWeight', {}).get('raw', None),
"employee_count": overview.get('employeeCount', {}).get('raw', None)
}
def _parse_top_companies(self, top_companies) -> Optional[_pd.DataFrame]:
"""
Parses the top companies data and converts it into a pandas DataFrame.
Args:
top_companies (Dict): The raw top companies data.
Returns:
Optional[pandas.DataFrame]: A DataFrame containing top company data, or None if no data is available.
"""
top_companies_column = ['symbol', 'name', 'rating', 'market weight']
top_companies_values = [(c.get('symbol'),
c.get('name'),
c.get('rating'),
c.get('marketWeight',{}).get('raw',None)) for c in top_companies]
if not top_companies_values:
return None
return _pd.DataFrame(top_companies_values, columns=top_companies_column).set_index('symbol')
@abstractmethod
def _fetch_and_parse(self) -> None:
"""
Abstract method for fetching and parsing domain-specific data.
Must be implemented by derived classes.
"""
raise NotImplementedError("_fetch_and_parse() needs to be implemented by children classes")
def _ensure_fetched(self, attribute) -> None:
"""
Ensures that the given attribute is fetched by calling `_fetch_and_parse()` if the attribute is None.
Args:
attribute: The attribute to check and potentially fetch.
"""
if attribute is None:
self._fetch_and_parse()