MQL5ログファースト設計を実コードで解説|event・side・reason・detailで追跡するEA開発

EAファンクラブ

MQL5でEAを開発する時、不具合の原因を後から追えるかどうかは、ロジックそのものと同じくらい重要です。

EAがエントリーしない、注文に失敗する、チャート表示が残る、時間足変更後に挙動が変わる、長時間稼働でログが増えすぎる。こうした問題は、発生時点の状態をExpertsログで追えないと、後から再現条件を整理することが難しくなります。

この記事では、MQL5 EA開発におけるログファースト設計を、学習用に一般化したコード断片を使って解説します。売買判断や収益性を示す記事ではなく、EAを安全に検証・保守するためのログ設計を整理する記事です。

完成EAソース全文、外部シート参照の動作制御ロジック、認証、endpoint、token、URL、実運用set値、中核エントリー条件は公開しません。この記事で扱うのは、ログ設計の考え方と、公開可能な範囲に一般化した短いコード例だけです。

この記事で扱う範囲

項目この記事で扱う内容扱わない内容
目的ExpertsログでEAの状態、見送り理由、失敗理由を追える設計利益を狙う売買ロジック、エントリー条件の公開
コード学習用に簡略化したログ関数、ログ抑制、出力例完成EAソース全文、実運用コード全文
ログevent、side、reason、detailに分けた構造化ログ認証情報、token、URL、口座情報を含むログ
確認対象INIT、ENTRY_SKIP、ORDER_FAIL、OBJECT_AUDITなどの考え方外部制御値の詳細、実運用set値、中核判定条件
読者MQL5開発者、EA利用者、開発依頼前にログを整理したい人売買判断や推奨設定を知りたい人

ログファースト開発とは

ログファースト開発とは、EAが正常に動いた時だけでなく、動かなかった理由、見送った理由、失敗した理由、保護処理が継続している理由を、最初からログで追えるように設計する考え方です。

MQL5では、Print()を使えばExpertsログへ文字を出せます。しかし、単にPrintを増やすだけでは、実運用や長時間検証で必要な情報を追えません。

重要なのは、ログを次のように分解して出すことです。

要素意味
layerどの機能層のログかINIT、ORDER、ENTRY、OBJECT_AUDIT、RISK
sideBUY側かSELL側か、方向なしのログかBUY、SELL、NONE
event何が起きたかSTART、SKIP、SEND_FAIL、STARTUP_FOUND
reasonなぜ起きたかSPREAD_LIMIT、NO_POSITION、INVALID_HANDLE
detail確認に必要な補足情報symbol、timeframe、retcode、object_kindなど

このように分けると、ログを見た時に「どの処理で」「どちら側で」「何が起きて」「なぜそうなったか」を追いやすくなります。

Printをただ増やすだけでは不十分な理由

EA開発では、不具合が出るたびにPrintを追加したくなります。しかし、Printを場当たり的に追加すると、次の問題が起きます。

よくある状態問題点改善方針
同じログが毎tick出るExpertsログが埋まり、重要な失敗ログが流れる状態変化時だけ出す、またはthrottleする
日本語文章だけのログ検索、比較、機械的な抽出がしにくいevent、reason、detailを固定キーにする
成功ログだけ多い見送り理由や失敗理由が追えないSKIP、BLOCK、FAILを理由付きで出す
売買判定とログ出力が混ざるログ修正が売買挙動へ影響する可能性がある判定helperとログhelperを分離する
機密情報がそのまま出る問い合わせ時にURL、token、口座情報が漏れるログ出力前にマスク・除外する

ログファースト設計では、Printを増やすこと自体が目的ではありません。検証、保守、問い合わせ対応で使える形に整理して出すことが目的です。

event / side / reason / detail の考え方

構造化ログでは、ログの文章を長くするよりも、固定された項目で揃えることを優先します。

たとえば、次のようなログ形式にすると、後から検索しやすくなります。

