English Deutsch
preview
取引量による取引の洞察:OHLCチャートを超えて

取引量による取引の洞察:OHLCチャートを超えて

MetaTrader 5 | 4 4月 2025, 14:08
149 0
Javier Santiago Gaston De Iriarte Cabrera
Javier Santiago Gaston De Iriarte Cabrera

はじめに

テクニカル分析の分野では、トレーダーは歴史的に、市場活動の主な指標として価格変動に依存してきました。本研究では、取引量の高度な数学的分析と機械学習技術を組み合わせた独自の方法論を提示し、取引量パターンが市場の動向に対するより深い洞察を提供し得ることに重点を置いています。LSTMニューラルネットワークと微積分に基づく取引量導関数を組み合わせることで、従来のテクニカル分析手法を超える洗練されたシステムを提供します。

この記事は3つの主要なセクションに分かれています。最初のセクションでは、取引量分析の基本的な重要性とその数学的基礎について説明します。2番目では、取引量導関数とLSTM予測の市場機会の特定への実用的応用について検討します。3番目では、取引量ダイバージェンス分析、トレンド確認、ブレイクアウト検証がどのように取引判断を強化するために活用できるかを説明します。


取引量のコア機能を理解する

特定の期間に取引された株式または契約の総数は取引量と呼ばれ、市場の活動と流動性を示す重要な指標です。価格は市場の方向性を示しますが、取引量は市場の動きの背後にある信頼を示し、トレンドの根底にある強さと持続力を浮き彫りにします。取引量は価格変動の背後にある力であり、価格変動をサポートしたり、反対したりする能力を持っています。取引量が多い大きな価格変動は、取引量が少ない場合よりも市場の信頼が高いことを示すことが多いです。さらに、取引量パターンは価格の変化を予測することが多いため、価格変動や市場の文脈とともに取引量パターンをうまく活用できるトレーダーにとっては貴重な指標となります。


取引量が重要な理由

以下は簡単な例です。

取引量分析の決定的な重要性は、標準的な分析を超えた高度な数学的手法を使用することで実証され、従来の指標だけでは実現できない、市場の動向を理解するためのより高度なフレームワークをトレーダーに提供します。OHLCデータに依存せず、取引量のダイナミクスのみに焦点を当てることで、取引量導関数やLSTMニューラルネットワークに特化した微積分学と機械学習を通じて、市場の重要な洞察を得ることができます。この革新的な方法は、取引と市場参加の微細な変化を識別するために高度な数学的概念を活用し、価格変動に先立って市場の動きを早期に警告します。

機械学習による予測と組み合わせて取引量の変化率(一次導関数)とその加速度(二次導関数)を分析することで、トレーダーは従来の取引量分析手法よりも新しいトレンドや反転の可能性をより正確に検出できます。この数学的アプローチを適切に適用することで、市場分析に対する強力な手段が提供され、従来のテクニカル分析だけでは不十分な現代のアルゴリズム主導の市場において特に有効となります。

この方法は、一次導関数(取引量の変化率)、二次導関数(取引量変化の加速)、および同じ取引量導関数を確認する将来の取引量に関するLSTM予測という3つの重要な取引量の要素を調べます。価格のノイズを排除することにより、このアプローチは市場参加の動向にのみ焦点を当てます。 

EAは、標準的なMetaTraderの宣言から開始されます。これには、注文管理のためのTradeライブラリと予測用のカスタムVolume_LSTMライブラリが含まれています。indicator_separate_windowプロパティは、このインジケーターが別ウィンドウで表示されることを示し、視覚化のために3つのインジケーターバッファが割り当てられます。
#property copyright "Your Name"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 3
#include <Trade\Trade.mqh>
#include <Volume_LSTM.mqh>
CTrade trade;

パラメータは論理グループに編成されます。LSTM構成セクションはニューラルネットワークの動作を制御し、エントリパラメータは取引ルールを管理します。各パラメータには特定の目的があり、LSTMパラメータは予測モデルの複雑さとメモリを制御します。取引パラメータはポジションのサイズと利益目標を定義し、リスク管理パラメータは損失限度とトレーリングストップを設定します。

