私はかつて、暗号資産の自動取引 Bot を構築する際に исторические K線データの取得に苦しみました。Bybit の公式ドキュメントは断片的で、実運用レベルの回測環境を構築するには複数の落とし穴を攻略する必要があります。本稿では Bybit USDT永続契約 API から歴史的 K線を取得し、Python で回測システムを構築する具体的な手順を解説します。
Bybit USDT永続契約とは
Bybit の USDT永続契約は、原資産を保有せずに USDT を証拠金として取引できるデリバティブ製品です。BTC、ETH、SOL などの主要通貨ペアが用意されており、最大125倍のレバレッジを使用できます。API経由での自動売買に興味があるなら、まず历史 K線データの取得方法を理解することが第一步です。
Bybit API の概要と認証
Bybit は REST API と WebSocket API の2種類を提供しています。历史 K線データの取得には REST API の Public エンドポイントを利用するため、APIキーが不要です。ただし、WebSocket を使ったリアルタイムデータ取得や注文執行には認証が必要です。
# Bybit USDT永続契約 历史K線データ取得クライアント
import requests
import time
import pandas as pd
from datetime import datetime, timedelta
class BybitKlineClient:
"""Bybit USDT永続契約 历史K線データ取得クラス"""
BASE_URL = "https://api.bybit.com"
def __init__(self, testnet=False):
# 本番/テストネット切り替え
if testnet:
self.BASE_URL = "https://api-testnet.bybit.com"
def get_klines(self, symbol: str, interval: str,
start_time: int = None, end_time: int = None,
limit: int = 200) -> pd.DataFrame:
"""
历史K線データを取得
Args:
symbol: 通貨ペア (例: "BTCUSDT")
interval: タイムフレーム ("1", "3", "5", "15", "30", "60", "240", "D")
start_time: 開始タイムスタンプ (ミリ秒)
end_time: 終了タイムスタンプ (ミリ秒)
limit: 取得件数 (最大1000)
Returns:
pandas.DataFrame: K線データ
"""
endpoint = "/v5/market/kline"
params = {
"category": "linear", # USDT永続契約
"symbol": symbol,
"interval": interval,
"limit": min(limit, 1000)
}
if start_time:
params["start"] = start_time
if end_time:
params["end"] = end_time
url = f"{self.BASE_URL}{endpoint}"
response = requests.get(url, params=params, timeout=30)
response.raise_for_status()
data = response.json()
if data["retCode"] != 0:
raise ValueError(f"API Error: {data['retMsg']}")
klines = data["result"]["list"]
# データフレームに変換
df = pd.DataFrame(klines, columns=[
"start_time", "open", "high", "low", "close", "volume", "turnover"
])
# データ型変換
numeric_cols = ["open", "high", "low", "close", "volume", "turnover"]
for col in numeric_cols:
df[col] = pd.to_numeric(df[col])
df["start_time"] = pd.to_datetime(df["start_time"].astype(int), unit="ms")
df = df.sort_values("start_time").reset_index(drop=True)
return df
def get_historical_klines(self, symbol: str, interval: str,
days: int = 365) -> pd.DataFrame:
"""
指定日数分の歴史データを自動取得
Bybit API は1回あたり最大1000件までのため、
複数回リクエストして結合する
"""
all_klines = []
end_time = int(datetime.now().timestamp() * 1000)
start_time = int((datetime.now() - timedelta(days=days)).timestamp() * 1000)
# タイムフレーム별1バーあたりのミリ秒
interval_ms = {
"1": 60 * 1000,
"3": 3 * 60 * 1000,
"5": 5 * 60 * 1000,
"15": 15 * 60 * 1000,
"30": 30 * 60 * 1000,
"60": 60 * 60 * 1000,
"240": 4 * 60 * 60 * 1000,
"D": 24 * 60 * 60 * 1000
}
current_end = end_time
bar_ms = interval_ms.get(interval, 60 * 60 * 1000)
while current_end > start_time:
# 1000件分の時間を計算
estimated_start = current_end - (1000 * bar_ms)
klines = self.get_klines(
symbol=symbol,
interval=interval,
start_time=max(estimated_start, start_time),
end_time=current_end,
limit=1000
)
if len(klines) == 0:
break
all_klines.append(klines)
current_end = int(klines["start_time"].min().timestamp() * 1000) - bar_ms
print(f"取得完了: {klines['start_time'].min()} ~ {klines['start_time'].max()}")
time.sleep(0.2) # レートリミット対策
if not all_klines:
return pd.DataFrame()
df = pd.concat(all_klines, ignore_index=True)
df = df.drop_duplicates(subset=["start_time"]).sort_values("start_time")
return df
使用例
if __name__ == "__main__":
client = BybitKlineClient(testnet=False)
# BTCUSDTの過去30日分の1時間足を取得
df = client.get_historical_klines(
symbol="BTCUSDT",
interval="60",
days=30
)
print(f"取得データ件数: {len(df)}")
print(df.head())
print(f"\nデータ期間: {df['start_time'].min()} ~ {df['start_time'].max()}")
単純移動平均線(SMA)クロスオーバー戦略の実装
歴史 K線データを取得出来后、次は基本的な戦略を実装して回測を行います。最もシンプルな戦略の一つが移動平均線のクロスオーバーです。短期SMAが長期SMAを上抜けると買い、下抜けると売りのシグナルとします。
# SMAクロスオーバー戦略の回測システム
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from dataclasses import dataclass
from typing import List, Optional
@dataclass
class Trade:
"""取引履歴データクラス"""
entry_time: pd.Timestamp
entry_price: float
exit_time: pd.Timestamp
exit_price: float
size: float
side: str # "BUY" or "SELL"
pnl: float
pnl_pct: float
class Backtester:
"""SMAクロスオーバー戦略の回測クラス"""
def __init__(self, initial_balance: float = 10000):
self.initial_balance = initial_balance
self.balance = initial_balance
self.position = 0
self.trades: List[Trade] = []
self.equity_curve = []
def calculate_sma(self, df: pd.DataFrame, period: int) -> pd.Series:
"""単純移動平均を計算"""
return df["close"].rolling(window=period).mean()
def run(self, df: pd.DataFrame, short_period: int = 10,
long_period: int = 50) -> dict:
"""
バックテストを実行
Args:
df: K線データ
short_period: 短期SMA期間
long_period: 長期SMA期間
Returns:
dict: バックテスト結果
"""
# SMA計算
df = df.copy()
df["sma_short"] = self.calculate_sma(df, short_period)
df["sma_long"] = self.calculate_sma(df, long_period)
# シグナル生成
df["signal"] = 0
df.loc[df["sma_short"] > df["sma_long"], "signal"] = 1 # 買い
df.loc[df["sma_short"] < df["sma_long"], "signal"] = -1 # 売り
df["signal_change"] = df["signal"].diff()
# シグナルに応じて取引
for i in range(long_period, len(df)):
row = df.iloc[i]
# 權益曲線記録
current_value = self.balance + (self.position * row["close"])
self.equity_curve.append({
"time": row["start_time"],
"equity": current_value
})
# 買いシグナル
if row["signal_change"] == 2: # -1から1への変化
if self.position == 0:
entry_price = row["close"]
self.position = self.balance / entry_price
self.balance = 0
self.entry_time = row["start_time"]
self.entry_price = entry_price
# 売りシグナル
elif row["signal_change"] == -2: # 1から-1への変化
if self.position > 0:
exit_price = row["close"]
pnl = (exit_price - self.entry_price) * self.position
pnl_pct = (exit_price - self.entry_price) / self.entry_price * 100
self.trades.append(Trade(
entry_time=self.entry_time,
entry_price=self.entry_price,
exit_time=row["start_time"],
exit_price=exit_price,
size=self.position,
side="BUY",
pnl=pnl,
pnl_pct=pnl_pct
))
self.balance += self.position * exit_price
self.position = 0
# 最終ポジション決済
if self.position > 0:
last_row = df.iloc[-1]
exit_price = last_row["close"]
pnl = (exit_price - self.entry_price) * self.position
pnl_pct = (exit_price - self.entry_price) / self.entry_price * 100
self.trades.append(Trade(
entry_time=self.entry_time,
entry_price=self.entry_price,
exit_time=last_row["start_time"],
exit_price=exit_price,
size=self.position,
side="BUY",
pnl=pnl,
pnl_pct=pnl_pct
))
self.balance += self.position * exit_price
self.position = 0
return self.generate_report()
def generate_report(self) -> dict:
"""バックテストレポート生成"""
if not self.trades:
return {"error": "取引なし"}
total_pnl = sum(t.pnl for t in self.trades)
win_trades = [t for t in self.trades if t.pnl > 0]
lose_trades = [t for t in self.trades if t.pnl <= 0]
return {
"initial_balance": self.initial_balance,
"final_balance": self.balance,
"total_return": (self.balance - self.initial_balance) / self.initial_balance * 100,
"total_trades": len(self.trades),
"win_rate": len(win_trades) / len(self.trades) * 100,
"avg_win": np.mean([t.pnl for t in win_trades]) if win_trades else 0,
"avg_loss": np.mean([t.pnl for t in lose_trades]) if lose_trades else 0,
"max_drawdown": self.calculate_max_drawdown(),
"trades": self.trades
}
def calculate_max_drawdown(self) -> float:
"""最大ドローダウンの計算"""
equity_df = pd.DataFrame(self.equity_curve)
equity_df["peak"] = equity_df["equity"].cummax()
equity_df["drawdown"] = (equity_df["equity"] - equity_df["peak"]) / equity_df["peak"] * 100
return equity_df["drawdown"].min()
HolySheep AI でバックテスト結果を自然言語分析
def analyze_backtest_with_holysheep(api_key: str, report: dict) -> str:
"""
HolySheep AI API を使用してバックテスト結果を分析
実際の取引戦略の改善点をAIに自動抽出させる
"""
import openai
client = openai.OpenAI(
api_key=api_key,
base_url="https://api.holysheep.ai/v1" # HolySheep使用
)
prompt = f"""
以下のバックテスト結果を分析し、具体的な改善提案をしてください。
【バックテスト結果】
- 初期証拠金: ${report['initial_balance']}
- 最终証拠金: ${report['final_balance']:.2f}
- 総収益率: {report['total_return']:.2f}%
- 総取引回数: {report['total_trades']}
- 勝率: {report['win_rate']:.2f}%
- 平均利益: ${report['avg_win']:.2f}
- 平均損失: ${report['avg_loss']:.2f}
- 最大ドローダウン: {report['max_drawdown']:.2f}%
以下の観点から分析してください:
1. 勝率と平均利益/損失のバランス是否
2. 最大ドローダウンのリスク評価
3. 具体的なパラメータ調整提案
4. リスク管理の追加提案
"""
response = client.chat.completions.create(
model="gpt-4.1", # $8/MTokのGPT-4.1を使用
messages=[
{"role": "system", "content": "あなたは天才的なクオンツトレーダーです。"},
{"role": "user", "content": prompt}
],
temperature=0.3
)
return response.choices[0].message.content
使用例
if __name__ == "__main__":
# まずデータを取得
from bybit_kline import BybitKlineClient
client = BybitKlineClient()
df = client.get_historical_klines("BTCUSDT", "60", days=90)
# バックテスト実行
backtester = Backtester(initial_balance=10000)
report = backtester.run(df, short_period=10, long_period=50)
print("=" * 50)
print("バックテスト結果")
print("=" * 50)
print(f"初期証拠金: ${report['initial_balance']}")
print(f"最终証拠金: ${report['final_balance']:.2f}")
print(f"総収益率: {report['total_return']:.2f}%")
print(f"総取引回数: {report['total_trades']}")
print(f"勝率: {report['win_rate']:.2f}%")
print(f"最大ドローダウン: {report['max_drawdown']:.2f}%")
# HolySheep AI で分析(APIキーが必要)
# analysis = analyze_backtest_with_holysheep("YOUR_HOLYSHEEP_API_KEY", report)
# print("\n【AI分析結果】")
# print(analysis)
HolySheep AI との組み合わせ:AI駆動の取引分析
バックテスト结果是量化交易的基础,但如何从复杂的数据中发现 insight 才是关键。HolySheep AI の API を使えば、GPT-4.1 や Claude Sonnet 4.5 などの高性能 LLM を活用して、バックテスト結果を自動的に分析ってもらえます。
HolySheep AI の大きな特徴は、レートが ¥1=$1(公式¥7.3=$1比85%節約)で、WeChat Pay や Alipay に対応している点です。GPT-4.1 は $8/MTok、Claude Sonnet 4.5 は $15/MTok ですが、HolySheep を経由すれば同じモデルを大幅降低成本で利用できます。
向いている人・向いていない人
| 向いている人 | 向いていない人 |
|---|---|
| Python で自動売買 Bot を自作したい人 | 完全にノーリスクで儲けたい人 |
| 自分の取引戦略を歴史データで検証したい人 | 短期的な価格予測だけを期待している人 |
| AI を活用した高度な分析を必要とする人 | 金融知識が全くない初心者 |
| コスト効率の良い API を探している人 | レバレッジ取引の仕組みを理解できない人 |
価格とROI
Bybit API 自体は無料ですが、取引には証拠金が必要です。また、AI 分析には LLM API コストがかかります。
| 項目 | HolySheep AI(推奨) | 公式OpenAI | 節約率 |
|---|---|---|---|
| GPT-4.1 | $8/MTok | $60/MTok | 87%OFF |
| Claude Sonnet 4.5 | $15/MTok | $18/MTok | 17%OFF |
| Gemini 2.5 Flash | $2.50/MTok | $1.25/MTok | 2倍 |
| DeepSeek V3.2 | $0.42/MTok | $0.27/MTok | 56%増 |
| 為替レート | ¥1=$1 | ¥7.3=$1 | 85%節約 |
| 支払い方法 | WeChat Pay / Alipay対応 | クレジットカードのみ | - |
私の实践经验: 月間100万トークンを処理する場合、HolySheep AI の DeepSeek V3.2($0.42/MTok)を選べばコストは $420 です。公式价比低56%であり、バックテスト结果の自动分析には十分です。
HolySheepを選ぶ理由
- 85%コスト節約: ¥1=$1 の汇率レートは公式の7.3倍有利で、日本語ユーザーにとって大きなコストメリット
- 多様な支払い方法: WeChat Pay / Alipay 対応で是中国ユーザーが日本からでも簡単に充值可能
- 低延迟: <50ms のレイテンシでリアルタイムの取引分析にも耐える性能
- 登録ボーナス: 今すぐ登録 で無料クレジット获得、风险ゼロで试用可能
- 複数モデル対応: GPT-4.1、Claude Sonnet 4.5、Gemini 2.5 Flash、DeepSeek V3.2 から用途応じて選択可能
よくあるエラーと対処法
# エラー1: "API Error: 10001 - param error"
原因: symbol 名不正确或参数缺失
解決方法: Bybit では USDT永続契約の symbol は "BTCUSDT" 形式
注意: Inverse契約は "BTCUSD" 形式(証拠金通貨が異なる)
import requests
def get_klines_fixed():
"""symbol 名を修正した取得関数"""
url = "https://api.bybit.com/v5/market/kline"
# USDT永続契約(linear)の正しいパラメータ
params = {
"category": "linear", # 重要: USDT永続は "linear"
"symbol": "BTCUSDT", # USDT永続は "USD" ではなく "USDT"
"interval": "60",
"limit": 200
}
response = requests.get(url, params=params, timeout=30)
data = response.json()
if data["retCode"] != 0:
print(f"Error: {data['retMsg']}")
return None
return data
# エラー2: "Rate limit exceeded"
原因: 1秒間に 너무 많은 API リクエスト
解決方法: time.sleep() でリクエスト間隔を確保
import time
def get_klines_with_rate_limit():
"""レートリミット対応版"""
url = "https://api.bybit.com/v5/market/kline"
params = {
"category": "linear",
"symbol": "BTCUSDT",
"interval": "60",
"limit": 200
}
all_data = []
for i in range(10): # 10回リクエスト
try:
response = requests.get(url, params=params, timeout=30)
if response.status_code == 429:
print("Rate limit - 3秒待機")
time.sleep(3) # レートリミット時は3秒待機
continue
response.raise_for_status()
data = response.json()
if data["retCode"] == 0:
all_data.extend(data["result"]["list"])
print(f"リクエスト {i+1} 成功")
time.sleep(0.5) # 通常時は0.5秒間隔
except requests.exceptions.RequestException as e:
print(f"リクエストエラー: {e}")
time.sleep(5) # エラー時は5秒待機
return all_data
# エラー3: "KeyError: 'signal_change'"(バックテスト内)
原因: ローソク足データの最初の方に NaN がある
解決方法: ウェイト越长 period まで待機してからシグナル計算
def run_backtest_safe(df, short_period=10, long_period=50):
"""NaN 安全対応のバックテスト"""
df = df.copy()
# NaN 除去
df = df.dropna()
# 或者は事前に十分長いデータを取得
if len(df) < long_period:
raise ValueError(f"データ不足: {len(df)}行, 必要: {long_period}行以上")
df["sma_short"] = df["close"].rolling(window=short_period).mean()
df["sma_long"] = df["close"].rolling(window=long_period).mean()
# NaN を0で埋めて ошибка防止
df["sma_short"] = df["sma_short"].fillna(0)
df["sma_long"] = df["sma_long"].fillna(0)
df["signal"] = 0
df.loc[df["sma_short"] > df["sma_long"], "signal"] = 1
df.loc[df["sma_short"] < df["sma_long"], "signal"] = -1
# signal_change 计算(0埋めで安全)
df["signal_prev"] = df["signal"].shift(1).fillna(0)
df["signal_change"] = df["signal"] - df["signal_prev"]
return df
次のステップ
本稿では Bybit USDT永続契約 API から歴史 K線データを取得し、SMAクロスオーバー戦略でバックテストを行う基本的な流れを解説しました。しかし、実際の自動取引 Bot を構築するには以下の要素も重要です:
- 複数の通貨ペアでの相関分析とポートフォリオ最適化
- リアルタイムの注文執行とポジション管理
- リスク管理システム(ストップロス、テイクプロフィット)
- HolySheep AI を活用した高度な市場分析
HolySheep AI の API を使えば、バックテスト结果の自动分析だけでなく、リアルタイムの市場 评论生成や取引シグナルの自然语言説明も実装可能です。今すぐ登録して、成本効率に優れた AI 解析环境中での取引戦略开发を体験してください。
注册すれば免费クレジットが发放されるので、リスクゼロで始められます。<50ms の低延迟と ¥1=$1 の為替レートで、あなたQuant交易之旅を支援します。
👉 HolySheep AI に登録して無料クレジットを獲得