DIAG/ORDER: side=BUY event=SEND_FAIL reason=RETCODE_REJECT detail=symbol=XXX retcode=10000
DIAG/ENTRY: side=SELL event=SKIP reason=SPREAD_LIMIT detail=spread=high
DIAG/OBJECT_AUDIT: side=NONE event=STARTUP_FOUND reason=VISUAL_ONLY detail=kind=AVG_LINE

この形式では、ログの前半だけで大まかな種類を把握できます。

  • DIAG/ORDER:注文・発注結果に関するログ
  • side=BUY:BUY側の処理
  • event=SEND_FAIL:注文送信に失敗
  • reason=RETCODE_REJECT:失敗理由の分類
  • detail=…:調査時に必要な補足

このようにログを分けると、同じEAでも、初期化、エントリー見送り、注文失敗、決済失敗、Object監査、リスク制御などを別々に確認できます。

ログを出す主な場面

EAでログを出す場面は、成功時だけではありません。むしろ、見送りや失敗の理由を残すことが重要です。

ログ種別目的確認すること
INITEA起動時の準備状態を確認するバージョン、銘柄、時間足、主要設定、初期化結果
ENTRY_SKIP新規エントリーを見送った理由を確認するspread、時間、リスク、同一バー制御、権限制御など
ORDER_FAIL注文送信や変更に失敗した理由を確認するretcode、GetLastError、lot、symbol、action
OBJECT_AUDITチャート上の残存Objectや表示状態を確認する表示専用、実ロジック参照除外、削除対象、無視対象
RUNTIME稼働中の状態変化を確認する許可状態、停止状態、ガード状態、保護処理の継続
DEINITEA終了時の安全性を確認する異常終了の有無、終了時に売買処理が走っていないか

INITログで確認すること

INITログは、EAをチャートへセットした直後の確認に使います。ここで重要なのは、すべての内部情報を出すことではなく、起動状態を判断できる最小限の情報を出すことです。

INITログに入れてよい情報の例です。

  • EA名、バージョン
  • symbol、timeframe
  • 主要機能のON/OFF状態
  • ログモード
  • Object監査の実行有無
  • 初期化成功または安全停止の状態

一方で、次の情報はINITログに出してはいけません。

  • 認証token
  • endpoint
  • Webhook URL
  • Google Sheet ID
  • 口座番号
  • 購入者管理情報
  • 実運用set値の詳細

ENTRY_SKIPログで確認すること

EAがエントリーしない時、最初に必要なのは「なぜ見送ったか」です。

よくある失敗は、エントリー条件が成立していないのか、成立したが執行前のガードで止まったのかをログで分けていないことです。

状態ログで分けるべき理由
シグナル不成立ENTRY対象ではない。signal側の確認が必要
スプレッド超過signalは候補だが、broker条件で見送り
同一バー重複防止再送防止による見送り
保有上限リスク・ポジション管理による見送り
外部許可NG新規Entryだけ停止。既存ポジション管理とは分けて確認

公開記事では、外部制御の詳細や中核エントリー条件は扱いません。ただし、ログ設計上は「見送り理由をreasonとして残す」ことが重要です。

ORDER_FAILログで確認すること

注文失敗時は、MQL5側の戻り値だけでなく、注文種別、方向、symbol、lot、retcode、GetLastErrorを分けて残します。

注文に失敗した場合、単に「注文失敗」と出すだけでは、次の調査ができません。

  • lotが不正だったのか
  • AutoTradingがOFFだったのか
  • 価格が変わったのか
  • サーバー側で拒否されたのか
  • 一時的な失敗でretry対象なのか
  • そもそも注文対象のsymbolが違うのか

注文結果ログでは、少なくとも「何を送ろうとして」「何が返ってきたか」を追えるようにします。

OBJECT_AUDITログで確認すること

チャート上に描画するEAでは、Objectの残存や再セット時の誤参照が問題になることがあります。

たとえば、平均価格ライン、TPライン、Trailライン、仮想ライン、ラベル、パネル部品などが残っている場合、それを実ロジックへ使うのか、表示専用として無視するのかを分ける必要があります。

Object監査ログでは、次のような観点を残します。