input group "Configuración LSTM"
input bool     UseLSTM = true;              
input int      LSTMHiddenSize = 32;         
input int      LSTMLookback = 10;           

input group "Entry Parameters"
input double   Lots = 0.1;         
input double   TPPoints = 100;      
input int      Periods = 4;         
input int      AccelBars = 4;       
input int      MaxBarsInTrade = 2; 
input double   ProfitClose = 15;    
input double   MaxDailyLoss = -25; 
input double   TrailingStart = 5;  
input double   TrailingStep = 5;

この関数は、取引量の変化率(一次導関数)と取引量変化の加速度(二次導関数)を計算します。既存の導関数をシフトして履歴を維持し、現在の取引量と前の取引量との差として新しい一次導関数を計算し、一次導関数の変化として新しい二次導関数を計算します。そして、取引量のモメンタムと加速度に関する洞察を提供します。

取引量の一次導関数を見ることで、本質的には、取引活動が時間の経過とともに増加しているか減少しているかを追跡します。この取引量の変動パターンは、市場のモメンタムに対する最初の洞察を提供します。継続的に正の一次導関数は市場の関心が増加していることを示唆し、一方で負の一次導関数は関与が減少していることを示唆します。

void CalculateDerivatives() {
    for(int i = 0; i < ArraySize(volumes)-1; i++) {
        firstDerivative[i] = firstDerivative[i+1];
        secondDerivative[i] = secondDerivative[i+1];
    }

    firstDerivative[ArraySize(volumes)-1] = volumes[ArraySize(volumes)-1] - volumes[ArraySize(volumes)-2];
    secondDerivative[ArraySize(volumes)-1] = firstDerivative[ArraySize(volumes)-1] - firstDerivative[ArraySize(volumes)-2];
}

これらの関数は取引のライフサイクルを管理します。TrackNewTradeは最初の利用可能なスロットに新しいポジションを記録し、RemoveTradeはポジションがクローズされたときに記録を消去します。どちらの関数も、取引追跡システムの整合性を維持します。

void TrackNewTrade(ulong ticket) {
    for(int i = 0; i < ArraySize(openTrades); i++) {
        if(openTrades[i].ticket == 0) {
            openTrades[i].ticket = ticket;
            openTrades[i].openTime = TimeCurrent();
            openTrades[i].barsOpen = 0;
            break;
        }
    }
}

void RemoveTrade(ulong ticket) {
    for(int i = 0; i < ArraySize(openTrades); i++) {
        if(openTrades[i].ticket == ticket) {
            openTrades[i].ticket = 0;
            openTrades[i].openTime = 0;
            openTrades[i].barsOpen = 0;
            break;
        }
    }
}

以下は利益追跡関数です。

  1. 現在の取引日を識別する
  2. 終了した取引から実現利益を計算する
  3. ポジションからの未実現利益を追加する
  4. 複数の取引にわたって毎日の利益追跡を維持する
  5. 毎日の損失制限の強化に役立つ
double GetDailyProfit() {
    datetime today = StringToTime(TimeToString(TimeCurrent(), TIME_DATE));

    if(lastDayChecked != today) {
        lastDayChecked = today;
        dailyProfit = 0;

        HistorySelect(today, TimeCurrent());
        int deals = HistoryDealsTotal();

        for(int i = 0; i < deals; i++) {
            ulong ticket = HistoryDealGetTicket(i);
            if(ticket > 0) {
                if(HistoryDealGetString(ticket, DEAL_SYMBOL) == _Symbol)
                    dailyProfit += HistoryDealGetDouble(ticket, DEAL_PROFIT);
            }
        }
    }
    
    // Add floating P/L
    double floatingProfit = 0;
    for(int i = PositionsTotal() - 1; i >= 0; i--) {
        ulong ticket = PositionGetTicket(i);
        if(ticket > 0 && PositionSelectByTicket(ticket)) {
            if(PositionGetString(POSITION_SYMBOL) == _Symbol)
                floatingProfit += PositionGetDouble(POSITION_PROFIT);
        }
    }

    return dailyProfit + floatingProfit;
}

