Source code for vistock.plotly.financials

"""
This module provides a function to plot financial data for a given stock symbol
using Plotly. The data includes Basic EPS, Operating Revenue, Trailing EPS,
and Forward EPS (if available), plotted on two subplots with customizable
styles via the `template` parameter.

The `plot` function generates:

1. Quarterly financial data.
2. Annual financial data, with markers for Trailing EPS and Forward EPS.

The plot is saved as an HTML file in the specified `out_dir`, with support
for interactive exploration.
"""
__software__ = "Financial Chart"
__version__ = "1.2"
__author__ = "York <york.jong@gmail.com>"
__date__ = "2024/09/07 (initial version) ~ 2024/09/07 (last revision)"

__all__ = ['plot']

import pandas as pd
import yfinance as yf
import plotly.graph_objs as go
from plotly.subplots import make_subplots

from .. import tw
from .. import file_utils
from ..yf_utils import fetch_financials


[docs] def plot(symbol, template='plotly', out_dir='out'): """Plots the financial data of a stock symbol using Plotly. The function fetches Basic EPS, Operating Revenue, Trailing EPS, and Forward EPS for the given stock symbol from Yahoo Finance, with data divided into quarterly and annual segments. The data is plotted using two subplots, one for each frequency. The primary y-axis displays Basic EPS, and the secondary y-axis displays Operating Revenue. The chart's layout is customizable through the `template` parameter. The function also saves the plot as a PNG file in the specified `out_dir` after generating the HTML plot using Plotly. Parameters ---------- symbol: str The stock symbol to analyze. template: str, optional: The Plotly template to use for styling the chart. Defaults to 'plotly'. Available templates include: - 'plotly': Default Plotly template with interactive plots. - 'plotly_white': Light theme with a white background. - 'plotly_dark': Dark theme for the chart background. - 'ggplot2': Style similar to ggplot2 from R. - 'seaborn': Style similar to Seaborn in Python. - 'simple_white': Minimal white style with no gridlines. - 'presentation': Designed for presentations with a clean look. - 'xgridoff': Plot with x-axis gridlines turned off. - 'ygridoff': Plot with y-axis gridlines turned off. For more details on templates, refer to Plotly's official documentation. out_dir: str, optional Directory to save the output HTML file. Default is 'out'. """ ticker = tw.as_yfinance(symbol) # Fetch trailing and forward EPS from yf.info info = yf.Ticker(ticker).info trailing_eps = info.get('trailingEps', '') forward_eps = info.get('forwardEps', '') fig = make_subplots( rows=2, cols=1, row_heights=[0.5, 0.5], specs=[[{"secondary_y": True}], [{"secondary_y": True}]], subplot_titles=("Quarterly", "Annual"), ) for freq, row in zip(['quarterly', 'annual'], [1, 2]): df = fetch_financials( ticker, fields=['Basic EPS', 'Operating Revenue', 'Total Revenue'], frequency=freq ) if df.empty: return # Add Basic EPS trace fig.add_trace( go.Scatter(x=df.index, y=df['Basic EPS'], name='Basic EPS'), row=row, col=1 ) # Add Trailing EPS and Forward EPS to the annual subplot if freq == 'quarterly': # Trailing EPS: last available date in the quarterly data last_date = df.index[-1] elif trailing_eps and forward_eps: # freq == 'annual' fig.add_trace( go.Scatter(x=[last_date], y=[trailing_eps], mode='markers', marker=dict(color='red', symbol='circle'), name='Trailing EPS'), row=row, col=1 ) # Forward EPS: one year after the last available date future_date = last_date + pd.DateOffset(years=1) fig.add_trace( go.Scatter(x=[future_date], y=[forward_eps], mode='markers', marker=dict(color='orange', symbol='x'), name='Forward EPS'), row=row, col=1 ) # Add Operating Revenue trace fig.add_trace( go.Scatter(x=df.index, y=df['Operating Revenue'], name='Operating Revenue', line=dict(dash='dot')), row=row, col=1, secondary_y=True ) fig.update_layout( title_text=f"{symbol} Financials", yaxis1=dict(title="Basic EPS"), yaxis2=dict(title="Operating Revenue"), yaxis3=dict(title="Basic EPS"), yaxis4=dict(title="Operating Revenue"), template=template, ) fig.show() # Save the figure out_dir = file_utils.make_dir(out_dir) fn = file_utils.gen_fn_info(symbol, '', df.index[-1], __file__) fig.write_html(f'{out_dir}/{fn}.html')
if __name__ == "__main__": plot('NVDA') plot('聯發科')