監査項目確認内容
STARTUP_FOUND起動時に既存Objectを検出した
VISUAL_ONLY表示専用として扱い、実ロジックへ使わない
IGNORE_FOR_LOGIC残存Objectを判定ロジックから除外する
CLEANUP_PLAN削除候補だが、条件を確認してから処理する
CLEANUP_SUMMARY監査や整理の結果を要約する

EA削除時にすべてのObjectを無理に消すより、再セット時に監査して、実ロジックへ誤採用しない構造にする方が安全な場合があります。

状態変化時だけログを出す理由

リアルタイムで動くEAでは、OnTickが何度も呼ばれます。条件不成立や待機状態を毎tickログに出すと、Expertsログがすぐに埋まります。

ログ過多になると、重要な失敗ログを見落としやすくなります。そのため、ログは次のように分けると実用的です。

ログ種別出力方針
注文成功・注文失敗重要なので原則出す
決済成功・決済失敗重要なので原則出す
設定不正状態変化時、または一定間隔で出す
待機中毎tickではなく抑制する
同じ見送り理由一定秒数以内は抑制する
起動時チェックリスト起動時に1回だけ出す

実コード断片1:構造化ログhelper

以下は、実際のEAで使う考え方を学習用に簡略化したコード例です。完成EAのソース全文ではなく、構造を理解するための抜粋です。

// 学習用に一般化したログ出力helperです。
// 実運用EAの完成ソースではありません。

bool CanWriteDiagLog()
{
   return true; // 実際はinputやruntime設定でON/OFFを分けます。
}

string SafeText(string value, string fallback)
{
   if(value == "")
      return fallback;

   // 公開用の考え方:機密情報に該当するdetailは出さない。
   if(StringFind(value, "token") >= 0)
      return "masked";

   return value;
}

void WriteDiagLog(string layer, string side, string eventName, string reason, string detail)
{
   if(!CanWriteDiagLog())
      return;

   string safeLayer  = SafeText(layer, "GENERAL");
   string safeSide   = SafeText(side, "NONE");
   string safeEvent  = SafeText(eventName, "UNKNOWN");
   string safeReason = SafeText(reason, "NO_REASON");
   string safeDetail = SafeText(detail, "no detail");

   Print("DIAG/", safeLayer,
         ": side=", safeSide,
         " event=", safeEvent,
         " reason=", safeReason,
         " detail=", safeDetail);
}

実際のEAでは、認証、外部制御、口座条件、エラー処理、ログ出力などを分けて設計します。この記事では、公開できる範囲の構造だけを取り上げています。

このコードの役割

行・処理役割
CanWriteDiagLogログ出力をON/OFFする入口です。開発版、検証版、配布版でログ粒度を変える時に使います。
SafeText空文字や機密情報をそのまま出さないための補助です。
WriteDiagLoglayer、side、event、reason、detailを固定形式で出力します。
PrintExpertsログへ1行で出します。ログ形式を揃えることで、後から検索しやすくなります。

ここで重要なのは、ログ出力を各処理に直接書き散らさず、helperへ集約することです。helperへ集約すると、ログ形式、マスク処理、出力ON/OFF、ログ抑制を後から調整しやすくなります。

実コード断片2:同じログを出しすぎない抑制例

以下は、同一キーのログを一定秒数だけ抑制する学習用コード例です。完成EAのソース全文ではなく、ログ過多を防ぐ考え方を示すための簡略例です。

// 学習用の簡易throttle例です。
// 実際のEAでは、ログ種類ごとに抑制秒数を分けます。

string g_lastLogKey = "";
datetime g_lastLogTime = 0;

bool ShouldSkipSameLog(string key, int throttleSeconds)
{
   datetime nowTime = TimeCurrent();

   if(key == g_lastLogKey)
   {
      if((nowTime - g_lastLogTime) < throttleSeconds)
         return true;
   }

   g_lastLogKey = key;
   g_lastLogTime = nowTime;
   return false;
}

void WriteDiagLogThrottled(string layer, string side, string eventName, string reason, string detail)
{
   string key = layer + "|" + side + "|" + eventName + "|" + reason;

   if(ShouldSkipSameLog(key, 300))
      return;

   WriteDiagLog(layer, side, eventName, reason, detail);
}

