仮想通貨のアルゴリズム取引 — Bot開発・API活用・DeFi自動化の実践ガイド
中級〜上級
アルゴリズム取引自動売買取引所APIDeFi
仮想通貨アルゴリズム取引の概要
仮想通貨市場は、24時間365日稼働、高ボラティリティ、充実したAPI、DeFiのプログラマビリティという特性から、アルゴリズム取引に最も適した市場の一つです。
株式市場との比較
| 特性 | 株式市場 | 仮想通貨市場 |
|---|---|---|
| 取引時間 | 平日の限定時間 | 24/365 |
| API整備 | 証券会社による | 標準的に提供 |
| 最小取引単位 | 1株〜 | 極小単位 |
| ボラティリティ | 低〜中 | 高 |
| 市場の効率性 | 高い | 比較的低い(非効率が多い) |
| DeFi | なし | プログラマブルな金融 |
CEX(中央集権型取引所)でのBot開発
主要取引所API
| 取引所 | REST API | WebSocket | 手数料(Maker/Taker) |
|---|---|---|---|
| Binance | あり | あり | 0.1% / 0.1% |
| Bybit | あり | あり | 0.1% / 0.1% |
| OKX | あり | あり | 0.08% / 0.1% |
| bitFlyer | あり | あり(限定的) | 0.01-0.15% |
| GMOコイン | あり | あり | Maker -0.01% / Taker 0.05% |
基本的なBot構成
# 取引Botの基本アーキテクチャ
import ccxt # 統一取引所API
class TradingBot:
def __init__(self, exchange_id, api_key, secret):
self.exchange = getattr(ccxt, exchange_id)({
'apiKey': api_key,
'secret': secret,
})
def fetch_data(self, symbol, timeframe='1h'):
"""OHLCVデータの取得"""
return self.exchange.fetch_ohlcv(symbol, timeframe)
def generate_signal(self, data):
"""取引シグナルの生成"""
# 例: 単純移動平均クロスオーバー
short_ma = calculate_sma(data, period=20)
long_ma = calculate_sma(data, period=50)
if short_ma[-1] > long_ma[-1] and short_ma[-2] <= long_ma[-2]:
return 'BUY'
elif short_ma[-1] < long_ma[-1] and short_ma[-2] >= long_ma[-2]:
return 'SELL'
return 'HOLD'
def execute_order(self, symbol, side, amount):
"""注文の実行"""
return self.exchange.create_order(
symbol=symbol,
type='limit',
side=side,
amount=amount,
price=self.exchange.fetch_ticker(symbol)['last']
)
def run(self, symbol):
"""メインループ"""
data = self.fetch_data(symbol)
signal = self.generate_signal(data)
if signal != 'HOLD':
self.execute_order(symbol, signal.lower(), 0.01)
ccxt(統一取引所ライブラリ)
100以上の取引所に対応した統一APIライブラリ:
import ccxt
# 取引所ごとの差異を吸収
binance = ccxt.binance({'apiKey': '...', 'secret': '...'})
bybit = ccxt.bybit({'apiKey': '...', 'secret': '...'})
# 同じコードで異なる取引所にアクセス
for exchange in [binance, bybit]:
ticker = exchange.fetch_ticker('BTC/USDT')
print(f"{exchange.id}: {ticker['last']}")
主要な取引戦略
1. アービトラージ(裁定取引)
取引所間アービトラージ
Binance: BTC/USDT = $64,000
Bybit: BTC/USDT = $64,100
→ Binanceで購入、Bybitで売却 = $100/BTC の利益
(送金時間、手数料、スリッページを考慮)
三角アービトラージ
BTC/USDT → ETH/BTC → ETH/USDT → USDT
1. 64,000 USDT → 1 BTC
2. 1 BTC → 26.67 ETH(BTC/ETH = 0.0375)
3. 26.67 ETH → 64,100 USDT(ETH/USDT = 2,403.75)
利益: 100 USDT(手数料前)
2. マーケットメイキング
スプレッド(売値と買値の差)から利益を得る戦略:
現在価格: $64,000
買い注文: $63,990(-$10)
売り注文: $64,010(+$10)
両方約定 → $20の利益(スプレッド収益)
リスク: 一方向に大きく動くと在庫リスク
対策: インベントリ管理、ヘッジ
3. トレンドフォロー
# 移動平均クロスオーバー戦略
def trend_following(data, short_period=20, long_period=50):
short_ma = data['close'].rolling(short_period).mean()
long_ma = data['close'].rolling(long_period).mean()
signals = pd.DataFrame(index=data.index)
signals['signal'] = 0
signals.loc[short_ma > long_ma, 'signal'] = 1 # ロング
signals.loc[short_ma < long_ma, 'signal'] = -1 # ショート
return signals
4. 平均回帰
# ボリンジャーバンド戦略
def mean_reversion(data, period=20, num_std=2):
ma = data['close'].rolling(period).mean()
std = data['close'].rolling(period).std()
upper = ma + num_std * std
lower = ma - num_std * std
signals = pd.DataFrame(index=data.index)
signals['signal'] = 0
signals.loc[data['close'] < lower, 'signal'] = 1 # 売られすぎ→買い
signals.loc[data['close'] > upper, 'signal'] = -1 # 買われすぎ→売り
return signals
5. ファンディングレートアービトラージ
先物市場のファンディングレート(資金調達率)を利用:
永久先物のファンディングレート: +0.03%(8時間ごと)
→ ロングがショートに0.03%を支払う
戦略:
現物: BTC 1枚 ロング($64,000)
先物: BTC 1枚 ショート($64,000)
→ 価格変動リスクなし
→ ファンディングレート収入: 0.03% × 3回/日 × 365日 = 年利約33%
注意: ファンディングレートは変動するため実際の利回りは異なる
オンチェーン分析
主要指標
| 指標 | 概要 | シグナル |
|---|---|---|
| MVRV比率 | 時価総額 / 実現時価総額 | >3.5で過熱、<1で割安 |
| SOPR | 送金時の損益比率 | >1で利確フェーズ |
| NVT比率 | 時価総額 / 送金額 | 高い→割高 |
| Exchange Netflow | 取引所への純流入 | 流入増→売り圧力 |
| アクティブアドレス | 取引に参加するアドレス数 | ネットワーク活動の指標 |
クジラ(大口保有者)追跡
# オンチェーンデータの取得(概念例)
def track_whale_movements(min_amount_btc=100):
"""大口送金を監視"""
transactions = get_large_transactions(min_amount_btc)
for tx in transactions:
if is_exchange_address(tx['to']):
# 取引所への大量送金 → 売り圧力の可能性
alert("WHALE DEPOSIT", tx)
elif is_exchange_address(tx['from']):
# 取引所からの大量出金 → 長期保有の意思
alert("WHALE WITHDRAWAL", tx)
DeFiでの自動取引
DEXアービトラージBot
# Uniswap v2 アービトラージの概念
from web3 import Web3
class DexArbitrage:
def __init__(self, w3, router_a, router_b):
self.w3 = w3
self.router_a = router_a # Uniswap
self.router_b = router_b # SushiSwap
def check_opportunity(self, token_a, token_b, amount):
"""価格差の確認"""
price_a = self.router_a.getAmountsOut(amount, [token_a, token_b])
price_b = self.router_b.getAmountsOut(amount, [token_a, token_b])
spread = abs(price_a - price_b) / min(price_a, price_b)
gas_cost = self.estimate_gas_cost()
if spread * amount > gas_cost * 2: # ガス代の2倍以上の利益
return True, spread
return False, 0
def execute(self, token_a, token_b, amount, direction):
"""アービトラージの実行"""
if direction == 'A_TO_B':
self.router_a.swapExactTokensForTokens(amount, ...)
self.router_b.swapExactTokensForTokens(received, ...)
フラッシュローンBot
// Aaveフラッシュローンによるアービトラージ
contract FlashLoanArbitrage is IFlashLoanReceiver {
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initiator,
bytes calldata params
) external override returns (bool) {
uint256 borrowed = amounts[0];
// 1. DEX Aで安く購入
uint256 received = swapOnDexA(assets[0], borrowed);
// 2. DEX Bで高く売却
uint256 profit = swapOnDexB(assets[0], received);
// 3. 借入金 + 手数料を返済
uint256 amountOwed = borrowed + premiums[0];
IERC20(assets[0]).approve(msg.sender, amountOwed);
// 利益 = profit - amountOwed
return true;
}
}
リスク管理
ポジションサイジング
def kelly_criterion(win_rate, win_loss_ratio):
"""ケリー基準によるポジションサイズ計算"""
kelly = win_rate - (1 - win_rate) / win_loss_ratio
# フルケリーは積極的すぎるため、半分にする
return max(0, kelly * 0.5)
# 例: 勝率55%、利益/損失比率1.5
position_size = kelly_criterion(0.55, 1.5)
# → 資金の約12.5%をリスクにさらす
主要リスクと対策
| リスク | 内容 | 対策 |
|---|---|---|
| 市場リスク | 価格の急変動 | ストップロス、ポジションサイジング |
| 流動性リスク | 約定できない、スリッページ | 取引量の確認、指値注文 |
| API障害 | 取引所APIのダウン | 複数取引所の冗長化 |
| スマートコントラクトリスク | コードの脆弱性 | 監査済みプロトコルの利用 |
| MEVリスク | フロントランニング等 | Flashbots、プライベートプール |
| 規制リスク | Bot取引の規制 | 法的確認、コンプライアンス |
バックテスト
import pandas as pd
import numpy as np
class Backtester:
def __init__(self, data, initial_capital=10000):
self.data = data
self.capital = initial_capital
self.positions = []
self.trades = []
def run(self, strategy_func):
"""バックテストの実行"""
signals = strategy_func(self.data)
position = 0
for i, row in self.data.iterrows():
signal = signals.loc[i, 'signal']
if signal == 1 and position == 0: # 買いシグナル
position = self.capital / row['close']
self.capital = 0
self.trades.append(('BUY', row['close'], i))
elif signal == -1 and position > 0: # 売りシグナル
self.capital = position * row['close']
position = 0
self.trades.append(('SELL', row['close'], i))
# 最終評価
final_value = self.capital + position * self.data.iloc[-1]['close']
return {
'total_return': (final_value / 10000 - 1) * 100,
'num_trades': len(self.trades),
'sharpe_ratio': self.calculate_sharpe(),
}
インフラ構成
本番環境の推奨構成
┌─────────────────────────────────────┐
│ 取引Bot サーバー │
│ (AWS/GCP、取引所に近いリージョン) │
├─────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────────┐ │
│ │ データ収集 │ │ シグナル生成 │ │
│ │ (WebSocket)│ │ (戦略エンジン)│ │
│ └─────┬────┘ └──────┬───────┘ │
│ │ │ │
│ ┌─────▼──────────────▼───────┐ │
│ │ 注文実行エンジン │ │
│ │ (リスク管理、レート制限) │ │
│ └─────────────┬───────────────┘ │
│ │ │
│ ┌─────────────▼───────────────┐ │
│ │ 取引所API / DEXコントラクト │ │
│ └─────────────────────────────┘ │
│ │
│ ┌─────────────────────────────┐ │
│ │ 監視・アラート(Grafana等) │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────┘
まとめ
| 要素 | ポイント |
|---|---|
| CEXでの取引 | ccxt等の統一APIで複数取引所対応 |
| 主要戦略 | アービトラージ、トレンドフォロー、マーケットメイキング |
| オンチェーン分析 | MVRV、クジラ追跡等の独自指標 |
| DeFi自動化 | スマートコントラクトによる原子的取引 |
| リスク管理 | ポジションサイジング、分散化、監視 |
この記事シリーズの関連記事: