ML Documentation

LSTMによる取引方向予測と最新価格予測手法

📊 概要

本ドキュメントでは、DavidCicoのGitHubリポジトリ「Forecasting-direction-of-trade-an-example-with-LSTM-neural-network」の手法を日本語で解説し、2024年の最新研究成果と組み合わせて、効果的な価格予測手法を包括的にまとめます。

🔍 DavidCicoの手法:LSTMによる取引方向予測

プロジェクト概要

特徴量の計算

def compute_features(orderbook_data, trade_data):
    """オーダーブックから特徴量を計算"""
    features = {}

    # 1. Volume Order Imbalance(ボリューム注文不均衡)
    bid_volume = orderbook_data['bid_volume'].sum()
    ask_volume = orderbook_data['ask_volume'].sum()
    features['volume_imbalance'] = (bid_volume - ask_volume) / (bid_volume + ask_volume)

    # 2. Bid-Ask Spread(ビッド・アスク・スプレッド)
    features['spread'] = orderbook_data['ask_price'][0] - orderbook_data['bid_price'][0]
    features['spread_pct'] = features['spread'] / orderbook_data['mid_price']

    # 3. Mid-price basis(中値ベース)
    features['mid_price'] = (orderbook_data['ask_price'][0] + orderbook_data['bid_price'][0]) / 2
    features['mid_price_change'] = features['mid_price'].diff()

    return features

LSTMアーキテクチャ

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout

def build_lstm_model(input_shape, lookback_period=50):
    """取引方向予測のためのLSTMモデル構築"""
    model = Sequential([
        LSTM(50, return_sequences=True, input_shape=(lookback_period, input_shape)),
        Dropout(0.2),
        LSTM(50, return_sequences=True),
        Dropout(0.2),
        LSTM(50),
        Dropout(0.2),
        Dense(1, activation='sigmoid')  # 二値分類:上昇/下降
    ])

    model.compile(
        optimizer='adam',
        loss='binary_crossentropy',
        metrics=['accuracy']
    )

    return model

主要な実装ポイント

  1. データ前処理
    - 買い注文と売り注文の不均衡を捉える特徴量設計
    - 時系列データの正規化とウィンドウ化

  2. モデル評価
    - 線形回帰との性能比較
    - 異なるルックバック期間での検証

  3. 限界と注意点
    - LSTMの可能性を示すデモンストレーション
    - 実際の取引戦略としては追加の検証が必要

🚀 2024年最新の価格予測手法

1. Transformer モデルの台頭

Predictive Modeling of Stock Prices Using Transformer Model (2024)

import torch
from torch import nn

class StockTransformer(nn.Module):
    def __init__(self, feature_dim, d_model=512, nhead=8, num_layers=6):
        super().__init__()

        # 時間エンコーディング(Time2Vec)
        self.time_encoding = Time2Vec(1, d_model)

        # 特徴量埋め込み
        self.feature_embedding = nn.Linear(feature_dim, d_model)

        # Transformerエンコーダ
        encoder_layer = nn.TransformerEncoderLayer(
            d_model=d_model,
            nhead=nhead,
            dim_feedforward=2048,
            dropout=0.1
        )
        self.transformer = nn.TransformerEncoder(encoder_layer, num_layers)

        # 出力層
        self.output_layer = nn.Linear(d_model, 1)

    def forward(self, features, timestamps):
        # 時間エンコーディング
        time_embed = self.time_encoding(timestamps)

        # 特徴量埋め込み
        feature_embed = self.feature_embedding(features)

        # 結合
        x = feature_embed + time_embed

        # Transformer処理
        x = self.transformer(x)

        # 予測
        return self.output_layer(x)

成果: LSTMやProphetモデルと比較して優れた性能を実証

2. DeepLOB アーキテクチャ

オーダーブックデータに特化した深層学習モデル。

