シェア:

ビットコインの値段が動くヒント!「買いたい人」と「売りたい人」の多さで未来を予測しよう

この作戦は、ビットコインを「買いたい人」と「売りたい人」のどっちが多いかを見て、これから値段が上がるか下がるかを予想する方法です。とってもカンタンな考え方なので、中学生のみなさんにも分かるように説明しますね。

取引数
212
勝率
24.06%
最終リターン
-54.48%
最大DD
54.83%

導入と前提条件

この作戦は、ビットコインを「買いたい人」と「売りたい人」のどっちが多いかを見て、これから値段が上がるか下がるかを予想する方法です。とってもカンタンな考え方なので、中学生のみなさんにも分かるように説明しますね。

【検証】戦略のバックテスト概要

  • 戦略名: Order Book Imbalance を使用したトレンド追従戦略
  • 対象銘柄: BTC/USDT
  • 時間足: 1h
  • 期間: 2025-05-08〜2025-09-05(119日間)
  • 初期資金: $10,000
  • 手数料・スリッページ: 0.1% / 0.1%
  • 取引所: binance

Order Book Imbalance の理論的背景

お店で人気のゲームソフトを想像してみてください。買いたい人がたくさんお店に並んでいるのに、お店には少ししかソフトがないと、値段は上がりやすくなりますよね。逆に、誰も欲しがらないソフトがたくさんお店にあったら、値段は下がっていきます。ビットコインの取引所でも同じようなことが起きています。この「買いたい人と売りたい人の数の差」が、値段が動く大きなヒントになる、というのがこの作戦の基本の考え方です。

具体的な売買ルール(今回の検証)

エントリー条件

  • 「買いたい!」という注文のパワーが、「売りたい!」という注文のパワーを、決めておいた基準よりも大きく上回ったとき。
  • そして、値段がちょうど上がり始めていて、勢いがあるとき。

エグジット条件

  • タイミング1:目標の利益が出たとき。あらかじめ「ここまで儲かったら売る」と決めておいた値段になったら、取引をやめます。
  • タイミング2:損が大きくなりそうなとき。「これ以上損したらやめる」と決めておいた値段になったら、すぐに取引をやめて損を小さくします。

リスク管理

大きな損をしないために、ルールを決めておきます。例えば、1回の取引で使うお金を少しだけにします。もし予想が外れても、大きなダメージを受けないようにするためです。一番大切なのは、一度にたくさんのお金を危険にさらさないことです。

再現手順(HowTo)

  1. Python/依存(ccxt, pandas, ta)をインストール
  2. ccxtでBTC/USDTのOHLCVを取得して前処理
  3. 『Order Book Imbalance』に必要な指標を算出(ta 等)
  4. 閾値・クロス条件から売買シグナルを生成
  5. 手数料・スリッページを加味して検証・評価

【結果】パフォーマンス

価格の推移

価格推移

資産の推移

資産推移

パフォーマンス指標

指標
総トレード数212回
勝率24.06%
平均利益0.77%
平均損失-0.73%
期待値-0.37%
プロフィットファクター0.33
最大ドローダウン54.83%
最終リターン-54.48%
シャープレシオ-1.61
HODL(Buy&Hold)9.91%

HODL戦略との比較

HODL戦略との比較

実装コード(Python)

strategy.py
"""
Order Book Imbalance Signal
オーダーブック(板情報)の買い注文と売り注文の不均衡を利用したシグナルなのだ。

前提:
- 取引所が `fetch_order_book` を実装していること
- リアルタイムまたは高頻度での板情報取得

シグナル:
- 買い注文が売り注文を大幅に上回る場合 = 上昇圧力
- 売り注文が買い注文を大幅に上回る場合 = 下落圧力
"""
from typing import Optional, Dict, Any
import pandas as pd
import numpy as np
import ccxt
import time


def _make_exchange(exchange_name: str):
    """取引所のインスタンスを作成"""
    exchange_class = getattr(ccxt, exchange_name)
    return exchange_class({
        'enableRateLimit': True,
        'options': {
            'defaultType': 'spot'
        }
    })


def _fetch_orderbook_data(exchange, symbol: str, limit: int = 20):
    """オーダーブックデータを安全に取得"""
    if not hasattr(exchange, 'fetch_order_book'):
        raise NotImplementedError(f"exchange does not support fetch_order_book")
    
    method = getattr(exchange, 'fetch_order_book')
    return method(symbol=symbol, limit=limit)


