Python {Article133}

ようこそ「Python」へ...

稼げる仮想通貨を見つけるには〔5〕仮想通貨のデータをローソク足チャート(移動平均線, ボリューム付き)に表示する

ここでは8回に分けて稼げる仮想通貨を見つける方法について解説します。 第5回目では、米国のYahoo! Financeからダウンロードした仮想通貨のデータをグラフに表示する方法について解説します。 ここでは、PythonのライブラリMatplotlib, Mplfinance, Plotly Expressを使用してさまざまなグラフを作成します。

Matplolibでは、仮想通貨の価格とボリュームを「subplot()」メソッドで個別にグラフに表示します。 次に、図(Figure)に2個のサブプロット(Subplot)を作成して、2個のSubplotを重ねて表示するといった方法も解説します。 言葉で説明するとイメージがわかないと思いますので「図B」をクリックしてご覧ください。

Mplfinanceでは、仮想通貨の価格をローソク足チャートに表示します。 さらに、ローソク足チャートに複数の移動平均線を追加する方法も解説します。 また、ローソク足チャートとボリュームを同時に表示する方法についても説明します。 図の「C, D」をクリックしてご覧ください。

Plotly Expressでは、仮想通貨の価格とボリュームを同時にグラフに表示します。 Plotly Expressでは、マウスをグラフ上にホバリングすると「日付、価格」をポップアップさせて表示させることができます。 また、日付をスライドさせて拡大させることも可能です。 さらに、マウスをホバリングしたときに表示されるホバーテキストをカスタマイズする方法についても説明します。 図の「E, F, G, H」をクリックしてご覧ください。

一般に仮想通貨に投資するときは、次のようなメトリック(投資のパフォーマンスや効果を測定するための指標や数値)を使用して判断します。
  • 日次リターン (Daily Return)
    仮想通貨の投資において1日あたりの収益率を示します。
  • ログリターン (Log Return)
    仮想通貨の投資においての対数収益率を示します。
  • 累積ログリターン (Cumulative Log Return)
    仮想通貨の投資においての累積的な対数収益率を示します。
  • トレーディングボリューム (Trading Volume)
    仮想通貨の取引量を示します。
  • マーケットキャップ (Market Cap)
    仮想通貨の時価総額を示します。
  • 価格波動性 (Price Volatility)
    仮想通貨の価格の変動率を示します。
さらに、実際にトレードするときは、次のようなテクニカルインジケーターを複数組み合わせて売買のタイミングを判断します。
  • Simple Moving Average (SMA)
    SMAが上昇傾向であれば買い。
  • Exponential Moving Average (EMA)
    EMAが上昇傾向であれば買い。
  • Bollinger Bands (BB)
    Bollinger Bandsで帯域が狭まっている場合は価格変動が大きいと見られ、買い/売りタイミングに注意。
  • Relative Strength Index (RSI)
    RSIが70以上であれば売り、30以下であれば買い。
  • Stochastic Oscillator (STO)
    STOが80以上であれば売り、20以下であれば買い。
説明文の左側に図の画像が表示されていますが縮小されています。 画像を拡大するにはマウスを画像上に移動してクリックします。 画像が拡大表示されます。拡大された画像を閉じるには右上の[X]をクリックします。 画像の任意の場所をクリックして閉じることもできます。
click image to zoom!
図A Bitcoin(BTC-JPY)
click image to zoom!
図B Matplotlib
click image to zoom!
図C Mplfinance [1]
click image to zoom!
図D Mplfinance [2]
click image to zoom!
図E Plotly [1]
click image to zoom!
図F Plotly [2]
click image to zoom!
図G Plotly [3]
click image to zoom!
図H Plotly [4]

