112 lines
3.6 KiB
Python
112 lines
3.6 KiB
Python
import logging
|
|
from typing import Union
|
|
|
|
from aiohttp.client import ClientSession
|
|
from bs4 import BeautifulSoup
|
|
from bs4.element import ResultSet, Tag
|
|
|
|
from . import constants
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
# The resulting dictionary's keys correspond to the name of the item (row) in the financial statement,
|
|
# while its values will always be tuples with a length corresponding to the number of periods (columns)
|
|
# and elements being the actual numbers, with the exception of the first key-value-pair, which will represent
|
|
# the end dates of the reporting periods as strings (either years or quarters).
|
|
ResultDict = dict[str, Union[tuple[int], tuple[str]]]
|
|
|
|
|
|
async def soup_from_url(url: str, session: ClientSession = None) -> BeautifulSoup:
|
|
"""
|
|
Requests a web page and turns the response text into BeautifulSoup.
|
|
"""
|
|
async with session.get(url) as response:
|
|
html = await response.text()
|
|
return BeautifulSoup(html, constants.HTML_PARSER)
|
|
|
|
|
|
def extract_end_dates(soup: BeautifulSoup) -> tuple[str]:
|
|
"""
|
|
Finds and returns the end dates of the reporting periods as strings (either years or quarters) from the page of a
|
|
financial statement.
|
|
"""
|
|
ths = soup.find('div', attrs={'class': 'financials'}).thead.find_all('th')
|
|
return tuple(str(th.string).strip() for th in ths[1:-1])
|
|
|
|
|
|
def is_relevant_table_row(tr: Tag) -> bool:
|
|
"""
|
|
Returns True if the item in the table row is marked as relevant. Additionally warns when an item is unknown.
|
|
"""
|
|
if tr.name != 'tr':
|
|
return False
|
|
item_name = str(tr.td.div.string).strip()
|
|
try:
|
|
return constants.FINANCIAL_STATEMENT_ITEMS[item_name]
|
|
except KeyError:
|
|
log.warning(f"Unknown item name '{item_name}' found in financial statement.")
|
|
return False
|
|
|
|
|
|
def find_relevant_table_rows(soup: BeautifulSoup) -> ResultSet:
|
|
"""
|
|
Returns the table rows containing the data of interest.
|
|
"""
|
|
return soup.find('div', attrs={'class': 'financials'}).tbody.find_all(is_relevant_table_row)
|
|
|
|
|
|
def extract_row_data(tr: Tag) -> tuple[str, tuple[int]]:
|
|
"""
|
|
Returns the name of the item displayed in the table row (of a financial statement)
|
|
as well as a number for each reporting period.
|
|
"""
|
|
pass
|
|
|
|
|
|
def extract_all_data(soup: BeautifulSoup) -> ResultDict:
|
|
"""
|
|
Extracts financials from the page.
|
|
"""
|
|
pass
|
|
|
|
|
|
async def _get_financial_statement(statement: str, ticker_symbol: str, quarterly: bool = False,
|
|
session: ClientSession = None) -> ResultDict:
|
|
"""
|
|
Returns data from the specified financial statement of the specified company.
|
|
"""
|
|
pass
|
|
|
|
|
|
async def get_balance_sheet(ticker_symbol: str, quarterly: bool = False,
|
|
session: ClientSession = None) -> ResultDict:
|
|
"""
|
|
Returns data from the balance sheet of the specified company.
|
|
"""
|
|
pass
|
|
|
|
|
|
async def get_income_statement(ticker_symbol: str, quarterly: bool = False,
|
|
session: ClientSession = None) -> ResultDict:
|
|
"""
|
|
Returns data from the income statement of the specified company.
|
|
"""
|
|
pass
|
|
|
|
|
|
async def get_cash_flow_statement(ticker_symbol: str, quarterly: bool = False,
|
|
session: ClientSession = None) -> ResultDict:
|
|
"""
|
|
Returns data from the cash flow statement of the specified company.
|
|
"""
|
|
pass
|
|
|
|
|
|
async def get_company_financials(ticker_symbol: str, quarterly: bool = False,
|
|
session: ClientSession = None) -> ResultDict:
|
|
"""
|
|
Returns all fundamentals (balance sheet, income statement and cash flow statement) of the specified company.
|
|
"""
|
|
pass
|