Python {Article040}

ようこそ「Python」へ...

Python + Matplotlibで仮想通貨(暗号通貨)の1分, 1時間, 1日, 1週間の価格変動率(%)を棒グラフで表示するには

ここではPythonのMatplotlibを使用して仮想通貨(暗号通貨)の1分、1時間、1日、1週間の価格変動(%)を横棒グラフで表示する方法を解説します。 仮想通貨(暗号通貨)の価格はBinanceのAPIを使用して取得します。 ここで解説するプログラムを実行するにはBinanceにアカウントを開設してAPIキーを取得する必要があります。 まだ、アカウントを開設していない方は事前に開設してAPIキーを取得してください。

BinanceのAPIを使用して過去の価格情報を取得するには「get_historical_klines()」メソッドを使用します。 たとえば、Bitcoinの1分間の価格変動を調べるにはget_historical_klines()の引数に「'BTCUSDT', '1m', '2 min ago UTC'」 のようなパラメータを指定します。同様に1時間、1日、1週間の価格変動を比較するには、 「'BTCUSDT', '1h', '2 day ago UTC'」、「'BTCUSDT', '1d', '2 day ago UTC'」、「'BTCUSDT', '1w', '2 week ago UTC'」のようなパラメータを指定します。

ここではVisula Studio Code(VSC)の「Python Interactive window」 を使用してJupter Notebookのような環境で説明します。 VSCを通常の環境からインタラクティブな環境に切り換えるにはコードを記述するときコメント「# %%」を入力します。 詳しい、操作手順については「ここ」 を参照してください。 インタラクティブな環境では、Pythonの「print(), plt.show()」などを使う必要がないので掲載しているコードでは省略しています。 VSCで通常の環境で使用するときは、必要に応じて「print(), plt.show()」等を追加してください。

この記事では、Pandas、Matplotlibのライブラリを使用しますので 「記事(Article001) | 記事(Article002) | 記事(Article003) | 記事(Article004)」 を参照して事前にインストールしておいてください。 Pythonのコードを入力するときにMicrosoftのVisula Studio Codeを使用します。 まだ、インストールしていないときは「記事(Article001)」を参照してインストールしておいてください。

説明文の左側に図の画像が表示されていますが縮小されています。 画像を拡大するにはマウスを画像上に移動してクリックします。 画像が拡大表示されます。拡大された画像を閉じるには右上の[X]をクリックします。 画像の任意の場所をクリックして閉じることもできます。

click image to zoom!
Price Change %[1H]
click image to zoom!
Price Change %[1D]
click image to zoom!
Price Change %[1W]