実際のEAでは、注文失敗や決済失敗のように必ず残したいログと、待機状態のように抑制したいログを分けます。すべてのログを同じ抑制にすると、重要な失敗履歴が欠落する可能性があるためです。

ログ抑制で注意すること

  • 注文失敗、決済失敗、初期化失敗は抑制しすぎない
  • 待機中、同じ見送り理由、同じ警告は抑制してよい
  • 抑制キーにはlayer、side、event、reasonを含める
  • detailまでキーに入れると抑制が効きにくい場合がある
  • 検証時だけ詳細ログをONにできるようにする

実コード断片3:理由付きログ出力の使い分け

以下は、INIT、ENTRY_SKIP、ORDER_FAIL、OBJECT_AUDITを、同じログhelperで出し分ける学習用コード例です。売買判断や中核エントリー条件は含めていません。

// 学習用の使用例です。
// エントリー条件や外部制御ロジックは含めていません。

void LogInitExample()
{
   WriteDiagLog("INIT", "NONE", "START",
                "EA_LOADED",
                "symbol=" + _Symbol + " tf=" + EnumToString(_Period));
}

void LogEntrySkipExample(bool isBuy, string reason)
{
   string side = (isBuy ? "BUY" : "SELL");

   WriteDiagLogThrottled("ENTRY", side, "SKIP",
                         reason,
                         "scope=new_entry_only");
}

void LogOrderFailExample(bool isBuy, MqlTradeResult &result)
{
   string side = (isBuy ? "BUY" : "SELL");

   WriteDiagLog("ORDER", side, "SEND_FAIL",
                "ORDER_RETCODE",
                "retcode=" + IntegerToString((int)result.retcode));
}

void LogObjectAuditExample(string objectKind)
{
   WriteDiagLog("OBJECT_AUDIT", "NONE", "STARTUP_FOUND",
                "VISUAL_ONLY",
                "kind=" + objectKind);
}

実際のEAでは、認証、外部制御、口座条件、エラー処理、ログ出力などを分けて設計します。この記事では、公開できる範囲の構造だけを取り上げています。

この例で分かること

  • INIT、ENTRY、ORDER、OBJECT_AUDITを同じ形式で出せる
  • BUY / SELL / NONEをsideとして分けられる
  • SKIP、SEND_FAIL、STARTUP_FOUNDなどのeventを固定できる
  • reasonを分けることで、同じSKIPでも理由を追える
  • detailは調査に必要な補足だけに絞れる

ログ設計と責務分離

ログファースト設計では、ログ出力そのものも責務分離します。

責務役割ログでの確認例
signal判定候補を作るSIGNAL、CANDIDATE、NO_SIGNAL
execution注文・決済を実行するORDER、CLOSE、SEND_FAIL、CLOSE_FAIL
riskロット、損失、上限、保護条件を扱うRISK_BLOCK、LOT_INVALID、LIMIT_REACHED
exit建値、トレール、決済条件を扱うTRAIL、BE、EXIT_SKIP、EXIT_DONE
auth利用許可や認証状態を扱う公開記事では詳細を扱わない。ログにも機密を出さない
external control外部設定による動作制御を扱う公開記事では詳細を扱わない。新規Entry停止と保護継続は分ける
UI / Objectチャート表示、パネル、ラインを扱うOBJECT_AUDIT、DISPLAY_SKIP、CLEANUP_SUMMARY

特に重要なのは、判定不成立執行見送りを混同しないことです。

シグナルが成立していない場合と、シグナル候補はあるがスプレッドや保有上限などで見送った場合では、確認すべき場所が違います。ログでは、この違いをreasonとして残す必要があります。

ログに出してよい情報・出してはいけない情報

ログは問い合わせや検証に使うため、必要な情報を残す一方で、機密情報を出してはいけません。