以下はトレーリングストップ関数です。

  1. すべてのポジションを反復処理する
  2. 各ポジションのポイント利益を計算する
  3. 利益に基づいてストップロスレベルを更新する
  4. 利益を確定するためのトレーリングメカニズムを実装する
  5. 買いポジションと売りポジションの両方を別々に処理する
void ApplyTrailingStop(double point) {
    for(int i = PositionsTotal() - 1; i >= 0; i--) {
        ulong ticket = PositionGetTicket(i);
        if(ticket <= 0) continue;

        if(PositionSelectByTicket(ticket)) {
            double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
            double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
            double currentSL = PositionGetDouble(POSITION_SL);
            long posType = PositionGetInteger(POSITION_TYPE);

            // Calculate and update trailing stop
            double profitPoints;
            if(posType == POSITION_TYPE_BUY) {
                profitPoints = (currentPrice - openPrice) / point;
                if(profitPoints >= TrailingStart) {
                    double newSL = openPrice + (profitPoints - TrailingStep) * point;
                    if(currentSL < newSL || currentSL == 0) {
                        trade.PositionModify(ticket, newSL, PositionGetDouble(POSITION_TP));
                    }
                }
            }
            // Similar logic for SELL positions
        }
    }
}

取引活動の加速または減速を示すことによって、取引量の二次導関数はさらに詳細な情報を提供します。この二次導関数が正の値を示す場合、取引量が増加しており、その増加率が加速していることを意味しているため、市場の勢いが高まっていることを強く示唆しています。市場参加者の関心が急速に高まっていることを示しており、この取引量の加速は、顕著な市場の動きが起こる前にしばしば発生します。私たちは、これらの導関数と将来の取引量パターンを予測するLSTMニューラルネットワーク予測を組み合わせることで、市場の行動を予測するための強力なフレームワークを提供します。私たちの研究は、取引量シーケンス内の複雑なパターンを識別するLSTMの能力によってさらに裏付けが強化され、観測された取引量の傾向が持続する可能性が高いかどうかを判断する助けとなります。

以下は主な取引ロジックです。

  1. 新しいバーの形成を確認する
  2. 1日の損失限度額を確認する
  3. 取引情報を更新する
  4. 取引量分析を実行する
  5. LSTM予測を生成する(有効な場合)
  6. 複数の要素に基づいて取引の決定を下す
  7. 条件が整えばポジションを建てる
void OnTick() {
    static datetime lastBar = 0;
    datetime currentBar = iTime(_Symbol, PERIOD_CURRENT, 0);

    if(lastBar == currentBar) return;
    lastBar = currentBar;

    if(GetDailyProfit() < MaxDailyLoss) {
        CloseAllPositions();
        return;
    }

    // Update and calculate
    UpdateTradesInfo();
    CheckTimeBasedClose();
    
    if(!CanTrade()) return;

    // Volume analysis and LSTM prediction
    // ... volume calculations ...
    
    if(UseLSTM && volumePredictor != NULL) {
        // LSTM prediction logic
        // ... prediction calculations ...
    }

    CalculateDerivatives();
    
    // Trading decisions based on calculations
    if(consecutiveAccel >= AccelBars) {
        if((!UseADX && !UseOBV) || ConfirmLongSignal()) {
            // Open buy position
        }
    }
    else if(consecutiveAccel <= -AccelBars) {
        if(!UseADX && !UseOBV || ConfirmShortSignal()) {
            // Open sell position
        }
    }
}

テクニカル指標の計算

  1. インジケーター値のデータバッファを設定する
  2. ハンドルからインジケータデータをコピーする
  3. ローカル配列を新しい値で更新する
  4. 意思決定のための指標データを維持する
