BybitのAPIを使ってFR(資金調達率)のグラフを自作する

仮想通貨のトレードするときに、FR(Funding Rate:資金調達率)の過去データを見ていますか?

coinglassのサイトで見れるこのようなグラフです。
https://www.coinglass.com/ja/FundingRate

BybitではFRのヒストリカルデータをAPIで取得できます。
Bybitの口座を開設していなくても取得可能です。

APIは”Get Funding Rate History”です。
https://bybit-exchange.github.io/docs/v5/market/history-fund-rate

これを使ってFRのグラフを自作してみたいと思います。
自作できるようになると、BTCUSDTだけでなく、他の仮想通貨のFRグラフも作れるようになります。

それでは、FRヒストリカルデータの取得方法とグラフ作成方法を、Pythonのサンプルコードをお見せしながらご紹介します。

FRヒストリカルデータの取得方法

まずは、FRのヒストリカルデータを取得する流れを説明します。
今回は例として、BTCUSDT無期限契約のFRのグラフを作成します。

FRヒストリカルデータ取得APIのパラメータ

BybitのAPIのパラメータはこうなっています。

BTCUSDT無期限契約のグラフを作成するので、パラメータ設定値は以下とします。

Parameter設定値
categorylinear
symbolBTCUSDT
startTime設定しない
endTime初回は未設定(最新が取得できる)。2回目以降は取得済みデータの最も古いタイムスタンプ。
limit設定しない(デフォルトは200個)
FRヒストリカルデータ取得APIのパラメータ設定値

フローチャート

処理内容は、FR取得APIを取得期間を変えて複数回呼び、必要な期間のFRデータを揃えます。
フローチャートは以下のようになります。

FRデータ取得のサンプルコード

Pythonを使って、実際にFRのヒストリカルデータを取得してみます。

取得するデータの期間は3ヶ月とします。
API呼び出し1回で取得できるデータ数が200個です。
FRは1日に3回更新されるので、1ヶ月だと3✕31=93個なので、APIコールが1回で済んでしまいます。
サンプルコードのループ処理が正しく動くことを示したいので、期間は3ヶ月とします。

サンプルコードでは、必要な関数を作成して、メイン処理から呼び出すようにします。
作成する関数の説明とメイン処理の説明をしていきます。

FRヒストリカルデータ取得関数

まずは、データを取得する関数のコードです。

関数名はget_funding_rate_history()としました。
引数は、「仮想通貨ペアの名前」と「取得期間の終端のタイムスタンプ」です。

def get_funding_rate_history(symbol, end_time):
    endPoint = 'https://api.bybit.com'
    path     = '/v5/market/funding/history'
    url = endPoint + path

    params = {
        'category': 'linear',
        'symbol': symbol,
        'endTime': end_time,
    }

    response = requests.get(url, params=params)
    res = response.json()
    return res

FRヒストリカルデータをDataFrameにする関数

BybitのFRヒストリカルデータ取得APIのレスポンスパラメータは以下です。

実際には、このようなレスポンスが返ります。

{
    "retCode": 0,
    "retMsg": "OK",
    "result": {
        "category": "linear",
        "list": [
            {
                "symbol": "BTCUSDT",
                "fundingRate": "0.0001",
                "fundingRateTimestamp": "1729152000000"
            },
            {
                "symbol": "BTCUSDT",
                "fundingRate": "0.0001",
                "fundingRateTimestamp": "1729123200000"
            },
            {
                "symbol": "BTCUSDT",
                "fundingRate": "0.0001",
                "fundingRateTimestamp": "1729094400000"
            },
            {
                "symbol": "BTCUSDT",
                "fundingRate": "0.0001",
                "fundingRateTimestamp": "1729065600000"
            },
            {
                "symbol": "BTCUSDT",
                "fundingRate": "0.0001",
                "fundingRateTimestamp": "1729036800000"
            },
            {
                "symbol": "BTCUSDT",
                "fundingRate": "0.0001",
                "fundingRateTimestamp": "1729008000000"
            }
        ]
    },
    "retExtInfo": {},
    "time": 1729165018157
}

このレスポンスの情報を扱いやすいようにDataFrameに入れます。
具体的には、”list”部分のFR情報のみ抜き出します。
その関数がconvert_data()です。

def convert_data(data):
    # FRデータを入れるDataFrame。
    df = pd.DataFrame()

    # FRデータが入っているリストから情報を取り出して、DataFrameに入れる。
    for d in data['result']['list']:
        df_add = pd.DataFrame(d, index=[0])
        df = pd.concat([df, df_add], axis='index')
    df = df.reset_index(drop=True)

    # FRはfloat型に変換する。
    df['fundingRate'] = df['fundingRate'].astype('float64')

    # タイムスタンプはint型に変換する。
    df['fundingRateTimestamp'] = df['fundingRateTimestamp'].astype('int64')
    return df

メイン処理

上のフローチャートで示したメインのループ処理のコードです。

3ヶ月分のBTCUSDTのFRデータを取得したら、ループ処理を抜けてdf_fr.csvに保存しています。
ループ処理から、上で説明した関数の get_funding_rate_history() と convert_data() を呼んでいます。

