Bot トレードロジック

仮想通貨botの開発記録#82(2024/7/29)「基本的な取引ロジックの雛形まとめ②」

2024年7月29日

前回の記事に引き続き、今回も仮想通貨botの開発状況をまとめていきます。

Yodaka

今回も5種類の基本的な取引ロジックの雛形をまとめました。

実際にbotで取引をしてみたいけれど、どんなコードを書いたら良いのか分からないという方の参考になると思います。

1.マーケットメイキング

Yodaka

買い気配と売り気配の間の狭いスプレッドで売買を行うタイプのbotです。

マーケットメイキング戦略は、買い注文(Bid)と売り注文(Ask)の間の価格差(スプレッド)を利用して利益を得る取引戦略です。この戦略の目的は、頻繁に小さな利益を積み重ねることにあります。以下に、Pythonとccxtライブラリを使用してマーケットメイキング戦略を実装するコードの基本的な雛形を示します。

必要なライブラリのインポート

import ccxt
import time

取引所の設定と初期化

exchange = ccxt.binance({
    'apiKey': 'YOUR_API_KEY',
    'secret': 'YOUR_API_SECRET',
    'enableRateLimit': True  # レートリミットを有効化
})
symbol = 'BTC/USDT'

オーダーブックから価格を取得し、注文を配置する関数

def market_make_order(symbol, spread_target):
    """
    オーダーブックを取得して、指定されたスプレッドに基づいて売買注文を配置する
    """
    orderbook = exchange.fetch_order_book(symbol)
    best_bid = orderbook['bids'][0][0] if orderbook['bids'] else None
    best_ask = orderbook['asks'][0][0] if orderbook['asks'] else None

    if best_bid and best_ask:
        mid_price = (best_bid + best_ask) / 2
        buy_price = mid_price * (1 - spread_target)
        sell_price = mid_price * (1 + spread_target)

        # ここで売買注文を配置
        amount = 0.01  # 取引量は適宜調整する
        print(f"Placing buy order at: {buy_price}, sell order at: {sell_price}")
        buy_order = exchange.create_limit_buy_order(symbol, amount, buy_price)
        sell_order = exchange.create_limit_sell_order(symbol, amount, sell_price)

        return buy_order, sell_order
    else:
        print("No sufficient data in order book")
        return None, None

ボットのメイン実行関数

def run_bot():
    """
    マーケットメイキング戦略を継続的に実行
    """
    while True:
        spread_target = 0.005  # スプレッドの目標値 (0.5%)
        market_make_order(symbol, spread_target)
        time.sleep(10)  # 取引間隔は適宜調整する

if __name__ == '__main__':
    run_bot()

このスクリプトでは、オーダーブックから最良のBidとAskを取得し、その中間価格を基にして目標スプレッドの範囲内で買い注文と売り注文を配置しています。マーケットメイキングは、価格変動リスクやオーダーの執行リスク(partial fillsやslippage)も伴うため、実際に運用する前にこれらの要素を考慮した上で適切なリスク管理策を検討することが重要です。

また、この雛形は非常に基本的なものであり、実際のマーケットコンディションや取引所のAPI仕様、さらには潜在的な技術的な問題(APIレートリミット、ネットワーク遅延など)に合わせて調整する必要があります。

2.オーダーフロー売買

Yodaka

売り買い注文の流れから価格変動を予測し、売買するタイプのbotです。

オーダーフロー売買戦略は、買い注文と売り注文の流れを分析して価格変動を予測し、それに基づいて売買を行います。以下はPythonとccxtライブラリを使用してオーダーフロー売買戦略を実装する基本的な雛形です。

必要なライブラリのインポート

import ccxt
import time

取引所の設定と初期化

exchange = ccxt.binance({
    'apiKey': 'YOUR_API_KEY',
    'secret': 'YOUR_API_SECRET',
    'enableRateLimit': True  # レートリミットを有効化
})
symbol = 'BTC/USDT'

オーダーブックを解析して売買注文を配置する関数

def analyze_order_flow(symbol):
    """
    オーダーブックを解析し、買い圧力と売り圧力を評価する
    """
    orderbook = exchange.fetch_order_book(symbol)
    bids = orderbook['bids']
    asks = orderbook['asks']

    buy_pressure = sum([bid[1] for bid in bids[:5]])  # 最初の5段階の買い注文の総量
    sell_pressure = sum([ask[1] for ask in asks[:5]])  # 最初の5段階の売り注文の総量

    return buy_pressure, sell_pressure

