MQL5ログファースト設計を実コードで解説|event・side・reason・detailで追跡するEA開発
MQL5でEAを開発する時、不具合の原因を後から追えるかどうかは、ロジックそのものと同じくらい重要です。
EAがエントリーしない、注文に失敗する、チャート表示が残る、時間足変更後に挙動が変わる、長時間稼働でログが増えすぎる。こうした問題は、発生時点の状態をExpertsログで追えないと、後から再現条件を整理することが難しくなります。
この記事では、MQL5 EA開発におけるログファースト設計を、学習用に一般化したコード断片を使って解説します。売買判断や収益性を示す記事ではなく、EAを安全に検証・保守するためのログ設計を整理する記事です。
完成EAソース全文、外部シート参照の動作制御ロジック、認証、endpoint、token、URL、実運用set値、中核エントリー条件は公開しません。この記事で扱うのは、ログ設計の考え方と、公開可能な範囲に一般化した短いコード例だけです。
- この記事で扱う範囲
- ログファースト開発とは
- Printをただ増やすだけでは不十分な理由
- event / side / reason / detail の考え方
- ログを出す主な場面
- INITログで確認すること
- ENTRY_SKIPログで確認すること
- ORDER_FAILログで確認すること
- OBJECT_AUDITログで確認すること
- 状態変化時だけログを出す理由
- 実コード断片1:構造化ログhelper
- 実コード断片2:同じログを出しすぎない抑制例
- 実コード断片3:理由付きログ出力の使い分け
- ログ設計と責務分離
- ログに出してよい情報・出してはいけない情報
- よくある失敗例
- Expertsログで確認するポイント
- 問い合わせ前に送るログ
- ログファースト設計を開発依頼に活かす
- 公開しない情報
- FAQ
- 関連ページ
- まとめ
この記事で扱う範囲
| 項目 | この記事で扱う内容 | 扱わない内容 |
|---|---|---|
| 目的 | 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 |
| side | BUY側か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でログを出す場面は、成功時だけではありません。むしろ、見送りや失敗の理由を残すことが重要です。
| ログ種別 | 目的 | 確認すること |
|---|---|---|
| INIT | EA起動時の準備状態を確認する | バージョン、銘柄、時間足、主要設定、初期化結果 |
| ENTRY_SKIP | 新規エントリーを見送った理由を確認する | spread、時間、リスク、同一バー制御、権限制御など |
| ORDER_FAIL | 注文送信や変更に失敗した理由を確認する | retcode、GetLastError、lot、symbol、action |
| OBJECT_AUDIT | チャート上の残存Objectや表示状態を確認する | 表示専用、実ロジック参照除外、削除対象、無視対象 |
| RUNTIME | 稼働中の状態変化を確認する | 許可状態、停止状態、ガード状態、保護処理の継続 |
| DEINIT | EA終了時の安全性を確認する | 異常終了の有無、終了時に売買処理が走っていないか |
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 | 空文字や機密情報をそのまま出さないための補助です。 |
| WriteDiagLog | layer、side、event、reason、detailを固定形式で出力します。 |
| Expertsログへ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 | 見送り理由の分類 | 中核エントリー条件、独自優位性のある判定式 |
| Object | kind、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ログの中で次の順に見ます。
- INITログでEAが正しく起動しているか確認する
- RUNTIMEまたはCHECKログで主要状態が安全側になっていないか確認する
- ENTRY_SKIPログで新規エントリー見送り理由を確認する
- ORDERログで注文送信結果を確認する
- CLOSE、EXIT、TRAILなどの管理決済ログを確認する
- OBJECT_AUDITログで表示Objectの残存や無視処理を確認する
- DEINIT周辺で異常終了や終了時の余計な売買処理がないか確認する
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の中核ロジックを公開しなくても、ログ設計の考え方を理解しておくことで、問題発生時の切り分けがしやすくなります。

