仮想通貨のトレードをするときに、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 | 設定値 |
|---|---|
| category | linear |
| symbol | BTCUSDT |
| startTime | 設定しない |
| endTime | 初回は未設定(最新が取得できる)。2回目以降は取得済みデータの最も古いタイムスタンプ。 |
| limit | 設定しない(デフォルトは200個) |
フローチャート
処理内容は、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%に到達しています。