def make_trade_decision(buy_pressure, sell_pressure, amount=0.01):
    """
    買い圧力と売り圧力に基づいてトレード決定を下す
    """
    if buy_pressure > sell_pressure:
        # 買い圧力が強い場合、購入
        print("Buy signal detected")
        price = exchange.fetch_ticker(symbol)['ask']
        order = exchange.create_limit_buy_order(symbol, amount, price)
        print(f"Placed buy order at {price} for {amount} {symbol}")
    elif sell_pressure > buy_pressure:
        # 売り圧力が強い場合、売却
        print("Sell signal detected")
        price = exchange.fetch_ticker(symbol)['bid']
        order = exchange.create_limit_sell_order(symbol, amount, price)
        print(f"Placed sell order at {price} for {amount} {symbol}")
    else:
        print("No clear trade signal")

ボットのメイン実行関数

def run_bot():
    """
    オーダーフローを周期的に分析し、トレード決定を行う
    """
    while True:
        buy_pressure, sell_pressure = analyze_order_flow(symbol)
        make_trade_decision(buy_pressure, sell_pressure)
        time.sleep(10)  # 分析間隔

if __name__ == '__main__':
    run_bot()

このコードは、オーダーブックから買い注文と売り注文の流れを分析し、その圧力を比較して売買シグナルを生成します。売り圧力が買い圧力を超えた場合は売り、その逆の場合は買いを行います。

オーダーフロー分析は非常にダイナミックで、マーケットの微妙な変動に迅速に反応する必要があります。実際の取引では、この基本的なアプローチをさらに洗練させ、ボリュームや価格の変動も考慮に入れると良いでしょう。また、APIのレートリミット、オーダーのスリッページ、手数料などの実際の取引条件を考慮することが重要です。

3.ペアトレーディング

Yodaka

相関の高い2銘柄間の価格差からエントリーチャンスを見つけるタイプのbotです。

ペアトレーディングは、相関関係にある二つの銘柄の価格差が一時的に拡大したときに、一方を買いもう一方を売ることで利益を得る戦略です。以下はPythonとccxtライブラリを使用してペアトレーディング戦略を実装するコードの雛形です。この例では、BTC/USDとETH/USDのペアを取引する場合を想定しています。

必要なライブラリのインポート

import ccxt
import pandas as pd
import numpy as np
import time
from datetime import datetime

取引所の設定と初期化

exchange = ccxt.binance({
    'apiKey': 'YOUR_API_KEY',
    'secret': 'YOUR_API_SECRET',
    'enableRateLimit': True
})
pair1 = 'BTC/USDT'
pair2 = 'ETH/USDT'

データ取得と価格差の計算

def fetch_prices():
    """取引所からペアの価格を取得"""
    ticker1 = exchange.fetch_ticker(pair1)['last']
    ticker2 = exchange.fetch_ticker(pair2)['last']
    return ticker1, ticker2

def calculate_spread(ticker1, ticker2):
    """価格差(スプレッド)を計算"""
    return ticker1 - ticker2

スプレッドの統計データを取得して閾値を設定

def initialize_spread_data():
    """スプレッドの初期データを取得して統計情報を計算"""
    historical_spreads = []
    for _ in range(100):
        price1, price2 = fetch_prices()
        spread = calculate_spread(price1, price2)
        historical_spreads.append(spread)
        time.sleep(1)  # APIレートリミットに注意

    mean_spread = np.mean(historical_spreads)
    std_spread = np.std(historical_spreads)
    return mean_spread, std_spread

トレードロジック

def trade(mean_spread, std_spread):
    """トレード実行ロジック"""
    price1, price2 = fetch_prices()
    current_spread = calculate_spread(price1, price2)

    if current_spread > mean_spread + 2 * std_spread:
        print(f"{datetime.now()} - Long {pair2}, Short {pair1}")
        # ここでpair2を買い、pair1を売る注文を出す
    elif current_spread < mean_spread - 2 * std_spread:
        print(f"{datetime.now()} - Long {pair1}, Short {pair2}")
        # ここでpair1を買い、pair2を売る注文を出す
    else:
        print(f"{datetime.now()} - No trade opportunity")

def run_bot():
    mean_spread, std_spread = initialize_spread_data()
    while True:
        trade(mean_spread, std_spread)
        time.sleep(60)  # ループ間隔

メイン関数の実行

if __name__ == '__main__':
    run_bot()