void CalculateADX() {
    if(!UseADX) return;

    double adx_buffer[];
    double plusdi_buffer[];
    double minusdi_buffer[];
    ArraySetAsSeries(adx_buffer, true);
    ArraySetAsSeries(plusdi_buffer, true);
    ArraySetAsSeries(minusdi_buffer, true);

    CopyBuffer(adx_handle, MAIN_LINE, 0, ArraySize(adx_main), adx_buffer);
    CopyBuffer(adx_handle, PLUSDI_LINE, 0, ArraySize(adx_plus), plusdi_buffer);
    CopyBuffer(adx_handle, MINUSDI_LINE, 0, ArraySize(adx_minus), minusdi_buffer);

    ArrayCopy(adx_main, adx_buffer);
    ArrayCopy(adx_plus, plusdi_buffer);
    ArrayCopy(adx_minus, minusdi_buffer);
}

各コンポーネントは連携して、堅牢なリスク管理プラクティスを維持しながら、取引量分析、LSTM予測、従来のテクニカル指標を組み合わせた包括的な取引システムを作成します。

Volume_LSTM.mqhファイルは、取引量を予測するために特別に設計された長・短期記憶(LSTM)ニューラルネットワークを実装します。

コードは、2D行列演算を処理する基本的なMatrix2D構造体から始まります。

struct Matrix2D {
    double values[];
    int rows;
    int cols;
    
    void Init(int r, int c) {
        rows = r;
        cols = c;
        ArrayResize(values, rows * cols);
        ArrayInitialize(values, 0);
    }
    // ... other methods
}

LSTMCellは包括的な構造体として実装されます。

struct LSTMCell {
    double forget_gate[];
    double input_gate[];
    double cell_state[];
    double output_gate[];
    double hidden_state[];
    
    Matrix2D Wf;  // Forget gate weights
    Matrix2D Wi;  // Input gate weights
    Matrix2D Wc;  // Cell state weights
    Matrix2D Wo;  // Output gate weights
    
    double bf[];  // Forget gate bias
    double bi[];  // Input gate bias
    double bc[];  // Cell state bias
    double bo[];  // Output gate bias
    
    int hidden_size;
    int input_size;
};

実装には、標準的なニューラルネットワーク活性化関数が含まれています。

double Sigmoid(double x) {
    return 1.0 / (1.0 + MathExp(-x));
}

double Tanh(double x) {
    return (MathExp(x) - MathExp(-x)) / (MathExp(x) + MathExp(-x));
}

重みはXavier/Glorot初期化のバリエーションを使用して初期化されます。

void InitializeWeights() {
    double scale = MathSqrt(2.0 / (lstm.input_size + lstm.hidden_size));
    
    // Initialize weight matrices
    lstm.Wf.Init(lstm.hidden_size, lstm.input_size);
    lstm.Wi.Init(lstm.hidden_size, lstm.input_size);
    // ... other initializations

    // Random initialization with scaling
    for(int i = 0; i < lstm.hidden_size; i++) {
        for(int j = 0; j < lstm.input_size; j++) {
            lstm.Wf.Set(i, j, (MathRand() / 32768.0 - 0.5) * scale);
            // ... other weight initializations
        }
    }
}

実装にはデータの正規化が含まれます。

void NormalizeVolumes() {
    volume_mean = 0;
    double sum_squared = 0;
    
    // Calculate mean
    for(int i = 0; i < ArraySize(historical_volumes); i++) {
        volume_mean += historical_volumes[i];
    }
    volume_mean /= ArraySize(historical_volumes);
    
    // Calculate standard deviation
    for(int i = 0; i < ArraySize(historical_volumes); i++) {
        sum_squared += MathPow(historical_volumes[i] - volume_mean, 2);
    }
    volume_std = MathSqrt(sum_squared / ArraySize(historical_volumes));
    
    // Normalize volumes
    if(volume_std == 0) volume_std = 1;  // Prevent division by zero
    for(int i = 0; i < ArraySize(historical_volumes); i++) {
        historical_volumes[i] = (historical_volumes[i] - volume_mean) / volume_std;
    }
}