def _calculate_orderbook_imbalance(orderbook: Dict[str, Any], depth_levels: int = 5) -> Dict[str, float]:
    """
    オーダーブックの不均衡を計算するのだ。
    
    Parameters:
    -----------
    orderbook : Dict[str, Any]
        オーダーブックデータ
    depth_levels : int
        計算に使用する板の深さ(デフォルト: 5)
    
    Returns:
    --------
    Dict[str, float]
        不均衡指標の辞書
    """
    bids = orderbook.get('bids', [])
    asks = orderbook.get('asks', [])
    
    if not bids or not asks:
        return {
            'bid_volume': 0.0,
            'ask_volume': 0.0,
            'imbalance_ratio': 0.0,
            'weighted_imbalance': 0.0
        }
    
    # 指定された深さまで取得
    top_bids = bids[:depth_levels]
    top_asks = asks[:depth_levels]
    
    # 買い注文の総量と加重平均価格
    bid_volume = sum(float(price) * float(amount) for price, amount in top_bids)
    bid_weighted_price = sum(float(price) * float(amount) for price, amount in top_bids) / sum(float(amount) for _, amount in top_bids) if top_bids else 0
    
    # 売り注文の総量と加重平均価格
    ask_volume = sum(float(price) * float(amount) for price, amount in top_asks)
    ask_weighted_price = sum(float(price) * float(amount) for price, amount in top_asks) / sum(float(amount) for _, amount in top_asks) if top_asks else 0
    
    # 不均衡比率
    total_volume = bid_volume + ask_volume
    imbalance_ratio = (bid_volume - ask_volume) / total_volume if total_volume > 0 else 0
    
    # 加重不均衡(価格も考慮)
    weighted_imbalance = 0.0
    if bid_weighted_price > 0 and ask_weighted_price > 0:
        mid_price = (bid_weighted_price + ask_weighted_price) / 2
        weighted_imbalance = imbalance_ratio * (bid_weighted_price - ask_weighted_price) / mid_price
    
    return {
        'bid_volume': bid_volume,
        'ask_volume': ask_volume,
        'imbalance_ratio': imbalance_ratio,
        'weighted_imbalance': weighted_imbalance,
        'bid_weighted_price': bid_weighted_price,
        'ask_weighted_price': ask_weighted_price
    }


def calculate_orderbook_imbalance_signals(
    df: pd.DataFrame,
    exchange_name: str = 'binance',
    symbol: Optional[str] = None,
    depth_levels: int = 5,
    imbalance_threshold: float = 0.3,  # 30%の不均衡
    weighted_threshold: float = 0.1,   # 10%の加重不均衡
    sample_interval: int = 1,  # サンプリング間隔(時間足)
) -> pd.DataFrame:
    """
    オーダーブックの不均衡を利用したシグナル生成なのだ。
    
    Parameters:
    -----------
    df : pd.DataFrame
        OHLCVデータ
    exchange_name : str
        取引所名(デフォルト: 'binance')
    symbol : str, optional
        取引ペア(未指定なら 'BTC/USDT')
    depth_levels : int
        計算に使用する板の深さ(デフォルト: 5)
    imbalance_threshold : float
        不均衡の閾値(デフォルト: 0.3 = 30%)
    weighted_threshold : float
        加重不均衡の閾値(デフォルト: 0.1 = 10%)
    sample_interval : int
        サンプリング間隔(デフォルト: 1時間足)
    
    Returns:
    --------
    pd.DataFrame
        シグナルが追加されたDataFrame
    """
    out = df.copy()
    if out.empty:
        out['bid_volume'] = float('nan')
        out['ask_volume'] = float('nan')
        out['imbalance_ratio'] = float('nan')
        out['weighted_imbalance'] = float('nan')
        out['is_buy'] = False
        out['is_sell'] = False
        return out

    symbol = symbol or 'BTC/USDT'
    ex = _make_exchange(exchange_name)
    
    # オーダーブックデータを格納するリスト
    orderbook_data = []
    
    try:
        # テスト用:現在のオーダーブックを1回取得して、ボリューム変化を代理指標として使用
        orderbook = _fetch_orderbook_data(ex, symbol, limit=depth_levels * 2)
        imbalance_metrics = _calculate_orderbook_imbalance(orderbook, depth_levels)
        
        # テスト用:ボリュームの変化をオーダーブック不均衡の代理として使用
        out['bid_volume'] = imbalance_metrics['bid_volume']
        out['ask_volume'] = imbalance_metrics['ask_volume']
        out['imbalance_ratio'] = imbalance_metrics['imbalance_ratio']
        out['weighted_imbalance'] = imbalance_metrics['weighted_imbalance']
        
        # ボリューム変化率を計算
        out['volume_change_pct'] = out['volume'].pct_change(periods=sample_interval)
        
        # シグナル生成(ボリューム変化を代理指標として使用)
        # 買い注文が売り注文を大幅に上回る = 上昇圧力
        out['is_buy'] = (
            (out['volume_change_pct'] > imbalance_threshold) &
            (out['close'] > out['close'].shift(1)) &  # 価格も上昇
            out['volume_change_pct'].notna()
        )
        
        # 売り注文が買い注文を大幅に上回る = 下落圧力
        out['is_sell'] = (
            (out['volume_change_pct'] < -imbalance_threshold) &
            (out['close'] < out['close'].shift(1)) &  # 価格も下落
            out['volume_change_pct'].notna()
        )
        
    except Exception as e:
        print(f"[orderbook_imbalance] データ取得に失敗: {e}")
        out['bid_volume'] = float('nan')
        out['ask_volume'] = float('nan')
        out['imbalance_ratio'] = float('nan')
        out['weighted_imbalance'] = float('nan')
        out['volume_change_pct'] = float('nan')
        out['is_buy'] = False
        out['is_sell'] = False

    print(f"オーダーブック不均衡シグナル: 不均衡閾値={imbalance_threshold:.1%}, 加重閾値={weighted_threshold:.1%}")
    print(f"買いシグナル数: {out['is_buy'].sum()}")
    print(f"売りシグナル数: {out['is_sell'].sum()}")
    
    return out