このスクリプトは、ビットコインとイーサリアムの価格差が通常よりも大きくなったり小さくなったりした場合に取引を行います。取引の実行部分には、具体的な購入や売却の命令を追加する必要があります。また、スプレッドの計算を改善するために、より複雑な統計的手法や機械学習モデルを組み込むことも考慮すると良いでしょう。

ペアトレーディングのリスク管理としては、取引のスリッページ、手数料、およびその他の取引コストも考慮する必要があります。また、市場の急激な変動による影響も考慮して、適切なリスク対策を施すことが重要です。

4.高周波取引

Yodaka

最小の価格変動をとらえ、大量の注文発注でわずかな利益を積み重ねるタイプのbotです。

高周波取引(High-Frequency Trading, HFT)は非常に高速で取引を行うことに焦点を当てた戦略であり、技術的な要求が非常に高いです。特に、超低遅延のネットワーク接続と高度に最適化されたコードが必要です。しかし、ここではPythonとccxtライブラリを使って基本的なHFTのコンセプトを模倣するシンプルな例を示します。(実際の高周波取引はより複雑なインフラと専門知識を必要とします。このコードは教育的な目的に限ります。)

必要なライブラリのインポート

import ccxt
import time

取引所の設定と初期化

exchange = ccxt.binance({
    'apiKey': 'YOUR_API_KEY',
    'secret': 'YOUR_API_SECRET',
    'enableRateLimit': True
})
symbol = 'BTC/USDT'

高速トレード実行関数

def high_frequency_trading():
    """高周波取引を行う関数"""
    last_trade_price = None

    while True:
        orderbook = exchange.fetch_order_book(symbol)
        best_bid = orderbook['bids'][0][0]
        best_ask = orderbook['asks'][0][0]
        mid_price = (best_bid + best_ask) / 2

        # 前回の取引価格と比較して、わずかな価格変動を捉える
        if last_trade_price is None or abs(mid_price - last_trade_price) / mid_price > 0.0001:  # 0.01%の価格変動を検出
            if mid_price > last_trade_price:
                # 価格が上昇していたら買う
                print(f"Buying at {mid_price}")
                # exchange.create_limit_buy_order(symbol, amount, mid_price)
            elif mid_price < last_trade_price:
                # 価格が下降していたら売る
                print(f"Selling at {mid_price}")
                # exchange.create_limit_sell_order(symbol, amount, mid_price)
            last_trade_price = mid_price

        time.sleep(0.01)  # 高速でポーリング(実際のHFTでは不適切)

メイン関数の実行

if __name__ == '__main__':
    high_frequency_trading()

このコードは、注文簿から最良の売り注文と買い注文の価格を取得し、その平均価格で小さな価格変動をとらえて即座に取引を行います。このスクリプトは教育的な目的に適しており、実際の取引環境で使用するには適していません。実際のHFTでは、専用の取引インフラ、専門的な市場データフィード、極めて高速な計算能力が必要です。

また、この雛形では実際には注文を出していません。実際の注文を行うためには、コメントアウトされている create_limit_buy_ordercreate_limit_sell_order の行のコメントを解除し、適切な数量を指定する必要があります。また、実際の取引ではレート制限、取引手数料、スリッページなどの要因も重要になります。

5.マルチアセット最適化

Yodaka

ポートフォリオ全体のリスク許容度に応じて、複数の銘柄を組み合わせて売買するタイプのbotです。

マルチアセット最適化は、ポートフォリオにおける複数の資産の最適な配分を見つけることを目的とした戦略です。この手法は一般的にリスクとリターンのバランスを取るために用いられます。以下のPythonスクリプトは、平均分散最適化(Mean-Variance Optimization)を用いてポートフォリオの資産配分を決定する例を示します。この手法はハリー・マーコウィッツのポートフォリオ理論に基づいています。

必要なライブラリのインポート

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.optimize import minimize

データ取得と前処理

# ここではサンプルデータを使用します。実際にはAPIから取得した市場データを使用します。
# 資産の過去の価格データ
data = {
    'Asset1': [100, 102, 104, 103, 105],
    'Asset2': [100, 101, 100, 99, 101],
    'Asset3': [100, 99, 98, 97, 99]
}
prices = pd.DataFrame(data)

# 収益率を計算
returns = prices.pct_change().dropna()

ポートフォリオ最適化の関数

def portfolio_variance(weights, mean_returns, cov_matrix):
    """ポートフォリオの分散を計算"""
    return weights.T @ cov_matrix @ weights