分類ログに出してよい例ログに出してはいけない例
環境symbol、timeframe、digits、point口座番号、サーバー名、個人情報
注文結果retcode、action、side、lotの分類実運用set値の詳細、推奨ロット表現
外部連携接続成功/失敗の分類、masked表示endpoint、token、Webhook URL、GAS URL、Sheet ID
認証OK / NG / masked summary認証ロジック、購入者管理情報、許可判定の詳細
Entry見送り理由の分類中核エントリー条件、独自優位性のある判定式
Objectkind、event、visual-only、ignore他EAや手動Objectを巻き込む詳細削除方針

問い合わせ時にログを共有する場合も、URL、token、口座情報、個人情報が含まれていないか確認してください。

よくある失敗例

失敗1:成功ログしか出していない

注文成功や初期化成功だけをログに出していると、EAが動かない時に原因を追えません。見送り、block、failも理由付きで残す必要があります。

失敗2:毎tick同じログを出している

OnTickで毎回同じPrintを出すと、短時間でログが大量になります。待機状態や同じ見送り理由は、状態変化時または一定間隔で出す方が実用的です。

失敗3:ログ文言が毎回違う

「注文できませんでした」「発注失敗」「Order error」のように表記が揺れると、検索や比較が難しくなります。eventやreasonは固定名にします。

失敗4:ログに機密情報を出している

外部連携や認証を使うEAでは、URL、token、Sheet ID、Webhook URLなどをログに出してはいけません。ログは共有される前提で設計します。

失敗5:ログ出力が売買ロジックへ影響している

ログ出力のON/OFFを変更しただけで売買判定や決済挙動が変わる構造は危険です。判定helper、執行helper、ログhelperは分けて設計します。

Expertsログで確認するポイント

EAの状態を確認する時は、Expertsログの中で次の順に見ます。

  1. INITログでEAが正しく起動しているか確認する
  2. RUNTIMEまたはCHECKログで主要状態が安全側になっていないか確認する
  3. ENTRY_SKIPログで新規エントリー見送り理由を確認する
  4. ORDERログで注文送信結果を確認する
  5. CLOSE、EXIT、TRAILなどの管理決済ログを確認する
  6. OBJECT_AUDITログで表示Objectの残存や無視処理を確認する
  7. DEINIT周辺で異常終了や終了時の余計な売買処理がないか確認する

MT5のExpertsログとJournalログの見方は、基本確認ページも参考にしてください。

MT5のログ確認方法|Experts・Journalの見方

問い合わせ前に送るログ

EAの不具合確認や開発相談を行う場合は、次の情報を整理すると原因を切り分けやすくなります。

送る情報内容注意点
EA名・バージョン対象ファイル名とバージョン旧版と混在していないか確認する
発生時刻問題が起きた日時PC時刻、サーバー時刻の違いに注意する
symbol・timeframe対象銘柄と時間足チャートとsetの対象を一致させる
ExpertsログINIT、ENTRY_SKIP、ORDER_FAIL、OBJECT_AUDITなど発生前後を含める
Journalログ端末側エラーや接続状態Expertsだけで不足する時に確認する
setファイル使用した設定URL、token、口座情報は削除またはマスクする
スクリーンショットチャート、パネル、ログ画面口座番号などが映っていないか確認する

不具合相談前の整理は、次のページも参考にしてください。

不具合報告・調査依頼について

ログファースト設計を開発依頼に活かす

EA開発を依頼する時も、ログ仕様を最初に決めておくと、完成後の確認がしやすくなります。

開発依頼前には、次のようなログ方針を整理しておくと実務上有効です。

  • 起動時に何を確認したいか
  • エントリー見送り理由をどこまで出したいか
  • 注文失敗時にretcodeを出すか
  • 決済失敗や変更失敗をどの粒度で出すか
  • チャートObjectの残存や再セットを監査するか
  • 長時間稼働時にログ過多を防ぐか
  • 問い合わせ時に送るログ項目を決めるか

仕様書、setファイル、ログ、スクリーンショットを整理する場合は、次のページも確認してください。

MT5開発依頼前に用意する資料まとめ|仕様書・setファイル・ログ・スクリーンショット

公開しない情報