以下がコア予測ロジックです。

double PredictNextVolume() {
    if(!is_initialized) return 0;
    
    double input1 = historical_volumes[ArraySize(historical_volumes)-1];
    
    // LSTM forward pass
    for(int h = 0; h < lstm.hidden_size; h++) {
        double ft = 0, it = 0, ct = 0, ot = 0;
        
        // Calculate gates
        for(int i = 0; i < lstm.input_size; i++) {
            ft += lstm.Wf.Get(h, i) * input1;
            it += lstm.Wi.Get(h, i) * input1;
            ct += lstm.Wc.Get(h, i) * input1;
            ot += lstm.Wo.Get(h, i) * input1;
        }
        
        // Apply gates and calculate states
        lstm.forget_gate[h] = Sigmoid(ft + lstm.bf[h]);
        lstm.input_gate[h] = Sigmoid(it + lstm.bi[h]);
        double c_tilde = Tanh(ct + lstm.bc[h]);
        lstm.cell_state[h] = lstm.forget_gate[h] * lstm.cell_state[h] + 
                            lstm.input_gate[h] * c_tilde;
        lstm.output_gate[h] = Sigmoid(ot + lstm.bo[h]);
        lstm.hidden_state[h] = lstm.output_gate[h] * Tanh(lstm.cell_state[h]);
    }
    
    // Calculate final prediction
    double prediction = 0;
    for(int h = 0; h < lstm.hidden_size; h++)
        prediction += lstm.hidden_state[h];
    prediction /= lstm.hidden_size;
    
    return prediction * volume_std + volume_mean;  // Denormalize
}


結果

以下は30分期間でのEURUSDの結果です。設定はSetting_eurusd.setです。

設定

グラフ

バックテスト

30分時間枠期間のGBPUSD

GBPUSD settings.set

グラフ

バックテスト

大規模な最適化により、大きな通貨ペアでより良い結果が得られる可能性がありますが、時間の都合でこの記事を拡張することはできません。各通貨ペアに対して大規模な最適化を行うことを強くお勧めします。また、コメント欄に新しい設定の提案を追加してくれるユーザーが現れることを期待しています。


高度なテクニック

トレンドの確認

価格が上昇する際に取引量が多いことは、市場の強いサポートを示し、トレンドが継続する可能性が高いことを意味します。逆に、価格が下落する際に取引量が多い場合は、強い売り圧力があることを反映しており、下降トレンドを裏付けています。価格変動時に取引量が少ない場合、トレンドが弱いか持続不可能であることを警告し、誤ったブレイクアウトや操作の兆候となることが多いです。

ブレイクアウト検証

大量のブレイクアウトは市場の確信を裏付け、持続的な価格変動につながります。低取引量のブレイクアウトは、「ブルトラップ」や「ベアトラップ」などの誤ったシグナルにつながることが多く、失敗する可能性が高くなります。ブレイクアウト中の取引量の急増は、動きを強力に裏付け、強力な市場サポートを示しています。

取引量の乖離

価格と取引量の傾向が異なる取引量の乖離は、トレンドの潜在的な反転または弱さを示します。価格が上昇しているのに取引量が減少している場合は上昇トレンドが弱まっていることを示し、価格が下落しているのに取引量が減少している場合は売り圧力が弱まり、市場が底を打つ可能性があることを示唆します。これらのパターンは、他の指標と組み合わせることで転換点を特定するのに役立ちます。


結論

最先端の機械学習手法と従来の取引量分析を融合することで、Volume-Based Trading EAはアルゴリズム取引の高度なアプローチを提供します。本システムは、ADXやOBVといった従来のテクニカル指標に加え、LSTMニューラルネットワークを活用した取引量予測をおこなうことで、市場分析と取引執行の強力な手法を実現しています。

