diff options
Diffstat (limited to 'src/teradata/stock.py')
| -rw-r--r-- | src/teradata/stock.py | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/teradata/stock.py b/src/teradata/stock.py new file mode 100644 index 0000000..58d34b4 --- /dev/null +++ b/src/teradata/stock.py @@ -0,0 +1,62 @@ +lazy from typing import Self + +from attrs import frozen +lazy import yfinance +lazy from pandas import DataFrame + +from .cache import persistent + + +@frozen +class Tickers: + prices: DataFrame + + @property + def normalized(self: Self) -> DataFrame: + """Indexed to 100 at t_0.""" + return (self.prices / self.prices.iloc[0]) * 100 + + @property + def cumulative_returns(self: Self) -> DataFrame: + """Percentage gain/loss since t_0.""" + return ((self.prices / self.prices.iloc[0]) - 1) * 100 + + +@frozen +class ValuationSnapshot: + ticker: str + ev_to_sales: float | None = None + revenue_growth_yoy: float | None = None + ev_to_fcf: float | None = None + trailing_pe: float | None = None + forward_pe: float | None = None + + +@persistent +def get_stock_data(tickers: list[str], start: str) -> DataFrame: + data = yfinance.download(tickers, start=start) + if data is None: + raise ValueError(f"Yahoo Finance data for {tickers} from {start} is None") + + return data + + +@persistent +def get_valuation_snapshot(ticker: str) -> ValuationSnapshot: + y_ticker = yfinance.Ticker(ticker) + + info = y_ticker.info + ev = info.get("enterpriseValue") + fcf = info.get("freeCashflow") + ev_fcf = (ev / fcf) if (ev and fcf and fcf > 0) else None + + return ValuationSnapshot( + ticker=ticker, + ev_to_sales=info.get("enterpriseToRevenue"), + revenue_growth_yoy=( + info.get("revenueGrowth", 0.0) * 100 + if info.get("revenueGrowth") is not None + else None + ), + ev_to_fcf=ev_fcf, + ) |