import os
import sys
import requests
import json
import time
from datetime import datetime
import pandas as pd

from dateutil import tz
JST = tz.gettz('Asia/Tokyo')
UTC = tz.gettz('UTC')

# 現在のUTC時刻を取得しておく。
now_utc = datetime.now(UTC)

# 取得するFRの通貨ペアを設定する。
# 今回はBTCUSDTとする。
symbol = 'BTCUSDT'

# エンドタイムスタンプを初期化する。
end_time = None

# FRを入れるDataFrameを初期化する。
df_fr = pd.DataFrame()

# ここから、ループ文で3ヶ月分のFRを取得する。
while True:

    # FRを取得する
    # end_timeはwhile文の中で毎回更新される。
    data = get_funding_rate_history(symbol, end_time)

    # 取得したFRを日付をIndexとするDataFrameに変換する。
    df_add = convert_data(data)

    # FRを保存するDataFrameに追加する。
    df_fr = pd.concat([df_fr, df_add], axis='index')

    # タイムスタンプのUNIX時間でソートする。未来の時刻が下側になるようにソートする。
    df_fr = df_fr.sort_values(by=['fundingRateTimestamp'], ascending=True)

    # 重複行は先頭を残す。
    # タイムスタンプで重複を判断する。
    df_fr = df_fr.drop_duplicates(subset='fundingRateTimestamp', keep='first')

    # Indexの通し番号を再度付与する。
    df_fr = df_fr.reset_index(drop=True)

    # 取得済みのFRの最も古いタイムスタンプを取得し、次に取得するFRの最後のタイムスタンプとする。
    # 先頭が最も古いタイムスタンプとなる。
    end_time = df_fr.iat[0, df_fr.columns.get_loc('fundingRateTimestamp')]

    # 最も古いタイムスタンプをUTC時刻に変換する。
    end_time_utc = datetime.fromtimestamp(end_time/1000, UTC)

    # 3ヶ月分のFRを取得できたら、抜ける。
    if (now_utc - end_time_utc).days > 31 * 3:
        break

    # 短時間にAPIを何度も呼ばないように1秒間寝る。
    time.sleep(1)

# FR情報をファイル出力する。
filename = 'df_fr.csv'
file_path = os.path.join(work_path, filename)
df_fr.to_csv(file_path)

変数work_pathには、ファイルを保存するディレクトリを設定してください。

これで、FRデータを取得できました。

FRヒストリカルデータのグラフ作成方法

次に、取得したFRヒストリカルデータをグラフ化します。

サンプルコード

処理を見やすくするために、グラフ作成処理は関数化します。

def draw_bar(df):
    fig, ax = plt.subplots(1, 1, figsize=(9.6, 3.6))

    x = []
    for timestamp in df['fundingRateTimestamp']:
        # X軸はdatetime型に変換する。
        x.append(timestamp.to_pydatetime())
    print(type(x[0]))

    # Y軸の単位は%にするために、100倍する。
    y = list(df['fundingRate'] * 100)

    ax.bar(
        x, y,
        width=0.2,
        alpha=0.6,
        label='FR[%]',
        )

    ax.legend() # 凡例の表示
    ax.grid(axis='y', linestyle='--', color='red') # グリッドラインの表示
    fig.autofmt_xdate()
    plt.show()
    return

メインの処理です。
FRデータをファイルから読み込んで、グラフ化関数を呼びます。

# FR情報をファイルから読み込む。
filename = 'df_fr.csv'
file_path = os.path.join(work_path, filename)
df_fr = pd.read_csv(file_path, index_col=0)

# タイムスタンプがUNIX時間になっているので、UTC時刻に変換する。
df_fr['fundingRateTimestamp'] = df_fr['fundingRateTimestamp'].apply(lambda x:datetime.fromtimestamp(x/1000, UTC))

# グラフを見やすくするため、データ数を減らす。FR情報を1ヶ月分にする。
df_fr = df_fr[df_fr['fundingRateTimestamp'] > datetime.now(UTC) - timedelta(days=31)]

# グラフ化関数を呼ぶ。
draw_bar(df_fr)

・import部分は省略させていただきます。
・3ヶ月分のデータだとグラフが細かくて見づらかったので、1ヶ月分に減らしています。
・変数work_pathには、FRデータのファイルを保存したディレクトリを設定してください。

自作したグラフの出力結果

完成したグラフがこちらになります。

BybitのFRは上限0.01%になっているようですね。
プラスになっていることが多いようです。

coinglassのグラフと比べてみます。
https://www.coinglass.com/ja/FundingRate

coinglassはデフォルトだと複数の取引所のデータがまざっているので、上部のチェックシートでBybitのみを選んでいます。
同じ期間を見ると、ほぼ同じグラフになっていることがわかります。

その他のコインのFRグラフ

BTCUSDTのFRのグラフ化はできたので、他のコインのFRのグラフも作成してみます。

SUIUSDT

2024年9月から10月に上昇トレンドを見せたSUIUSDTのFRデータです。
10月初旬は大きなマイナスになっています。

REEFUSDT

2024年10月15日に大暴落をしたREEFUSDTのFRデータです。
暴落付近はFRが-3%に到達しています。