def calculate_portfolio(mean_returns, cov_matrix, risk_free_rate=0.01):
    """最適なポートフォリオを計算する関数"""
    num_assets = len(mean_returns)
    args = (mean_returns, cov_matrix)
    constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})  # 合計の重みは1
    bound = (0.0, 1.0)
    bounds = tuple(bound for asset in range(num_assets))
    result = minimize(portfolio_variance, num_assets*[1./num_assets,], args=args,
                      method='SLSQP', bounds=bounds, constraints=constraints)
    return result

# 平均収益率と共分散行列を計算
mean_returns = returns.mean()
cov_matrix = returns.cov()

# 最適化を実行
opt_result = calculate_portfolio(mean_returns, cov_matrix)
print("Optimal weights:", opt_result.x)

結果の可視化

# 各資産の重みをプロット
plt.figure(figsize=(10, 6))
plt.bar(data.keys(), opt_result.x, color='green')
plt.xlabel('Assets')
plt.ylabel('Weight')
plt.title('Optimal Portfolio Weights')
plt.show()

このコードは、指定された資産群の歴史的収益データに基づいて、ポートフォリオの分散を最小化するように資産の重みを最適化します。この最適化プロセスは制約条件の下で行われ、各資産の重みが0から1の範囲に制限され、全資産の重みの合計が1になるように設定されています。

この基本的なフレームワークを使用して、リスク許容度や他の投資目標に合わせてさらにカスタマイズすることが可能です。また、実際にはAPIからリアルタイムで市場データを取得し、定期的にポートフォリオの再最適化を行うことが一般的です。

補足:ハリー・マーコウィッツのポートフォリオ理論

ハリー・マーコウィッツのポートフォリオ理論は、1952年に彼が提唱した近代ポートフォリオ理論(Modern Portfolio Theory, MPT)の基礎となる考え方です。この理論は、投資のリスクとリターンの関係を定量的に分析し、最適な資産配分を求めるためのフレームワークを提供します。ここでは、この理論の主要な要素を説明します。

1. 効率的フロンティア

マーコウィッツの理論では、異なるリスクとリターンの組み合わせから成る投資ポートフォリオの集合を考え、その中で最も効率的なポートフォリオを選ぶことを目指します。効率的フロンティアとは、与えられたリスクレベルに対して最大のリターンを提供するポートフォリオの集合を指します。

2. 分散投資

ポートフォリオのリスクを最小化するためには、資産間の相関関係を考慮して、異なる資産に分散投資することが重要です。相関が低い、または負の資産を組み合わせることで、全体のポートフォリオのリスクを減少させることができます。

3. 期待リターンとリスク

期待リターンは、資産の過去のパフォーマンスや将来の見込みから計算される投資のリターンの平均値です。リスクは、リターンの不確実性または変動性を表し、通常、標準偏差または分散で測定されます。

4. 最適ポートフォリオ

投資家が特定のリスク許容度を持っている場合、効率的フロンティア上でそのリスクに対応する最適なポートフォリオを選択します。最適ポートフォリオは、投資家のリスク許容度とリターン目標に最も適合する資産配分を提供します。

5. シャープ比率

シャープ比率は、リスクを考慮したリターンの尺度で、ポートフォリオのパフォーマンスを評価するために使用されます。この比率は、ポートフォリオのリターンから無リスクリターン(例えば、国債のリターン)を差し引いた値をリスク(標準偏差)で割ったものです。

6. キャピタル・アセット・プライシング・モデル(CAPM)

マーコウィッツの理論は後にCAPMの基礎となり、個々の証券やポートフォリオの期待リターンを評価するための重要なモデルへと発展しました。CAPMは、市場リスク(ベータ)と無リスクリターンを用いて、証券の期待リターンを計算します。

ハリー・マーコウィッツのポートフォリオ理論は、投資におけるリスク管理とリターン最大化のための強力なツールとして、現在も広く使用されています。この理論により、投資家はより情報に基づいた投資決定を行うことが可能になります。

まとめ

今回も5種類の雛形を紹介しました。

これらはあくまで雛形なので、そのまま実行しても収益を出すことは難しいです。

そのため、これらを基本として組み合わせを考えたり、一つ一つの精度を高めたりすることが重要です。

Yodaka

例えば、私は高頻度取引を行うbotの開発に力を注いでいます。これならできそうだな手をつけてみると面白いかもなどと感じたものから触ってみることを大事にしています。(そうしていくうちに最終的には色々なタイプのbotを触ることになるので)

今後もこの調子で仮想通貨botの開発状況をまとめていきます。

-Bot, トレードロジック