Yahoo! Financeからダウンロードした仮想通貨のデータをMatplotlib, Mplfinance, Plotly Expressでグラフに表示する

  1. まずは、Visual Studio Codeを起動してプログラムファイルを作成する

    Visual Studio Code (VS Code)を起動したら新規ファイル(*.py)を作成して行1-430をコピペします。 ここでは、Jupter NotebookのようにPythonのプログラムをセル単位で実行します。 VS Codeの場合は「#%%」から「#%%」の間がセルになります。 セルを選択したら[Ctrl + Enter」でセルのコードを実行します。 IPythonが起動されて「インタラクティブ」ウィンドウが表示されます。 「インタラクティブ」ウィンドウからはPythonのコードを入力して実行させることができます。 たとえば、「df.info()」を入力して[Shift + Enter」で実行します。

    * Article.py:
    # Daily return vs log returns article (Part5)
    # %%
    
    ### Import pandas and matplotlib libraries 
    import os
    import math
    import numpy as np
    
    import pandas as pd
    
    import matplotlib.pyplot as plt 
    from matplotlib.dates import MonthLocator, DateFormatter
    from matplotlib.dates import DayLocator, DateFormatter
    
    import mplfinance as mpf    # pip install --upgrade mplfinance
    
    from plotly.subplots import make_subplots
    import plotly.graph_objects as go
    
    import datetime as dt
    from datetime import timedelta
    from time import sleep
    import yfinance as yf           
    import warnings
    
    warnings.simplefilter('ignore')
    plt.style.use('fivethirtyeight')
    pd.set_option('display.max_rows', 10)
    
    
    # %%
    
    ######################################################################################################################################
    def load_data(symbol: str, start_date: dt.datetime , end_date: dt.datetime, period='1d', interval='1d', prepost=True) -> pd.DataFrame:
        # valid periods: 1d,5d,1mo,3mo,6mo,1y,2y,5y,10y,ytd,max
        # fetch data by interval (including intraday if period < 60 days)
        # valid intervals: 1m,2m,5m,15m,30m,60m,90m,1h,1d,5d,1wk,1mo,3mo    
        try:
            end_date = end_date + timedelta(days=1)
            start_date_str = dt.datetime.strftime(start_date, "%Y-%m-%d")
            end_date_str = dt.datetime.strftime(end_date, "%Y-%m-%d")
            print(f"Loading data for {symbol}: start_date={start_date_str}, end_date={end_date_str}, {period=}, {interval=}")
            
            df = yf.download(symbol, start=start_date_str, end=end_date_str, period=period, interval=interval, prepost=prepost)
            # Date     Open          High           Low         Close     Adj Close       Volume   Symbol : interval=1d,5d,1wk,1mo,3mo
            # Datetime Open          High           Low         Close     Adj Close       Volume   Symbol : interval=1m,2m,5m,15m,30m,60m,90m,1h
    
            # Add symbol
            df['symbol'] = symbol 
    
            # Reset index
            df.reset_index(inplace=True) 
    
            # Rename Date or Datetime column name to Time
            if interval in '1m,2m,5m,15m,30m,60m,90m,1h':
                df.rename(columns={'Datetime': 'Date'}, inplace=True)
            else: # interval=1d,5d,1wk,1mo,3mo
                df.rename(columns={'Date': 'Date'}, inplace=True)    
    
            # Convert column names to lower case    
            df.columns = df.columns.str.lower()
            return df
        except Exception as e:
            print(f"load_data({symbol}) exception error: {str(e)}")
            return pd.DataFrame()
    
    ############################################
    def get_data(csv_file: str) -> pd.DataFrame:
        print(f"Loading data: {csv_file} ")
        df = pd.read_csv(csv_file)       
        # date,open,high,low,close,adj close,volume,symbol
        df['date'] = pd.to_datetime(df['date'])   
        # df['date'] = pd.to_datetime(df['date'], utc=True)          
        df.set_index(['date'], inplace=True)
        return df   
    
    ##############################
    # Main
    ##############################
    pd.set_option('display.max_rows', 6)
    ### Load the crypto data from yahoo finance
    symbol = 'BTC-JPY'   # BTC-JPY, ETH-JPY, LTC-JPY, OP-USD, HEX-USD, TWT-US, MATIC-USD, DOGE-USD
    interval = '1d' # 1m,2m,5m,15m,30m,60m,90m,1h,1d,5d,1wk,1mo,3mo
    csv_file = f"data/csv/yahoo_crypto_20200101({symbol})_{interval}.csv"  # data/csv/yahoo_crypto_20200101(BTC-JPY)_1d.csv
    isFile = os.path.isfile(csv_file)
    if not isFile:    
        if interval in '1m,2m,5m,15m,30m,60m,90m,1h':
            end = dt.datetime.now()          
            start = end - timedelta(days=7)      
        else: # interval=1d,5d,1wk,1mo,3mo  
            start = dt.datetime(2020,1,1)   # 2014,1,1 or 2020,1,1 or 2023,1,1
            end = dt.datetime.now()         
        # load_data(symbol: str, start_date: dt.datetime , end_date: dt.datetime, period='1d', interval={'1m'|'1d'}, prepost=True) -> pd.DataFrame:
        df = load_data(symbol, start, end, period='1d', interval=interval)
        if not df.empty:    
            df.to_csv(csv_file, index=False)
    # end of if not isFile:
    
    isFile = os.path.isfile(csv_file)
    if isFile: 
        df = get_data(csv_file)
        df.dropna(inplace=True)
        if df.empty:
            print(f"Quit the program due to df is empty: {df.empty=}")
            quit()
    
    raw_df = df.copy()
    
    
    # %%
    
    df = raw_df.copy()
    
    ### Plot Line Chart : Close price
    
    fig = plt.figure(figsize=(12, 6))
    plt.plot(df['close'], label='close')
    plt.title(f'{symbol} Plot Line Chart: Close Price')
    plt.xlabel('Date')
    plt.ylabel('Price')
    plt.xticks(rotation=45)
    plt.legend(loc='best')
    plt.show()
    
    
    # %%
    
    df = raw_df.copy()
    
    ### Plot Bar Chart : Volume
    
    fig = plt.figure(figsize=(12, 6))
    plt.bar(df.index, df['volume'], label='volume')
    plt.title(f'{symbol} Plot Bar Chart: Volume')
    plt.xlabel('Date')
    plt.ylabel('Volume')
    plt.xticks(rotation=45)
    plt.legend(loc='best')
    plt.show()
    
    
    # %%
    
    df = raw_df.copy()
    
    ### Plot Close, Cumulative Log Return and Volume
    
    # fig, ax = plt.subplots(2, 1, figsize=(10, 8))
    # fig, ax1, ax2 = plt.subplots(2, 1, figsize=(10, 8))
    
    fig = plt.figure(figsize=(12, 6))
    ax1 = fig.add_subplot(2, 1, 1)  # Plot Close
    ax2 = fig.add_subplot(2, 1, 2)  # Plot Volume
    
    ax1.set_title(f'{symbol} Plot Close & Volume')
    
    # Plot close price : line chart
    ax1.plot(df['close'], label='close')
    ax1.tick_params(bottom=False, labelbottom=False)
    # ax1.tick_params(top=False,
    #                bottom=False,
    #                left=False,
    #                right=False,
    #                labelleft=True,
    #                labelbottom=True)
    ax1.set_ylabel('Close Price')
    ax1.legend(loc='best')
    
    # Plot volume : bar chart
    ax2.bar(df.index, df['volume'], label='volume')
    # ax2.set_title('Volume')
    ax2.set_xlabel('Date')
    ax2.set_ylabel('Volume')
    ax2.legend(loc='best')
    
    # plt.legend(loc='best')
    plt.xticks(rotation=45)
    plt.show()
    
    
    # %%
    
    df = raw_df.copy()
    
    # ### Plot line & volume using twinx()
    fig, ax1 = plt.subplots(figsize=(12, 6))
    ax2 = ax1.twinx()
    
    ax1.set_title(f'{symbol} Plot Close & Volume')
    ax1.plot(df['close'], label='close')
    ax1.set_ylabel('Close Price')
    ax1.tick_params(axis='y')
    
    ax2.bar(df.index, df['volume'], label='volume', alpha=0.3)
    ax2.set_ylabel('Volume')
    ax2.tick_params(axis='y')
    
    ax1.set_ylim(bottom=0)
    ax2.set_ylim(bottom=0)
    
    ax1.grid(True)
    ax2.grid(False)
    
    # Set the x-axis to display year/month format
    ax1.xaxis.set_major_locator(DayLocator(interval=120))
    # ax1.xaxis.set_major_locator(MonthLocator())
    ax1.xaxis.set_major_formatter(DateFormatter('%y/%m'))
    # ax1.xaxis.set_major_formatter(DateFormatter('%Y/%m'))
    ax1.set_xlabel('Date', fontsize=9)
    
    fig.autofmt_xdate(rotation=45)
    
    plt.show()
    
    
    # %%
    
    df = raw_df.copy()
    
    ### Plot Candlestick : mplfinance 
    
    df = df.tail(60)
    # mpf.plot(df)    # type='candle', type='line', type='renko', or type='pnf'
    mpf.plot(    
        df, 
        type='candle',
        datetime_format='%m/%d',
        style = 'binance', # yahoo, binance, mike   
        title=f'{symbol} Plot Candlestick (type=candle, style=mike)',
        figratio=(12,6)
        )
    
    # mpf.plot(df, type='line')
    # mpf.plot(df, type='renko')
    # mpf.plot(df, type='pnf')
    
    # figratio=(30,15),
    # title='Some stock price',
    # tight_layout=True,
    # style = 'yahoo',
    
    # mpf.available_styles()
    # ['binance',
    #  'blueskies',
    #  'brasil',
    #  'charles',
    #  'checkers',
    #  'classic',
    #  'default',
    #  'ibd',
    #  'kenan',
    #  'mike',
    #  'nightclouds',
    #  'sas',
    #  'starsandstripes',
    #  'yahoo']
    
    
    # %%
    
    df = raw_df.copy()
    
    ### Plot moving averages with the mav keyword
    df = df.tail(60)
    
    mpf.plot(
        df,
        type='ohlc',
        mav=4,
        datetime_format='%m/%d',
        style = 'yahoo',     
        title=f'{symbol} Add moveing average (type=ohlc, mav=4)',
        figratio=(12,6)
        )
    
    
    # %%
    
    df = raw_df.copy()
    
    ### Plot Candlestick with moveing average
    df = df.tail(60)
    
    mpf.plot(
        df,
        type='candle',
        mav=(3,6,9),
        datetime_format='%m/%d',
        style = 'yahoo',     
        title=f'{symbol} Add moveing average (type=candle, mav=(3,6,9))',
        figratio=(12,6)    
        )
    
    
    # %%
    
    df = raw_df.copy()
    
    ### Plot Candlestick with moveing average & volume (stype=yahoo)
    df = df.tail(60)
    mpf.plot(
        df,
        type='candle',
        mav=(3,6,9),
        volume=True,
        datetime_format='%m/%d',    
        style = 'yahoo',     
        title=f'{symbol} Add volume (type=candle, mav=(3,6,9), volume=True)',
        figratio=(12,6)
        )
    
    # figratio=(30,15),
    # title='Some stock price',
    # tight_layout=True,
    # style = 'yahoo',
    
    # %%
    
    df = raw_df.copy()
    
    ### Plot Candlestick with moveing average & volume (style=mike)
    df = df.tail(60)
    mpf.plot(
        df,
        type='candle',
        mav=(3,6,9),
        volume=True,
        datetime_format='%m/%d',    
        style='mike', # yahoo, binance, mike    
        title=f'{symbol} Add volume (type=candle, mav=(3,6,9), volume=True)',
        figratio=(12,6)
    )
    
    
    # %%
    
    df = raw_df.copy()
    
    # Load data
    df = df.reset_index()
    df = df.tail(150)
    df = df.sort_values('date')
    
    ### Candlestick with Rangeslider
    
    # Create subplots
    # fig = make_subplots(rows=2, cols=1)
    fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.02)
    
    # Plot candlestick chart
    fig.add_trace(go.Candlestick(x=df['date'],
                    open=df['open'], high=df['high'],
                    low=df['low'], close=df['close'],
                    increasing=dict(line=dict(color='green')),
                    decreasing=dict(line=dict(color='red')),
                    name='Candlestick'), row=1, col=1) 
    
    # Plot moving averages
    short_window = 20
    long_window = 50
    df['SMA_short'] = df['close'].rolling(short_window).mean()
    df['SMA_long'] = df['close'].rolling(long_window).mean()
    
    fig.add_trace(go.Scatter(x=df['date'], y=df['SMA_short'], name=f'SMA{short_window}'), row=1, col=1)
    fig.add_trace(go.Scatter(x=df['date'], y=df['SMA_long'], name=f'SMA{long_window}'), row=1, col=1)
    
    # Add volume bar chart
    fig.add_trace(go.Bar(x=df['date'], y=df['volume'], name='Volume'), row=2, col=1)
    
    # Format x-axis dates
    fig.update_xaxes(
        rangebreaks=[dict(bounds=['sat', 'mon'])],
        type='date',
        tickformat='%Y/%m'    
    )
    
    # Add chart title and axis labels                                  
    fig.update_layout(title=f'{symbol} Candlestick Chart with Moving Averages and Volume (With Rangeslider)',
                      xaxis_title='Date',
                      yaxis_title='Price')
    
    # Show plot
    fig.show()
    
    
    # %%
    
    ### Candlestick without Rangeslider
    
    # Create subplots
    # fig = make_subplots(rows=2, cols=1)
    fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.02)
    
    # Plot candlestick chart
    fig.add_trace(go.Candlestick(x=df['date'],
                    open=df['open'], high=df['high'],
                    low=df['low'], close=df['close'],
                    increasing=dict(line=dict(color='green')),
                    decreasing=dict(line=dict(color='red')),
                    name='Candlestick'), row=1, col=1) 
    
    # Plot moving averages
    short_window = 20
    long_window = 50
    df['SMA_short'] = df['close'].rolling(short_window).mean()
    df['SMA_long'] = df['close'].rolling(long_window).mean()
    
    fig.add_trace(go.Scatter(x=df['date'], y=df['SMA_short'], name=f'SMA{short_window}'), row=1, col=1)
    fig.add_trace(go.Scatter(x=df['date'], y=df['SMA_long'], name=f'SMA{long_window}'), row=1, col=1)
    
    # Add volume bar chart
    fig.add_trace(go.Bar(x=df['date'], y=df['volume'], name='Volume'), row=2, col=1)
    
    # Format x-axis dates
    fig.update_xaxes(
        rangebreaks=[dict(bounds=['sat', 'mon'])],
        type='date',
        tickformat='%Y/%m'
    )
    
    # Add chart title and axis labels                                  
    fig.update_layout(title=f'{symbol} Candlestick Chart with Moving Averages and Volume (Without Rangeslider)',
                      xaxis_rangeslider_visible=False,
                      # xaxis_title='Date',
                      yaxis_title='Price')
    
    # fig.update_layout(xaxis_rangeslider_visible=False)
    
    # Show plot
    fig.show()  
    click image to zoom!
    図1
    図1にはVS Codeの画面が表示されています。 次のステップでは「セル」を選択して「セル」単位でPythonのコードを実行します。
  2. Pythonのライブラリを取り込む

    VS Codeから行5-28のセルをクリックして[Ctrl + Enter]で実行します。 IPythonが起動して「インタラクティブ」ウィンドウに実行結果が表示されます。 ここでは、Python 3.10.9とIPython 8.9.0を使用しています。

    click image to zoom!
    図2
    図2ではPythonの各種ライブラリを取り込んでいます。 行26ではPythonの警告メッセージを抑止しています。 行27ではMatplotlibのデフォルトのスタイルを設定しています。 行28では、PandasのDataFrameを表示するときデータ件数を最大10件に制限しています。
  3. 米国のYahoo! Financeからビットコイン(BTC-JPY)のデータをダウンロードする

    行34-107のセルを選択したら[Ctrl + Enter]で実行します。 ここでは、米国のYahoo! Financeからビットコイン(BTC-JPY)のデータをダウンロードしてPandasのDataFrameに格納しています。 「2020/1/1~2023/2/22」の範囲を指定して日次(Daily)のデータをダウンロードしています。

    click image to zoom!
    図3
    図3では、DataFrameの構造とデータの内容を表示しています。 DataFrameは「date, open, high, lose, adj close, volume, symbol」のカラムから構成されています。 このDataFrameにはビットコイン(BTC-JPY)のデータが1148件格納されています。
  4. Matplotlibでビットコイン(BTC-JPY)の価格・ボリュームをグラフに表示する

    行112-123のセルを選択したら[Ctrl + Enter]で実行します。 ここではMatplotlibを使用してビットコインの「close: 終値」をグラフに表示しています。

    click image to zoom!
    図4-1
    図4-1には、ビットコイン(BTC-JPY)の終値(close)がグラフに表示されています。 ビットコインのシンボルが「BTC-JPY」なので、日本円換算の価格になります。 ここでは、Matplotlibに「xticks(rotation=45)」を追加して日付が45度斜めに表示されるようにしています。
    click image to zoom!
    図4-2
    図4-2には、ビットコインの取引高(ボリューム)がグラフに表示されています。 Matplotlibに「legend(loc='best')」を追加すると、凡例が最適な場所に表示されます。
    click image to zoom!
    図4-3
    図4-3には、ビットコインの終値と取引高が表示されています。 ここでは、上段のサブプロット(ax1)に「tick_params(bottom=False, labelbottom=False)」を追加して X軸の「日付、ラベル」が表示されないようにしています。
    click image to zoom!
    図4-4
    図4-4には、ビットコインの終値と取引高が重ね合わせた状態で表示されています。 下段のサブスロット(ax2)を上段のサブスロット(ax1)と重ねるには、 下段のサブスロット(ax2)を「ax2 = ax1.twinx()」で生成します。

    ここでは、X軸の「日付」の間隔、書式、フォントサイズを変更しています。 詳細は下のコードを参照してください。
    ### Plot line & volume using twinx()
    fig, ax1 = plt.subplots(figsize=(10, 8))
    ax2 = ax1.twinx()
    
    ax1.set_title(f'{symbol} Plot Close & Volume')
    ax1.plot(df['close'], label='close')
    ax1.set_ylabel('Close Price')
    ax1.tick_params(axis='y')
    
    ax2.bar(df.index, df['volume'], label='volume', alpha=0.3)
    ax2.set_ylabel('Volume')
    ax2.tick_params(axis='y')
    
    ax1.set_ylim(bottom=0)
    ax2.set_ylim(bottom=0)
    
    ax1.grid(True)
    ax2.grid(False)
    
    ax1.xaxis.set_major_locator(DayLocator(interval=120))
    ax1.xaxis.set_major_formatter(DateFormatter('%y/%m'))
    ax1.set_xlabel('Date', fontsize=9)
    
    fig.autofmt_xdate(rotation=45)
    
    plt.show()  
  5. Mplfinanceでビットコイン(BTC-JPY)の価格・ボリュームをグラフに表示する

    行218-231のセルを選択したら[Ctrl + Enter]で実行します。 ここでは、Mplfinanceを使用してビットコイン(BTC-JPY)のローソク足チャートをグラフに表示します。 ローソク足チャートを表示するには、Mplfinanceの「plot()」メソッに引数「type='candle'」を追加します。 ここでは、引数「datetime_format='%m/%d'」を追加して日付を「mm/dd」の形式で表示させています。

    click image to zoom!
    図5-1
    図5-1には、ビットコイン(BTC-JPY)のローソク足チャートがグラフに表示されています。 ローソク足チャートを表示するには、「plot()」メソッドの引数に「type='candle'」を追加します。 ここでは「style='yahoo'」を追加してYahooスタイルのグラフを表示しています。
    click image to zoom!
    図5-2
    図5-2では、Mplfinanceがサポートしているスタイルの一覧を表示しています。 スタイルの一覧は「available_styles()」メソッドで取得することができます。
    click image to zoom!
    図5-3
    図5-3では、「style='mike'」で表示しています。 この場合、背景色が黒になります。
    click image to zoom!
    図5-4
    図5-4では、「style='binance'」で表示しています。
    click image to zoom!
    図5-5
    図5-5では、「mav=4」を追加して「type='ohlc'」で表示しています。 「ohlc」は「open, high, low, close」の略称です。 ローソク足チャートと同じ情報になります。 「mav=」を追加すると移動平均線も表示されます。
    click image to zoom!
    図5-6
    図5-6では、「mav=3,6,9」を追加して「type='candle'」で表示しています。 この場合、ローソク足チャートに3本の移動平均線が表示されます。
    click image to zoom!
    図5-7
    図6-7では、「volume=True」を追加して取引高も同時に表示させています。
    click image to zoom!
    図5-8
    図5-8では、「style='mike'」にして背景色を黒にしています。 移動平均線を追加するときは、背景色を黒にすると見えやすくなります。
  6. Plotly Expressでビットコイン(BTC-JPY)の価格・ボリュームをグラフに表示する

    行348-383のセルを選択したら[Ctrl + Enter]で実行します。 ここでは、Plotly Expressを使用してビットコイン(BTC-JPY)のデータを表示しています。 Plotlyを使うと、グラフ上にマウスをホバリングさせて価格(open, close, low, high)をポップアップ表示させるといったことが可能になります。 さらに、日付をスライドさせて拡大表示させることも可能です。

    click image to zoom!
    図6-1
    図6-1には、ビットコイン(BTC-JPY)のローソク足と取引高がグラフに表示されています。 ここではマウスをホバリングさせて日付(Jan 20, 2023)と価格(open, close, low, high)をポップアップ表示させています。 日付を「2023/01/20」のようにカスタマイズする方法については図6-4で解説しています。
    click image to zoom!
    図6-2
    図6-2では日付のスライダーをドラッグしてローソク足チャートを拡大表示させています。 なお、スライダーはデフォルトの状態では有効になっています。
    click image to zoom!
    図6-3
    図6-3では、日付のスライダーを無効にしています。 スライダーを無効にするには「xaxis_rangeslider_visible=False」を追加します。 マウスをホバリングすると、日付と取引高がポップアップ表示されます。
    # Add chart title                                   
    fig.update_layout(
        title=f'{symbol} Candlestick Chart with Moving Averages and Volume (Without Rangeslider)',
        xaxis_rangeslider_visible=False,                  
        yaxis_title='Price')
    
    click image to zoom!
    図6-4
    図6-4ではホバーテキスト(hovertext)をカスタマイズしています。 ここでは日付を「Nov 9,2022」から「2022/11/9」のように表示されるようにしています。 ホバーテキストをカスタマイズするには、「add_trace()」メソッドの引数に「hoverinfo=」と「hovertext=」を追加します。 詳細は下のコードを参照してください。
    # Plot candlestick chart
    fig.add_trace(go.Candlestick(
        x=df['date'],
        open=df['open'], high=df['high'],
        low=df['low'], close=df['close'],
        increasing=dict(line=dict(color='green')),
        decreasing=dict(line=dict(color='red')),
        name='Candlestick', 
        hoverinfo='text',
        hovertext='<b>Date:</b> ' + df['date'].dt.strftime('%Y/%m/%d') + '<br>' +
                    '<b>Open:</b> ' + df['open'].astype(str) + '<br>' +
                    '<b>High:</b> ' + df['high'].astype(str) + '<br>' +
                    '<b>Low:</b> ' + df['low'].astype(str) + '<br>' +
                    '<b>Close:</b> ' + df['close'].astype(str)
        ),              
        row=1, col=1
    )