バックテストの失敗の多くは、戦略そのものではなく、最初のデータ段階ですでに歪みが生じていることに原因があります。

暗号資産市場ではこの問題がさらに顕著になります。価格は24時間動き続け、流動性は急速に変化し、約定構造は非常に断片化されています。不完全または不整合なヒストリカルデータを使うと、実際には歪んだ市場環境で戦略を検証していることになります。

バックテストの本質は単なる利益検証ではなく、より根本的には**「戦略が過去の市場構造の中で一貫した振る舞いをするかどうか」**を確認することです。

1. バックテストは利益シミュレーションではなく行動の再構築

多くの人はバックテストを「過去の利益検証ツール」と考えますが、システム設計の観点ではそれはマーケットリプレイシステムに近いものです。

重要なのは収益予測ではなく、以下の3点です:

  • 各時点で実際に約定可能な価格帯
  • 戦略がその環境でどのように注文を出すか
  • 約定の有無とスリッページの分布

特にCryptocurrency Marketでは、市場構造の変化が激しいため、ある局面で有効な戦略が別の局面では完全に機能しないことがあります。

2. ヒストリカルデータは価格列ではなくイベント列

OHLCのローソク足だけを使うと、多くの情報が失われます。

より現実的な市場表現は以下を含みます:

  • ティックデータ(価格 / 出来高 / タイムスタンプ)
  • 高頻度足(1秒または100ms)
  • オーダーブック情報(マーケットメイク戦略など)

ミクロ構造の観点では、市場はローソク足の連続ではなく、取引イベントのストリームです。

例えば同じ1分足の上昇でも:

  • 徐々に上昇し出来高が伴うケース
  • 10秒で急騰しその後横ばいになるケース

見た目は同じでも戦略の結果は大きく異なります。

3. データ取得がバックテストの上限を決める

暗号資産データは多様ですが、重要なのは「量」ではありません。

  • 連続性
  • タイムスタンプ整合性
  • 約定構造の有無
  • マルチマーケットの正規化

実務では統一されたデータインターフェースを使うことが多く、例えばAllTickのヒストリカルティックやKラインデータを利用することで、複数市場を同一時間軸で扱うことが可能になります。

重要なのはデータ量ではなく構造的一貫性です。

4. バックテストシステムの基本構成

一般的なバックテストは以下の4層で構成されます:

4.1. データ層

  • ティックデータ
  • ローソク足
  • オーダーブック

4.2. 戦略層

  • マーケットメイク
  • トレンド判断
  • 平均回帰

4.3. 約定シミュレーション層

  • 約定/非約定判定
  • スリッページ
  • 手数料

4.4. ポートフォリオ層

  • ポジション管理
  • 損益管理
  • リスク管理

全体は以下のループになります:

データ → 戦略 → 約定 → ポートフォリオ

5. シンプルなティックバックテスト例(Python)

import pandas as pd

class SimpleBacktest:
    def __init__(self, data, fee=0.0005):
        self.data = data
        self.fee = fee
        self.position = 0
        self.cash = 10000
        self.entry_price = 0

    def signal(self, row):
        if row["price"] > row["ma"]:
            return 1
        elif row["price"] < row["ma"]:
            return -1
        return 0

    def run(self):
        for _, row in self.data.iterrows():
            sig = self.signal(row)
            price = row["price"]

            if sig == 1 and self.position == 0:
                self.position = 1
                self.entry_price = price
                self.cash -= price * self.fee

            elif sig == -1 and self.position == 1:
                pnl = price - self.entry_price
                self.cash += pnl
                self.cash -= price * self.fee
                self.position = 0

        return self.cash

この構造には以下が含まれています:

  • シグナル生成
  • ポジション管理
  • 約定コスト
  • 資金更新

6. よくある問題点

6.1. スリッページは定数ではない

実際の市場では:

  • 流動性低下 → スリッページ増加
  • ボラティリティ上昇 → 約定不安定

6.2. 時間整合性の重要性

  • ティック遅延
  • タイムスタンプの乱れ
  • 取引所間の時間差

価格が正しくても時間がズレると戦略は崩れます。

6.3. 約定シミュレーションの重要性

理想約定では利益が出ても:

  • 部分約定
  • キュー優先順位
  • 遅延

を加えると結果は大きく変わります。

7. 単一資産からマルチアセットへ

BTCやETH単体ではなく複数資産になると:

  • BTCとETHのラグ
  • 暗号資産と伝統資産の連動
  • ボラティリティの伝播

バックテストは単なる戦略評価から、市場構造モデルの検証へ変わります。

8. 重要なのは損益曲線ではない

見るべきは:

  • ドローダウンの安定性
  • 市場局面ごとの差異
  • ボラティリティ依存性
  • 極端相場依存度

安定した戦略は必ずしも最も利益が大きい戦略ではありませんが、構造的に一貫しています。

9. ヒストリカルデータの本質

バックテストの目的は過去の利益を再現することではなく:

  • どの局面で崩れるか
  • リスクがどこに集中するか
  • 隠れた依存関係の発見

ヒストリカルデータを価格記録ではなく市場行動の履歴として扱うことで、バックテストは性能評価から構造理解へと変わります。