本EAの最大の強みは、多層的なリスク管理アプローチにあります。厳格な1日あたりの損失制限、動的トレーリングストップ、詳細なポジション追跡といった機能を備えることで、リスクを適切にコントロール可能です。さらに、柔軟なエントリーパラメータと可変セッション管理を組み合わせることで、さまざまな市場環境に適応しつつ、規律ある取引手法を維持できます。

特に重要なのは、取引量の導関数分析とLSTM予測を組み合わせた独自のハイブリッドシステムです。この組み合わせにより、市場の変化が完全に顕在化する前にその兆候を捉えられる可能性があり、従来のテクニカル指標による検証を活用することで誤ったシグナルを減らす効果も期待できます。また、モジュール化されたコード構造により、将来的な機能拡張やメンテナンスも容易におこなえます。

ただし、本システムは高度なアルゴリズムを採用しているため、実際の運用前には綿密なバックテストとパラメータ調整が必須です。LSTMモデルの効果を最大限に発揮させるには、十分な計算リソースと適切な訓練データが必要となります。こうした課題はあるものの、本EAは最先端技術と実証済みの取引理論を融合した強力なツールであり、取引量を基盤とした取引手法の自動化を目指すトレーダーにとって有用なソリューションとなるでしょう。

本記事が、価格データだけでなくOHLCVデータの活用を検討する一助となれば幸いです。


ファイル名 詳細
MQL5/Profiles/Tester/Setting_eurusd.set EURUSDを例に入力を設定する
MQL5/Profiles/Tester/GBPUSD_settings.set
GBPUSDの例の入力設定
MQL5/Experts/Volume_high_low_difference_LSTM.mq5 例で使用するEA
MQL5/Include/Volume_LSTM.mqh mqhインクルードファイル(EAのパスを保存場所に合わせて変更することを忘れないでください)


MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/16445

添付されたファイル |
Volume_LSTM.mqh (14.91 KB)
Setting_eurusd.set (3.28 KB)
ログレコードをマスターする(第1回):MQL5の基本概念と最初のステップ ログレコードをマスターする(第1回):MQL5の基本概念と最初のステップ
新たな旅の始まりへようこそ。この記事は、MQL5言語で開発する方向けに、ログ操作のライブラリを段階的に作成するという特別な連載の最初の記事です。
MQL5で取引管理者パネルを作成する(第6回):取引管理パネル(II) MQL5で取引管理者パネルを作成する(第6回):取引管理パネル(II)
この記事では、多機能管理パネルの取引管理パネル(Trade Management Panel)を強化します。コードを簡素化し、読みやすさ、保守性、効率性を向上させる強力なヘルパー関数を導入します。また、追加のボタンをシームレスに統合し、インターフェイスを強化して、より幅広い取引タスクを処理する方法も紹介します。ポジションの管理、注文の調整、ユーザーとのやり取りの簡素化など、このガイドは、堅牢でユーザーフレンドリーな取引管理パネルの開発に役立ちます。
知っておくべきMQL5ウィザードのテクニック(第49回):近接方策最適化による強化学習 知っておくべきMQL5ウィザードのテクニック(第49回):近接方策最適化による強化学習
近接方策最適化は、強化学習におけるアルゴリズムの一つで、モデルの安定性を確保するために、しばしばネットワーク形式で非常に小さな増分で方策を更新します。前回の記事と同様に、ウィザードで作成したエキスパートアドバイザー(EA)において、これがどのように役立つかを探ります。
プライスアクション分析ツールキットの開発(第3回):Analytics Master EA プライスアクション分析ツールキットの開発(第3回):Analytics Master EA
シンプルな取引スクリプトから完全に機能するエキスパートアドバイザー(EA)に移行することで、取引エクスペリエンスが大幅に向上します。チャートを自動で監視し、バックグラウンドで重要な計算を実行し、さらに2時間ごとに定期的な更新を提供するシステムを想像してみてください。このEAは、的確な取引判断を下すために不可欠な主要指標を分析し、常に最新の情報を取得して戦略を効果的に調整できるようにします。