class DeepLOB(nn.Module):
    """CNN-LSTMハイブリッドモデル for LOB分析"""

    def __init__(self, num_features=40):
        super().__init__()

        # CNN層:空間的特徴抽出
        self.conv1 = nn.Conv2d(1, 32, kernel_size=(1, 2), stride=(1, 2))
        self.conv2 = nn.Conv2d(32, 32, kernel_size=(4, 1))
        self.conv3 = nn.Conv2d(32, 32, kernel_size=(4, 1))

        # Inception Module
        self.inception = InceptionModule(32, 64)

        # LSTM層:時系列パターン学習
        self.lstm = nn.LSTM(
            input_size=64 * num_features // 2,
            hidden_size=64,
            num_layers=1,
            batch_first=True
        )

        # 出力層
        self.fc = nn.Linear(64, 3)  # 3クラス分類:上昇/横ばい/下降

    def forward(self, x):
        # CNN特徴抽出
        x = torch.relu(self.conv1(x))
        x = torch.relu(self.conv2(x))
        x = torch.relu(self.conv3(x))

        # Inception
        x = self.inception(x)

        # Reshape for LSTM
        x = x.permute(0, 2, 1, 3)
        x = x.reshape(x.shape[0], x.shape[1], -1)

        # LSTM処理
        x, _ = self.lstm(x)

        # 最終予測
        return self.fc(x[:, -1, :])

3. 高度なオーダーブック特徴量

2024年の研究で有効性が確認された特徴量:

class OrderBookFeatures:
    """最新研究に基づくオーダーブック特徴量"""

    @staticmethod
    def stationary_features(orderbook):
        """定常性を持つ特徴量の構築"""
        features = {}

        # 1. Order Flow Imbalance(注文フロー不均衡)
        bid_volume_change = orderbook['bid_volume'].diff()
        ask_volume_change = orderbook['ask_volume'].diff()
        features['order_flow_imbalance'] = (
            bid_volume_change - ask_volume_change
        ) / (bid_volume_change.abs() + ask_volume_change.abs() + 1e-8)

        # 2. Relative Spread(相対スプレッド)
        mid_price = (orderbook['bid_price'] + orderbook['ask_price']) / 2
        features['relative_spread'] = (
            orderbook['ask_price'] - orderbook['bid_price']
        ) / mid_price

        # 3. Price Level Imbalance(価格レベル不均衡)
        for level in range(5):  # Top 5 levels
            bid_vol = orderbook[f'bid_volume_{level}']
            ask_vol = orderbook[f'ask_volume_{level}']
            features[f'level_{level}_imbalance'] = (
                bid_vol - ask_vol
            ) / (bid_vol + ask_vol + 1e-8)

        # 4. Weighted Mid Price(加重中値)
        total_bid_size = orderbook['bid_volume_0']
        total_ask_size = orderbook['ask_volume_0']
        features['weighted_mid_price'] = (
            orderbook['bid_price_0'] * total_ask_size + 
            orderbook['ask_price_0'] * total_bid_size
        ) / (total_bid_size + total_ask_size + 1e-8)

        return features

4. ハイブリッドモデル:PSO-LSTM

2024年に提案された粒子群最適化(PSO)とLSTMの組み合わせ。

import numpy as np
from pyswarm import pso

class PSO_LSTM:
    """粒子群最適化によるLSTMハイパーパラメータ調整"""

    def __init__(self, input_shape):
        self.input_shape = input_shape
        self.best_params = None

    def objective_function(self, params):
        """最適化対象の目的関数"""
        # パラメータの解釈
        units = int(params[0])
        dropout_rate = params[1]
        learning_rate = params[2]

        # モデル構築
        model = self.build_lstm(units, dropout_rate, learning_rate)

        # 訓練と評価
        history = model.fit(
            self.X_train, self.y_train,
            validation_data=(self.X_val, self.y_val),
            epochs=50,
            batch_size=32,
            verbose=0
        )

        # 検証損失を返す
        return min(history.history['val_loss'])

    def optimize(self):
        """PSOによる最適化実行"""
        # パラメータの範囲
        lb = [10, 0.1, 0.0001]  # 下限:units, dropout, lr
        ub = [200, 0.5, 0.01]   # 上限

        # PSO実行
        best_params, best_loss = pso(
            self.objective_function,
            lb, ub,
            swarmsize=20,
            maxiter=50
        )

        self.best_params = best_params
        return best_params, best_loss

5. Multi-Feature Integration(マルチ特徴量統合)

VMD-TMFG-LSTMモデル:変分モード分解とトポロジカル特徴の統合。

class MultiFeatureLSTM:
    """複数の特徴量ソースを統合するLSTM"""

    def __init__(self):
        self.vmd_decomposer = VMD()  # 変分モード分解
        self.tmfg_extractor = TMFG()  # トポロジカル特徴抽出

    def extract_features(self, price_data, orderbook_data, news_sentiment):
        """マルチソース特徴量抽出"""
        features = {}

        # 1. 価格分解特徴
        modes = self.vmd_decomposer.decompose(price_data)
        features['vmd_features'] = modes

        # 2. トポロジカル市場構造
        market_graph = self.tmfg_extractor.build_graph(orderbook_data)
        features['topology_features'] = market_graph.get_features()

        # 3. センチメント統合
        features['sentiment_scores'] = news_sentiment

        # 4. テクニカル指標
        features['technical'] = self.compute_technical_indicators(price_data)

        return self.combine_features(features)

    def build_model(self, feature_dim):
        """統合モデルの構築"""
        inputs = []
        embeddings = []

        # 各特徴量タイプごとの埋め込み
        for feature_type in ['vmd', 'topology', 'sentiment', 'technical']:
            input_layer = Input(shape=(None, feature_dim[feature_type]))
            embedding = LSTM(64, return_sequences=True)(input_layer)
            inputs.append(input_layer)
            embeddings.append(embedding)

        # 特徴量の結合
        combined = Concatenate()(embeddings)

        # 最終LSTM層
        lstm_out = LSTM(128)(combined)
        output = Dense(1, activation='linear')(lstm_out)

        model = Model(inputs=inputs, outputs=output)
        return model

📈 実装のベストプラクティス(2024年版)

1. データ前処理の重要性

def preprocess_orderbook_data(orderbook_df):
    """2024年のベストプラクティスに基づく前処理"""

    # 1. 定常性の確保
    orderbook_df['price_returns'] = orderbook_df['mid_price'].pct_change()

    # 2. 外れ値の処理
    for col in orderbook_df.columns:
        if 'volume' in col or 'price' in col:
            # Winsorization(上下1%をクリップ)
            lower = orderbook_df[col].quantile(0.01)
            upper = orderbook_df[col].quantile(0.99)
            orderbook_df[col] = orderbook_df[col].clip(lower, upper)

    # 3. 特徴量スケーリング
    from sklearn.preprocessing import RobustScaler
    scaler = RobustScaler()

    numeric_cols = orderbook_df.select_dtypes(include=[np.number]).columns
    orderbook_df[numeric_cols] = scaler.fit_transform(orderbook_df[numeric_cols])

    # 4. 時間特徴の追加
    orderbook_df['hour'] = orderbook_df.index.hour
    orderbook_df['minute'] = orderbook_df.index.minute
    orderbook_df['day_of_week'] = orderbook_df.index.dayofweek

    return orderbook_df

2. モデル評価とバックテスト

class ModelEvaluator:
    """包括的なモデル評価フレームワーク"""

    @staticmethod
    def walk_forward_validation(model, data, window_size=1000, step_size=100):
        """ウォークフォワード検証"""
        results = []

        for i in range(window_size, len(data) - step_size, step_size):
            # 訓練データ
            train_data = data[i-window_size:i]

            # テストデータ
            test_data = data[i:i+step_size]

            # モデル訓練
            model.fit(train_data)

            # 予測と評価
            predictions = model.predict(test_data)
            metrics = calculate_metrics(test_data['target'], predictions)

            results.append({
                'period': i,
                'metrics': metrics,
                'predictions': predictions
            })

        return results

    @staticmethod
    def calculate_metrics(y_true, y_pred):
        """取引特化メトリクス"""
        metrics = {}

        # 方向予測精度
        direction_true = np.sign(y_true)
        direction_pred = np.sign(y_pred)
        metrics['directional_accuracy'] = np.mean(direction_true == direction_pred)

        # Sharpe比
        returns = y_pred * y_true  # 予測に基づく収益
        metrics['sharpe_ratio'] = np.mean(returns) / (np.std(returns) + 1e-8) * np.sqrt(252)

        # 最大ドローダウン
        cumulative_returns = np.cumprod(1 + returns)
        running_max = np.maximum.accumulate(cumulative_returns)
        drawdown = (cumulative_returns - running_max) / running_max
        metrics['max_drawdown'] = np.min(drawdown)

        return metrics

3. リアルタイム予測パイプライン

class RealTimePredictionPipeline:
    """本番環境向けリアルタイム予測システム"""

    def __init__(self, model, feature_extractor):
        self.model = model
        self.feature_extractor = feature_extractor
        self.buffer = deque(maxlen=100)  # 最新100ティックを保持

    async def process_tick(self, tick_data):
        """新しいティックデータの処理"""
        # バッファに追加
        self.buffer.append(tick_data)

        # 特徴量抽出
        if len(self.buffer) >= 50:  # 最小必要データ
            features = self.feature_extractor.extract(list(self.buffer))

            # 予測
            prediction = await self.predict_async(features)

            # 取引シグナル生成
            signal = self.generate_trading_signal(prediction)

            return signal

        return None

    async def predict_async(self, features):
        """非同期予測"""
        # モデル推論を別スレッドで実行
        loop = asyncio.get_event_loop()
        prediction = await loop.run_in_executor(
            None, 
            self.model.predict, 
            features
        )
        return prediction

    def generate_trading_signal(self, prediction):
        """予測から取引シグナルへの変換"""
        signal = {
            'timestamp': datetime.now(),
            'prediction': prediction,
            'action': None,
            'confidence': None
        }

        # 閾値ベースの判断
        if prediction > 0.002:  # 0.2%以上の上昇予測
            signal['action'] = 'BUY'
            signal['confidence'] = min(prediction * 100, 100)
        elif prediction < -0.002:  # 0.2%以上の下降予測
            signal['action'] = 'SELL'
            signal['confidence'] = min(abs(prediction) * 100, 100)
        else:
            signal['action'] = 'HOLD'
            signal['confidence'] = 0

        return signal

🎯 統合アプローチ:最良の実践

エンサンブルモデル

class EnsemblePredictor:
    """複数モデルの統合による頑健な予測"""

    def __init__(self):
        self.models = {
            'lstm': LSTMModel(),
            'transformer': TransformerModel(),
            'deeplob': DeepLOBModel(),
            'pso_lstm': PSO_LSTM()
        }
        self.weights = None

    def train_ensemble(self, train_data, val_data):
        """各モデルの訓練と重み最適化"""
        predictions = {}

        # 各モデルを訓練
        for name, model in self.models.items():
            model.fit(train_data)
            predictions[name] = model.predict(val_data)

        # 最適な重みを見つける
        self.weights = self.optimize_weights(predictions, val_data['target'])

    def predict(self, data):
        """重み付きアンサンブル予測"""
        predictions = []

        for name, model in self.models.items():
            pred = model.predict(data)
            weighted_pred = pred * self.weights[name]
            predictions.append(weighted_pred)

        return sum(predictions)

まとめ

2024年の価格予測における主要トレンド

  1. Transformerモデルの優位性
    - LSTMを上回る性能(特に長期依存関係)
    - Time2Vecエンコーディングによる時系列特徴の改善

  2. オーダーブック特徴量の進化
    - 定常性を持つ特徴量の構築
    - マルチレベル情報の活用

  3. ハイブリッドアプローチ
    - CNN-LSTM(DeepLOB)
    - PSO-LSTM(最適化統合)
    - VMD-TMFG-LSTM(マルチ特徴量)

  4. 実装上の改善
    - ウォークフォワード検証の標準化
    - リアルタイム処理の最適化
    - アンサンブル手法の洗練

推奨事項

  1. データ: オーダーブックの全レベルデータを活用
  2. モデル: Transformer または DeepLOB から開始
  3. 特徴量: 定常性を確保した Order Flow Imbalance を必須に
  4. 評価: 方向予測精度とSharpe比の両方を重視
  5. 実装: リアルタイム処理を前提とした設計

これらの手法を組み合わせることで、2024年の最先端の価格予測システムを構築できます。