仮想通貨(暗号通貨)の価格変動率(1秒/1時間/1日/1週間)を横棒グラフに表示する

  1. Binanceで取引している仮想通貨(暗号通貨)の全てのシンボルを取得する

    Visual Studio Code(VSC)を起動したら行1-34をコピペして実行します。 行2-13ではPythonのライブラリを取り込んでいます。 行14ではPythonの警告を抑止しています。 行17-18ではWindowsの環境変数に設定しているBinanceのAPI-KEYとSECRET-KEYを取得しています。 行19ではBinanceのAPIのクライアントのインスタントを生成しています。

    行23ではget_all_tickers()メソッドでBinanceで取引している全ての仮想通貨(暗号通貨)のシンボルと価格を取得しています。 行25-27では仮想通貨(暗号通貨)のシンボルと価格をPandasのDataFrameに取り込んでCSVファイルに保存しています。 行30-33では仮想通貨(暗号通貨)の価格が米ドル「USTD」のものだけを抽出してCSVファイルに保存しています。 行34ではCSVファイルからPandasのDataFrameに米ドル(USDT)の仮想通貨(暗号通貨)のシンボルを取り込んでいます。
    # Import the necessary libraries
    import os
    import datetime
    import pandas as pd
    import matplotlib.pyplot as plt
    import matplotlib.dates as mpl_dates
    import matplotlib.style as style
    import numpy as np
    import re
    from binance import Client  # pip install python-binance
    import warnings
    
    from pandas.core.base import DataError
    warnings.simplefilter('ignore')
    
    # Get Binance API-key / Secret Key
    api_key = os.environ.get('BINANCE_API_KEY')
    api_secret = os.environ.get('BINANCE_SECRET_KEY')
    client = Client(api_key, api_secret, tld='us')  # tld='us' , testnet=True
    
    # Get all symbol prices
    prices = client.get_all_tickers()
    
    # Save all tickers
    df = pd.DataFrame(prices)
    csv_file = 'data/csv/binance/tickers.csv'
    df.to_csv(csv_file, index=False)
    
    # Save only USDT currency
    filter_by = df['symbol'].str.endswith('USDT')
    dfx = df[filter_by]
    csv_file = 'data/csv/binance/tickers(USDT).csv'
    dfx.to_csv(csv_file, index=False)
    df = pd.read_csv(csv_file)
    click image to zoom!
    図1-1
    図1-1はVisual Studio Code(VSC)の画面です。 ここでは行21で取得した仮想通貨(暗号通貨)のシンボルと価格を表示しています。
    click image to zoom!
    図1-2
    図1-2はVSCの画面です。 ここでは行33で取り込んだPandasのDataFrameの内容を表示しています。
  2. BinanceからAPI経由で全ての仮想通貨(暗号通貨)の価格情報を取得する

    行1ではPandasのDataFrameから列「symbol」の値を取得して変数「symbols」に格納しています。 行3-13ではBinanceからAPI経由で仮想通貨(暗号通貨)の価格を取得しています。 この関数からはPandasのDataFrameが戻り値として返されます。 行25では1日「1d」の価格変動率のグラフを作成することを指定しています。 1分間のときは「1m」、1時間なら「1h」、1週間なら「1w」を設定します。

    行28-57では関数getminutedata()を呼び出してBinanceから仮想通貨(暗号通貨)の価格を取得しています。 行46-49では価格変動率を計算してDataFrameに格納しています。 行64-67ではDataFrameに仮想通貨(暗号通貨)の価格変動率を取り込んでいます。 行68-71では価格変動率が「プラス」か「マイナス」をチェックしています。 プラスのときは「True」を、マイナスのときは「False」を格納します。 行73では列「coin_name」にindexを設定しています。
    symbols = df['symbol'].values
    
    def getminutedata(symbol, interval, lookback):
        res = client.get_historical_klines(symbol, interval, lookback)
        frame = pd.DataFrame(res)
        if frame.shape[0] == 2:
            frame = frame.iloc[:,:6]
            frame.columns = ['Date','Open','High','Low','Close','Volume']
            frame = frame.set_index('Date')
            frame.index = pd.to_datetime(frame.index, unit='ms')        
            frame.index = frame.index + datetime.timedelta(hours=9)   
            frame = frame.astype(float)
        return frame
    
    coin_name_list = []      # BTC, ETH, LTC,...
    coin_currency_list = []  # USDT, USDT, USDT,...
    price_list = []
    percent_change_1m_list  = []
    percent_change_1h_list  = []
    percent_change_1d_list  = []
    percent_change_1w_list  = []
    
    #percent_timeframe = '1m' 
    #percent_timeframe = '1h'
    percent_timeframe = '1d'
    #percent_timeframe = '1w'
    
    for symbol in symbols:
        if percent_timeframe == '1m':
            df = getminutedata(symbol, '1m', '2 min ago UTC')     
        elif percent_timeframe == '1h':
            df = getminutedata(symbol, '1h', '2 hour ago UTC') 
        elif percent_timeframe == '1d':
            df = getminutedata(symbol, '1d', '2 day ago UTC') 
        else:
            df = getminutedata(symbol, '1w', '2 week ago UTC')         
    
        rows = df.shape[0]
        if rows == 2:
            # Reverse String replace() 
            symbol_coin = ''.join(symbol.rsplit('USDT', 1))
            #symbol_coin = re.sub(r'(.*)USDT', r'\1', symbol)
            symbol_currency = 'USDT' 
            coin_name = [symbol_coin] * rows
            coin_currency = [symbol_currency] * rows 
            df['pct_changed_1m'] = df['Close'].pct_change()    
            df['pct_changed_1h'] = df['Close'].pct_change() 
            df['pct_changed_1d'] = df['Close'].pct_change() 
            df['pct_changed_1w'] = df['Close'].pct_change() 
    
            coin_name_list.append(coin_name[1])
            coin_currency_list.append(coin_currency[1])
            price_list.append(df['Close'].values[1])
            percent_change_1m_list.append(df['pct_changed_1m'].values[1]) 
            percent_change_1h_list.append(df['pct_changed_1h'].values[1])
            percent_change_1d_list.append(df['pct_changed_1d'].values[1]) 
            percent_change_1w_list.append(df['pct_changed_1w'].values[1])        
      
    df = pd.DataFrame(columns=['coin_name', 'coin_currency', 'price', 
        'percent_change_1m','percent_change_1h','percent_change_1d', 'percent_change_1w'])
    df['coin_name'] = coin_name_list
    df['coin_currency'] = coin_currency_list
    df['price'] = price_list
    df['percent_change_1m'] = percent_change_1m_list
    df['percent_change_1h'] = percent_change_1h_list
    df['percent_change_1d'] = percent_change_1d_list
    df['percent_change_1w'] = percent_change_1w_list
    df['positive_percent_change_1m'] = df['percent_change_1m'] > 0
    df['positive_percent_change_1h'] = df['percent_change_1h'] > 0
    df['positive_percent_change_1d'] = df['percent_change_1d'] > 0
    df['positive_percent_change_1w'] = df['percent_change_1w'] > 0
    
    df = df.set_index('coin_name')
    click image to zoom!
    図2-1
    図2-1はVisual Studio Code(VSC)の画面です。 ここでは行1の変数「symbols」の内容を表示しています。
    click image to zoom!
    図2-2
    図2-2ではPandasのDataFrameの列名を表示しています。
    click image to zoom!
    図2-3
    図2-3ではPandasのDataFrameの内容を表示しています。
  3. 全ての仮想通貨(暗号通貨)の価格変動(%)を横棒グラフで表示する

    行6-17ではPandasのDataFrameに格納されている仮想通貨(暗号通貨)の価格変動率を横棒グラフで表示しています。 DataFrameのplot()メソッドの引数には「kind='barh'」を指定して横棒グラフを作成するように指示しています。 引数colorには列「positive_percent_change_1?」を指定して変動率がプラスのときは「緑」、 マイナスのときは「赤」の横棒グラフを作成するように指示しています。
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo' 
    plt.style.use('fivethirtyeight')        
    plt.figure(figsize=(10,12))  # 10, 12
    
    if percent_timeframe == '1m':
        df.sort_values('percent_change_1m', ascending=True, inplace=True)
        df['percent_change_1m'].plot(kind='barh', color=df.positive_percent_change_1m.map({True: 'g', False: 'r'})) 
    elif percent_timeframe == '1h':
        df.sort_values('percent_change_1h', ascending=True, inplace=True)    
        df['percent_change_1h'].plot(kind='barh', color=df.positive_percent_change_1h.map({True: 'g', False: 'r'})) 
    elif percent_timeframe == '1d':
        df.sort_values('percent_change_1d', ascending=True, inplace=True)    
        df['percent_change_1d'].plot(kind='barh', color=df.positive_percent_change_1d.map({True: 'g', False: 'r'})) 
    else:
        df.sort_values('percent_change_1w', ascending=True, inplace=True)    
        df['percent_change_1w'].plot(kind='barh', color=df.positive_percent_change_1w.map({True: 'g', False: 'r'})) 
     
    plt.legend()
    plt.grid(False)
    plt.ylabel('Crypto Symbols')
    plt.title(f'Binance Crypto Price Change\n(USDT)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    click image to zoom!
    図3-1
    図3-1はVisual Studio Code(VSC)の画面です。 ここには仮想通貨(暗号通貨)の価格変動率のグラフ(1/2)が表示されています。
    click image to zoom!
    図3-2
    図3-2はVisual Studio Code(VSC)の画面です。 ここには仮想通貨(暗号通貨)の価格変動率のグラフ(2/2)が表示されています。
    click image to zoom!
    図3-3
    図3-3は棒グラフをPNGファイルに保存した画面です。 緑が変動率がプラス、赤が変動率がマイナスの仮想通貨(暗号通貨)です。
  4. ここで解説したコードをまとめて掲載

    最後にここで解説したすべてのコードをまとめて掲載しましたので参考にしてください。
    
    # Import the necessary libraries
    import os
    import datetime
    import pandas as pd
    import matplotlib.pyplot as plt
    import matplotlib.dates as mpl_dates
    import matplotlib.style as style
    import numpy as np
    import re
    from binance import Client  # pip install python-binance
    import warnings
    
    from pandas.core.base import DataError
    warnings.simplefilter('ignore')
    
    # Get Binance API-key / Secret Key
    api_key = os.environ.get('BINANCE_API_KEY')
    api_secret = os.environ.get('BINANCE_SECRET_KEY')
    client = Client(api_key, api_secret, tld='us')  # tld='us' , testnet=True
    
    # Get all symbol prices
    prices = client.get_all_tickers()
    
    # Save all tickers
    df = pd.DataFrame(prices)
    csv_file = 'data/csv/binance/tickers.csv'
    df.to_csv(csv_file, index=False)
    
    # Save only USDT currency
    filter_by = df['symbol'].str.endswith('USDT')
    dfx = df[filter_by]
    csv_file = 'data/csv/binance/tickers(USDT).csv'
    dfx.to_csv(csv_file, index=False)
    df = pd.read_csv(csv_file)
    
    # %%
    
    symbols = df['symbol'].values
    #symbols = ['BTCUSDT','ETHUSDT','LTCUSDT']
    # symbols = ['BTCUSDT', 'ETHUSDT', 'XRPUSDT' *, 'BCHUSDT', 'LTCUSDT', 'BNBUSDT',
    #     'ADAUSDT', 'BATUSDT', 'ETCUSDT', 'XLMUSDT', 'ZRXUSDT', 'DOGEUSDT',
    #     'ATOMUSDT', 'NEOUSDT', 'VETUSDT', 'QTUMUSDT', 'ONTUSDT', 'KNCUSDT',
    #     'VTHOUSDT', 'COMPUSDT', 'HNTUSDT', 'MKRUSDT', 'ONEUSDT',
    #     'BANDUSDT', 'STORJUSDT', 'BUSDUSDT', 'UNIUSDT', 'SOLUSDT',
    #     'EGLDUSDT', 'PAXGUSDT', 'OXTUSDT', 'ZENUSDT', 'FILUSDT',
    #     'AAVEUSDT', 'SHIBUSDT', 'CRVUSDT', 'AXSUSDT' *] 
    
    def getminutedata(symbol, interval, lookback):
        res = client.get_historical_klines(symbol, interval, lookback)
        #res = client.get_historical_klines(symbol, interval, lookback + ' min ago UTC')
        frame = pd.DataFrame(res)
        if frame.shape[0] == 2:
            frame = frame.iloc[:,:6]
            frame.columns = ['Date','Open','High','Low','Close','Volume']
            frame = frame.set_index('Date')
            frame.index = pd.to_datetime(frame.index, unit='ms')        
            frame.index = frame.index + datetime.timedelta(hours=9)   
            frame = frame.astype(float)
        return frame
    
    coin_name_list = []      # BTC, ETH, LTC,...
    coin_currency_list = []  # USDT, USDT, USDT
    price_list = []
    percent_change_1m_list  = []
    percent_change_1h_list  = []
    percent_change_1d_list  = []
    percent_change_1w_list  = []
    
    #percent_timeframe = '1m' 
    #percent_timeframe = '1h'
    percent_timeframe = '1d'
    #percent_timeframe = '1w'
    
    for symbol in symbols:
        #symbol = 'BTCUSDT'
        #symbol = 'ETHUSDT'
        #symbol = 'LTCUSDT'
        if percent_timeframe == '1m':
            df = getminutedata(symbol, '1m', '2 min ago UTC')     
        elif percent_timeframe == '1h':
            df = getminutedata(symbol, '1h', '2 hour ago UTC') 
        elif percent_timeframe == '1d':
            df = getminutedata(symbol, '1d', '2 day ago UTC') 
        else:
            df = getminutedata(symbol, '1w', '2 week ago UTC')         
    
        #df = getminutedata('BTCUSDT', '1m', '1 day ago UTC')
        #df = getminutedata('BTCUSDT', '1d', '8 day ago UTC')
        #df = getminutedata('BTCUSDT', '1d', '30 day ago UTC')
        #df = getminutedata('BTCUSDT', '1d', '100 day ago UTC')
        # # m -> minutes; h -> hours; d -> days; w -> weeks; M -> months
        # # 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M
    
        rows = df.shape[0]
        if rows == 2:
            # Reverse String replace() : USDxUSD => USDx
            symbol_coin = ''.join(symbol.rsplit('USDT', 1))
            #symbol_coin = re.sub(r'(.*)USDT', r'\1', symbol)
            #symbol_coin = symbol.replace('USDT', '')   # BUG BUG BUG
            symbol_currency = 'USDT' 
            coin_name = [symbol_coin] * rows
            coin_currency = [symbol_currency] * rows 
            df['pct_changed_1m'] = df['Close'].pct_change()    
            df['pct_changed_1h'] = df['Close'].pct_change()
            df['pct_changed_1d'] = df['Close'].pct_change()
            df['pct_changed_1w'] = df['Close'].pct_change()
    
            coin_name_list.append(coin_name[1])
            coin_currency_list.append(coin_currency[1])
            price_list.append(df['Close'].values[1])
            percent_change_1m_list.append(df['pct_changed_1m'].values[1]) 
            percent_change_1h_list.append(df['pct_changed_1h'].values[1])
            percent_change_1d_list.append(df['pct_changed_1d'].values[1]) 
            percent_change_1w_list.append(df['pct_changed_1w'].values[1])        
      
    df = pd.DataFrame(columns=['coin_name', 'coin_currency', 'price', 
        'percent_change_1m','percent_change_1h','percent_change_1d', 'percent_change_1w'])
    df['coin_name'] = coin_name_list
    df['coin_currency'] = coin_currency_list
    df['price'] = price_list
    df['percent_change_1m'] = percent_change_1m_list
    df['percent_change_1h'] = percent_change_1h_list
    df['percent_change_1d'] = percent_change_1d_list
    df['percent_change_1w'] = percent_change_1w_list
    df['positive_percent_change_1m'] = df['percent_change_1m'] > 0
    df['positive_percent_change_1h'] = df['percent_change_1h'] > 0
    df['positive_percent_change_1d'] = df['percent_change_1d'] > 0
    df['positive_percent_change_1w'] = df['percent_change_1w'] > 0
    
    df = df.set_index('coin_name')
    
    # %%
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Meiryo'  # Meiryo, Yu Gothic
    plt.style.use('fivethirtyeight')        # 'fivethirtyeight' 'ggplot'
    plt.figure(figsize=(10,12))  # 10, 12
    
    if percent_timeframe == '1m':
        df.sort_values('percent_change_1m', ascending=True, inplace=True)
        df['percent_change_1m'].plot(kind='barh', color=df.positive_percent_change_1m.map({True: 'g', False: 'r'})) 
    elif percent_timeframe == '1h':
        df.sort_values('percent_change_1h', ascending=True, inplace=True)    
        df['percent_change_1h'].plot(kind='barh', color=df.positive_percent_change_1h.map({True: 'g', False: 'r'})) 
    elif percent_timeframe == '1d':
        df.sort_values('percent_change_1d', ascending=True, inplace=True)    
        df['percent_change_1d'].plot(kind='barh', color=df.positive_percent_change_1d.map({True: 'g', False: 'r'})) 
    else:
        df.sort_values('percent_change_1w', ascending=True, inplace=True)    
        df['percent_change_1w'].plot(kind='barh', color=df.positive_percent_change_1w.map({True: 'g', False: 'r'})) 
     
    plt.legend()
    plt.grid(False)
    plt.ylabel('Crypto Symbols')
    plt.title(f'Binance Crypto Price Change\n(USDT)')
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    
    # %%