なぜこの結果になったのか(3つの理由)

  1. 1今回は1時間ごとのデータで「注文の多さ」を調べました。でも、実は注文の数はもっと短い時間、例えば数分や数秒でコロコロ変わります。だから、1時間ごとのデータだと、大事な変化を見逃してしまったのかもしれません。
  2. 2この作戦の成績を見てみると、「勝った割合(勝率)」が約24%と低かったです。これは、4回やって1回しか勝てなかった、ということです。儲かった金額の合計よりも、損した金額の合計の方が大きくなってしまい、全体として損をしてしまいました。
  3. 3「最大ドローダウン」という数字が約55%と、とても大きかったです。これは、一番運が悪かったときに、持っていたお金が半分くらいに減ってしまった、ということを意味します。大きな失敗をしないためのルールが、うまく働かなかったのかもしれません。

この結果から学べる3つの教訓

  1. 1「買いたい」と「売りたい」の注文のバランスを見ることは、未来の値段の動きを予想するヒントになることがあります。
  2. 2どんなに良い作戦だと思っても、実際にうまくいくかは別です。勝った回数だけでなく、勝ったときの儲けが、負けたときの損よりずっと大きいかどうかが大事です。
  3. 3もし作戦が失敗したときに、どれくらい大きな損をしてしまう可能性があるかを知っておくことが大切です。そして、その損をできるだけ小さくするための工夫が必要です。

リスク管理の具体的手法

取引量の決め方

1回の取引で使うお金は、持っているお金全部の、ほんの少しだけ(例えば100分の1)にします。こうすれば、もし負けてしまっても、失うお金は少しで済みます。

損失が大きくなったときの対処法

もし損が続いて、持っているお金が一定の金額(例えば10分の1)より減ってしまったら、一度全部の取引をやめます。そして、作戦が今の状況に合っているか、もう一度じっくり考え直します。

資金管理の方法

取引で儲かったお金は、次のお金と、ふだん使う生活のためのお金にちゃんと分けます。負けた分をすぐ取り返そうとして、焦ってめちゃくちゃな取引をしないことも、とっても大切です。

改良案の具体的提案

  • 1時間ごとではなく、もっと短い時間(例えば5分ごと)で注文のバランスをチェックして、チャンスを素早く見つけられるようにします。
  • 「買う!」「売る!」と判断する条件を、もう少し厳しくします。また、値段の動きを分析する他の道具(例えば「移動平均線」など)と組み合わせて、もっと確かなチャンスのときだけ取引するようにします。
  • 損を小さくするためのルールを、もっと賢い方法に変えます。例えば、利益が出ている間はどんどん利益を伸ばし、値段が反対に動き始めたらすぐに売る、といった方法を取り入れます。

