Source code for vistock.mpl.ibd_rs_cmp

"""
ibd_rs_cmp - A module for plotting IBD Relative Strength (RS) comparisons of
multiple stocks using mplfinance.

This module provides functionality to plot the Relative Strength (RS) of
multiple stocks compared to a reference index (e.g., S&P 500 or Taiwan
Weighted Index) using mplfinance.  It fetches historical stock data from Yahoo
Finance, calculates RS values, and generates a multi-panel chart. The resulting
chart is saved as an image file.

Functions:
- plot: Generates a Relative Strength comparison plot for multiple stocks.

Usage:
To use this module, call the `plot` function with a list of stock symbols and
desired parameters.
"""
__software__ = "IBD RS Comparison chart"
__version__ = "2.5"
__author__ = "York <york.jong@gmail.com>"
__date__ = "2024/08/16 (initial version) ~ 2024/10/05 (last revision)"

__all__ = ['plot']

import pandas as pd
import yfinance as yf
import matplotlib.pyplot as plt
import mplfinance as mpf

from .. import tw
from .. import file_utils
from . import mpf_utils as mpfu
from ..ibd import relative_strength, relative_strength_3m
from .. import stock_indices as si


[docs] def plot(symbols, period='2y', interval='1d', ticker_ref=None, rs_window='12mo', legend_loc='best', style='checkers', color_cycle=plt.cm.Paired.colors, out_dir='out'): """ Plot the Relative Strength (RS) of multiple stocks compared to a reference index using mplfinance. This function generates a multi-panel chart that compares the RS values i of the specified stocks against a reference index (e.g., S&P 500 or Taiwan Weighted Index). The chart includes RS lines for each stock, and can be customized based on the selected period and interval. The resulting plot is saved as an image file in the specified output directory. Parameters ------------ symbols: list of str List of stock symbols to compare. Can include both US and Taiwan stocks. period: str, optional The period of historical data to fetch. Valid values are '6mo', '1y', '2y', '5y', '10y', 'ytd', 'max'. Default is '2y'. - mo -- monthes - y -- years - ytd -- year to date - max -- all data interval: str, optional The interval for data points. Valid values are '1d' for daily or '1wk' for weekly. Default is '1d'. ticker_ref: str, optional The ticker symbol of the reference index. If None, defaults to S&P 500 ('^GSPC') or Taiwan Weighted Index ('^TWII') if the first stock is a Taiwan stock. rs_window: str, optional Specify the time window ('3mo' or '12mo') for Relative Strength calculation. Default to '12mo'. legend_loc: str, optional the location of the legend (default is 'best'). Valid locations are - 'best' - 'upper right' - 'upper left' - 'lower left' - 'lower right' - 'right' - 'center left' - 'center right' - 'lower center' - 'upper center' - 'center' style: str, optional The chart style to use. Common styles include: - 'yahoo': Yahoo Finance style - 'charles': Charles style - 'tradingview': TradingView style - 'binance': Binance style - 'binancedark': Binance dark mode style - 'mike': Mike style (dark mode) - 'nightclouds': Dark mode with sleek appearance - 'checkers': Checkered style - 'ibd': Investor's Business Daily style - 'sas': SAS style - 'starsandstripes': Stars and Stripes style - 'kenan': Kenan style - 'blueskies': Blue Skies style - 'brasil': Brasil style Default is 'checkers'. color_cycle: list or None Specifies a list of colors to be used for cycling through plot lines. If None, the default matplotlib color cycle will be used. You can pass a list of colors to override the default color cycle. Each plot line will use the next color in the sequence. Default color sequence: - plt.cm.Paired.colors (20 colors, cooler and more muted) Other useful predefined color cycles: - plt.cm.tab20.colors (20 colors, brighter) - plt.cm.tab20b.colors (20 colors, darker) - plt.cm.Paired.colors (12 colors, alternating between deep and pastel colors; useful for categorical data) - plt.cm.Set3.colors (12 colors, pastel-like; good for categorical data) - plt.cm.Set1.colors (9 colors, bold and highly distinct; ideal for categorical data) out_dir: str, optional Directory to save the image file. Defaults to 'out'. Returns -------- None The function generates a plot and saves it as an image file. Example -------- >>> symbols = ['NVDA', 'MSFT', 'META', 'AAPL', 'TSM'] >>> plot(symbols) """ if not ticker_ref: ticker_ref = '^GSPC' # S&P 500 Index if tw.is_taiwan_stock(tw.as_yfinance(symbols[0])): ticker_ref = '^TWII' # Taiwan Weighted Index # Fetch data for stocks and index tickers = [tw.as_yfinance(s) for s in symbols] df = yf.download([ticker_ref]+tickers, period=period, interval=interval) df_price = df.xs('Close', level='Price', axis=1) # Select the appropriate relative strength function based on the rs_window rs_func = { '3mo': relative_strength_3m, '12mo': relative_strength, }[rs_window] # Set the figure fig = mpf.figure(style=style, figsize=(12, 6)) ax = fig.add_subplot() # Add first subplot if color_cycle: ax.set_prop_cycle(color=color_cycle) # Plot Relative Strength Lines for ticker, symbol in zip(tickers, symbols): rs = rs_func(df_price[ticker], df_price[ticker_ref], interval) ax.plot(rs.index, rs, label=f'{si.get_name(symbol)}') # Plot the Reference Line ax.plot(rs.index, [100]*len(df), label=f'{si.get_name(ticker_ref)}', color='gray', linestyle='--') # Set Y axis ax.set_ylabel('Relative Strength ' f'(Compared to {si.get_name(ticker_ref)})') ax.yaxis.set_label_position("right") ax.yaxis.tick_right() ax.tick_params(axis='y', labelright=True, labelleft=False) # Set location of legends ax.legend(loc=legend_loc) # Convert datetime index to string format suitable for display df.index = df.index.strftime('%Y-%m-%d') fig.suptitle(f"IBD Relative Strength Comparison - {interval} " f"({df.index[0]} to {df.index[-1]})" f"; RS: {rs_window}", y=0.93) # Show the figure mpf.show() # Save the figure out_dir = file_utils.make_dir(out_dir) fn = file_utils.gen_fn_info('stocks', interval, df.index[-1], __file__) fig.savefig(f'{out_dir}/{fn}.png', bbox_inches='tight')
#------------------------------------------------------------------------------ # Test #------------------------------------------------------------------------------ def main(): mpfu.use_mac_chinese_font() symbols = ['NVDA', 'MSFT', 'META', '^NDX', '^TWII'] #symbols = ['NVDA', 'MSFT', 'META', '^NDX'] #plot(symbols) #symbols = ['羅昇', '昆盈', '穎漢', '光聖', '所羅門'] plot(symbols, rs_window='3mo', interval='1d', period='1y') if __name__ == '__main__': main()