【MQL5】HistoryDealGetDouble関数の使い方と自動売買実装コード

1. HistoryDealGetDouble関数の概要と実務での活用法

MQL5において、HistoryDealGetDoubleは「過去に行われた約定(Deal)」の数値データ(価格、利益、手数料など)を取得するための非常に重要な関数です。

MT4からMQL5に移行した開発者が最初につまずくポイントは、「注文(Order)」「約定(Deal)」「ポジション(Position)」の違いです。MQL5では、エントリーや決済という「行為」はすべて「約定(Deal)」として履歴に記録されます。

実務においては、単に決済価格を知るだけでなく、「実際に発生したスワップや手数料を差し引いた純利益」を計算したり、「約定時の正確なスリッページ」を分析したりする際にこの関数が必須となります。特に、ナンピンや分割売買を行う複雑なEA(エキスパートアドバイザー)では、現在のポジション情報だけでなく、過去の約定履歴を正確に紐解くスキルが不可欠です。

2. 構文と戻り値

この関数は、指定した約定チケット番号に対応するdouble型のプロパティを返します。

構文

double HistoryDealGetDouble(
   ulong                         ticket_number,     // 約定チケット番号
   ENUM_DEAL_PROPERTY_DOUBLE     property_id        // プロパティの種類
);

パラメーター

  1. ticket_number: 取得したい約定のチケット番号(ulong型)。
  2. property_id: 取得したい情報の種類。以下の定数などがよく使われます。
    • DEAL_PRICE: 約定価格
    • DEAL_VOLUME: 約定数量
    • DEAL_PROFIT: 損益(決済時のみ)
    • DEAL_COMMISSION: 手数料
    • DEAL_SWAP: スワップ

戻り値

指定されたプロパティの値をdouble型で返します。指定したチケットが存在しない場合は 0.0 を返します。

3. 具体的な使い方・実践サンプルコード

以下のコードは、最後に決済されたトレードの「純利益(損益+手数料+スワップ)」を計算してエキスパートログに出力する例です。

void OnStart()
{
   // 1. 履歴を取得する範囲を指定(ここでは全履歴)
   datetime end = TimeCurrent();
   datetime start = end - PeriodSeconds(PERIOD_D1) * 30; // 過去30日間

   // 履歴の選択(これを行わないとHistoryDealGetDoubleは機能しません)
   if(!HistorySelect(start, end))
   {
      Print("履歴の取得に失敗しました。");
      return;
   }

   // 2. 全約定数を取得
   int deals_total = HistoryDealsTotal();

   // 3. 履歴を後ろ(最新)から遡って、最初の「決済約定」を探す
   for(int i = deals_total - 1; i >= 0; i--)
   {
      // インデックスからチケット番号を取得
      ulong ticket = HistoryDealGetTicket(i);
      if(ticket > 0)
      {
         // その約定が「決済」であるか確認(エントリーではなくエグジット)
         long entry_type = HistoryDealGetInteger(ticket, DEAL_ENTRY);

         if(entry_type == DEAL_ENTRY_OUT)
         {
            // 4. HistoryDealGetDoubleを使って詳細データを取得
            double profit     = HistoryDealGetDouble(ticket, DEAL_PROFIT);
            double commission = HistoryDealGetDouble(ticket, DEAL_COMMISSION);
            double swap       = HistoryDealGetDouble(ticket, DEAL_SWAP);
            double volume     = HistoryDealGetDouble(ticket, DEAL_VOLUME);
            double price      = HistoryDealGetDouble(ticket, DEAL_PRICE);

            // 合計純利益の計算
            double net_profit = profit + commission + swap;

            PrintFormat("最新決済約定: チケット#%I64u", ticket);
            PrintFormat("数量: %.2f, 価格: %.5f", volume, price);
            PrintFormat("損益: %.2f, 手数料: %.2f, スワップ: %.2f", profit, commission, swap);
            PrintFormat("計(純利益): %.2f", net_profit);

            break; // 1つ見つけたらループ終了
         }
      }
   }
}

4. 使用上の注意点とよくあるエラー

① HistorySelect() の呼び出し忘れ

最も多いミスは、HistoryDealGetDouble を呼ぶ前に HistorySelect() または HistorySelectByPosition() を実行していないケースです。MQL5では、まず「どの範囲の履歴をメモリに読み込むか」を明示的に指示しない限り、関数の戻り値は常に 0 になります。

② チケット番号とインデックスの混同

HistoryDealGetDouble の第一引数は「チケット番号」です。ループ変数(iなど)をそのまま渡しても正しい値は取得できません。必ず HistoryDealGetTicket(i) を介してチケット番号を取得してから渡すようにしてください。

③ 「注文(Order)」との取り違え

指値などの「注文」の情報を取得したい場合は HistoryOrderGetDouble を使用します。HistoryDealGetDouble は「実際に売買が成立した結果」の情報を取得するためのものです。決済時に滑った(スリッページが発生した)後の「確定した価格」を知りたい場合は、必ず「Deal」の方を参照してください。

5. 【重要】自動売買における約定スピードと環境の罠

アルゴリズムトレードにおいて、ロジックと同じくらい重要なのが「実行環境」です。どれほど高度なEAを開発し、HistoryDealGetDoubleで正確な損益分析を行っても、自宅のPCや一般的なインターネット回線で運用している限り、本当のパフォーマンスは発揮できません。家庭用回線には避けられないネットワーク遅延(レイテンシ)が存在し、相場急変時にはミリ秒単位の遅れが致命的なスリッページを招き、期待した価格から乖離した場所で約定してしまうからです。

プロレベルの自動売買を実践するエンジニアにとって、ブローカーの取引サーバーに物理的に近い場所に位置する「専用VPS(仮想専用サーバー)」の導入は必須事項です。ネットワーク遅延を極限まで排除することで、EAの注文はミリ秒単位で高速執行され、スリッページによる「見えない損失」を最小限に抑えることが可能になります。インフラへの投資を惜しむことは、シストレにおいて自らハンデを背負って戦うことと同義であると理解すべきです。

💡 この記事の内容を実運用で活かすには?

この記事の内容を実運用で活かすには、正しい環境が必要です。
特にVPSを使わないと、このロジックは再現できません。

コメント

タイトルとURLをコピーしました