この記事では、MQL5のログ設計を学ぶために、公開可能な範囲だけを一般化して解説しています。以下は公開しません。

  • 完成EAソース全文
  • 外部シート参照による動作制御ロジック
  • 外部シートCSV取得、解析、時間枠、方向制御ロジック
  • 認証、口座許可判定、購入者管理ロジック
  • endpoint、token、URL、Google Sheet ID、Webhook URL、GAS URL
  • APIキー、認証トークン、口座番号、サーバー名
  • 実運用set値
  • 中核エントリー条件
  • 独自優位性のある売買判定式
  • 利益保証、勝率保証、推奨ロット、推奨銘柄、推奨エントリー

本記事は、投資判断や売買指示ではなく、MQL5開発におけるログ設計と検証手順を理解するための技術解説です。

FAQ

このコードは完成EAとして使えますか?

いいえ。この記事のコード例は、MQL5のログ設計を理解するために簡略化した学習用コードです。完成EAとしてそのまま使うことは想定していません。

実際のEAソース全文は公開されていますか?

公開していません。完成EAソース全文、外部シート制御、認証、endpoint、token、URL、実運用set値、中核エントリー条件は公開対象外です。

EAが動かない時は、どのログを見ればよいですか?

まずINITログで起動状態を確認し、次にENTRY_SKIP、ORDER、CLOSE、OBJECT_AUDITなどを確認します。見送りなのか、注文失敗なのか、表示Objectの問題なのかを分けて見ることが重要です。

ENTRY_SKIPログが出ている場合は、エントリー条件が悪いという意味ですか?

必ずしもそうではありません。ENTRY_SKIPは、新規エントリー候補があっても、スプレッド、保有上限、同一バー制御、リスク制御などで見送る場合にも出ます。reasonを確認してください。

ORDER_FAILログが出た場合は何を確認しますか?

retcode、GetLastError、symbol、lot、注文種別、AutoTradingの状態、証拠金、ブローカー側の制約などを確認します。単に「注文失敗」と見るのではなく、戻り値と理由を分けて確認します。

ログは多いほどよいですか?

いいえ。重要な失敗ログは残すべきですが、同じ待機ログや同じ見送り理由を毎tick出すと、確認しにくくなります。状態変化時だけ出す、または一定間隔で抑制する設計が有効です。

問い合わせ時にログをそのまま送ってよいですか?

送る前に、URL、token、Webhook URL、GAS URL、Google Sheet ID、口座番号、個人情報が含まれていないか確認してください。必要に応じてマスクしたうえで共有してください。

この記事は売買判断や推奨設定を示すものですか?

いいえ。この記事はMQL5開発におけるログ設計の技術解説です。売買判断、推奨ロット、推奨銘柄、利益保証、勝率保証を行うものではありません。

関連ページ

ページ確認できること
MT5のログ確認方法|Experts・Journalの見方ExpertsログとJournalログの基本的な確認方法
MT5開発依頼前に用意する資料まとめ|仕様書・setファイル・ログ・スクリーンショット開発相談前に整理する資料
不具合報告・調査依頼について不具合相談前に整理する情報
開発・改修の相談ページを見るMT5向けEA・インジケーター開発や既存改修の相談導線
よくある質問導入、確認、相談前のFAQ
ご購入前の確認事項購入前に確認する条件や注意点
免責事項投資判断、損益、利用上の注意に関する確認
投資助言を行わない方針売買助言ではなく技術支援として扱う方針

まとめ

MQL5 EAのログ設計では、Printを増やすことよりも、後から追える形でログを設計することが重要です。

特に、次の4点を分けておくと、不具合確認や保守がしやすくなります。

  • event:何が起きたか
  • side:BUY、SELL、NONEのどれか
  • reason:なぜ起きたか
  • detail:確認に必要な補足情報

EAが動かない時に重要なのは、単に「動かない」と判断することではなく、起動、判定、見送り、発注、決済、表示、終了処理のどこで止まっているかを分けて確認することです。

ログファースト設計は、開発者だけでなく、EAを使う側、検証する側、サポートを受ける側にも役立ちます。完成EAの中核ロジックを公開しなくても、ログ設計の考え方を理解しておくことで、問題発生時の切り分けがしやすくなります。

ABOUT ME
記事URLをコピーしました