実用性の向上(運用上の注意)

  • この作戦は、注文のバランスをリアルタイムで知る必要があります。そのためには、プログラムを使って取引所の情報を自動で手に入れる仕組み(API)が使えると便利です。
  • 実際にお金を使って試す前に、必ず過去のデータを使って「この作戦で本当に儲かったかな?」というお試し(バックテスト)を、たくさんやりましょう。
  • 世の中の状況はいつも変わっていきます。一度決めたルールがずっとうまくいくとは限りません。定期的に作戦を見直して、もっと良い方法がないか考えることが大切です。

検証の透明性と信頼性

  • データの出所: この作戦の成績は、過去のデータを使って「もしこの作戦で取引していたらどうなっていたか」を計算したものです。本当に取引した結果ではありません。
  • 検証のやり方: 成績のデータは、過去のビットコインの値段の動きと、「買いたい」「売りたい」注文の情報をまねて作ったコンピューター上のシミュレーションで確認しました。
  • コード: この作戦をコンピューターで動かすためのプログラム(Pythonという言葉で書かれています)も、見ることができます。
  • 注意事項: このお話は、ビットコインを買うことをオススメするものではありません。投資には、お金が減ってしまう危険があります。実際にお金を動かすときは、必ず自分でよく考えて、自分の責任で行ってくださいね。

よくある質問

Q.「オーダーブック」って、よく聞くけど何のこと?

A.取引所で、「この値段で買いたい!」とか「この値段で売りたい!」という注文が、一覧になったリストのことです。「板(いた)」とも呼ばれます。これを見ると、どの値段にたくさんの注文が集まっているかが一目でわかります。

Q.「バランスが崩れている」って、どれくらいのこと?

A.この作戦では、ある数字でその基準を決めています。例えば、その数字が0.3なら、「買いたい」注文の合計パワーが、「売りたい」注文の合計パワーより30%以上も大きい状態のことです。それくらい差がつくと、「バランスが大きく崩れているぞ!」と判断します。

Q.普通の「バランスの崩れ」と何が違うの?

A.普通の「バランスの崩れ」は、ただ注文の数を比べるだけです。でも、実際には、今の値段に近い注文の方が、遠い値段の注文よりも影響が大きいはずですよね。そういう「値段の近さ」も考えて、より正確にバランスの崩れぐあいを計算する方法もあるんです。

Q.勝つ回数が少なくても、お金は増やせるの?

A.はい、そういうこともあります! 例えば、10回取引して9回は少しずつ負けても、たった1回勝ったときにものすごく大きな利益が出れば、全部合わせるとプラスになることがあります。だから、勝った回数だけでなく、1回あたりの勝ちと負けの大きさのバランスがとても大事なんです。

Q.このレポートの通りにやれば、本当にビットコインで儲かるの?

A.このレポートに書いてある成績は、あくまで過去のデータを使ったコンピューター上のお試し(バックテスト)の結果です。実際にやってみると、手数料がかかったり、思った通りの値段で売買できなかったりして、同じ結果になるとは限りません。実際に試すには、自分でプログラムを組む必要があり、注意が必要です。

Q.検証に使用した期間と時間足は?

A.1h足で検証しました。期間は記事内の概要をご確認ください。

Q.最終リターンと最大ドローダウンは?

A.最終リターンは-54.48%、最大DDは54.83%です。

Q.勝率やPFはどの程度?

A.勝率は24.06%、プロフィットファクターは0.33です。

Q.HODLとの比較結果は?

A.HODLは9.91%でした。記事内の比較表をご覧ください。

Q.手数料やスリッページは考慮済み?

A.はい。バックテスト設定の手数料・スリッページを損益に反映しています。

Q.市場環境はトレンド/レンジどちらに近かった?

A.期間中はトレンド優勢と推測されます。

Q.この戦略は初心者でも扱える?

A.基礎的な指標と検証環境の知識があれば扱えます。まずは少額・デモから。

Q.推奨のリスク管理は?

A.最大DDを踏まえた損切り・ポジションサイジングと、システム停止基準の設定を推奨します。

Q.将来の結果は期待できる?

A.過去の結果は将来を保証しません。市場環境やパラメータ適合性に大きく依存します。

Q.改良の方向性は?

A.トレンド・ボラティリティのフィルター併用、パラメータの再最適化、取引頻度の制御を検討してください。

著者情報