#!/usr/bin/env python3 from typing import Dict, List, Tuple import yfinance as yf import file_writer import renderer class stock_quote_renderer(renderer.debuggable_abstaining_renderer): """Render the stock prices page.""" def __init__( self, name_to_timeout_dict: Dict[str, int], symbols: List[str], display_subs: Dict[str, str] = None, ) -> None: super(stock_quote_renderer, self).__init__(name_to_timeout_dict, False) self.symbols = symbols self.display_subs = display_subs def debug_prefix(self) -> str: return "stock" @staticmethod def get_ticker_name(ticker: yf.ticker.Ticker) -> str: """Get friendly name of a ticker.""" info = ticker.get_info() return info["shortName"] @staticmethod def get_price(ticker: yf.ticker.Ticker) -> float: """Get most recent price of a ticker.""" keys = [ "bid", "ask", "regularMarketPrice", "lastMarket", "open", "previousClose", ] info = ticker.get_info() for key in keys: if key in info and info[key] is not None and info[key] != 0.0: print(f"Price: picked {key}, ${info[key]}.") return float(info[key]) return None @staticmethod def get_change_and_delta( ticker: yf.ticker.Ticker, price: float ) -> Tuple[float, float]: """Given the current price, look up opening price and compute delta.""" keys = [ "open", "previousClose", ] info = ticker.get_info() for key in keys: if key in info and info[key] is not None: print(f"Change: picked {key}, ${info[key]}.") old_price = float(info[key]) delta = price - old_price return (delta / old_price * 100.0, delta) return (0.0, 0.0) def periodic_render(self, key: str) -> bool: """Write an up-to-date stock page.""" with file_writer.file_writer("stock_3_86400.html") as f: f.write("

Stock Quotes


") f.write("") symbols_finished = 0 for symbol in self.symbols: ticker = yf.Ticker(symbol) print(type(ticker)) # print(ticker.get_info()) if ticker is None: self.debug_print(f"Unknown symbol {symbol} -- ignored.") continue name = stock_quote_renderer.get_ticker_name(ticker) price = stock_quote_renderer.get_price(ticker) if price is None: self.debug_print(f"No price information for {symbol} -- skipped.") continue (percent_change, delta) = stock_quote_renderer.get_change_and_delta( ticker, price ) # print(f"delta: {delta}, change: {percent_change}") cell_color = "#b00000" if percent_change < 0 else "#009000" if symbols_finished % 4 == 0: if symbols_finished > 0: f.write("") f.write("") symbols_finished += 1 if self.display_subs is not None and symbol in self.display_subs: symbol = self.display_subs[symbol] f.write( f""" """ ) f.write("
{symbol}
${price:.2f}
({percent_change:.1f}%)
${delta:.2f}
") return True # Test #x = stock_quote_renderer({}, ["MSFT", "GOOG", "BTC-USD", "OPTAX", "GC=F", "VNQ"], { "BTC-USD": "BTC", "GC=F": "GOLD" }) #x.periodic_render(None)