「バックテストでは動くのに本番で動かない」は、ほぼ必ず
“どこかの条件で処理が止まってる / 発注が拒否されてる / そもそもEAが走ってない” のどれかです。
Print をどこに付けるか → それで何が分かるか → 次の打ち手の順でまとめます。


0) まず大前提:Printの出る場所は2つ

  • エキスパートタブPrint() のログ

  • 操作履歴(口座履歴):実際に注文が通った/決済した結果(通らなければ基本出ない)

    • 注文が通らない場合は「操作履歴」には何も出ないので、原因調査はエキスパートが本丸です。


1) Printを付ける目的は「どこで止まったか」を特定すること

EAの処理はざっくりこう進みます:

  1. EAが起動しているか(OnInit/OnTickが呼ばれているか)

  2. 環境チェックで止まってないか(取引許可/スプレッド/時間帯など)

  3. エントリー条件が満たされているか(テストと本番で値が違うことが多い)

  4. 注文を出したか(OrderSend呼んだか)

  5. 注文が通ったか(エラー番号は何か)

  6. その後の管理(TP/SL更新、決済)が走っているか

Printはこの各段階に**「通過ログ」**を置いていくイメージです。


2) 最低限これだけ入れれば迷子にならない「Printテンプレ」

A. 起動確認(EAが動いてるか)

どこに付ける?

  • OnInit()OnTick() の最初

Print例

  • OnInit: 「EA起動、口座、サーバ、シンボル、時間足」

  • OnTick: 「ティック来た、時刻、Bid/Ask、スプレッド」

わかること

  • そもそも本番でEAが動いていない(AutoTradingオフ、DLL設定、チャートに載ってない、など)を切れる

  • ティックが来ていない(市場が閉まってる/気配値が止まってる/シンボルが違う)を切れる

次の打ち手

  • Printが一切出ない → EAが起動してない。まず設定/貼り付け/自動売買を確認

  • OnInitだけ出てOnTickが出ない → ティックが来てない or OnTickに到達してない(returnで抜けてる)


B. 取引できない状態を炙り出す「環境チェックログ」

本番だけ止まる典型はここ。

どこに付ける?

  • 取引前に必ず通る部分(OnTickの序盤、またはエントリー関数の最初)

Printで出すべき項目

  • IsTradeAllowed()(取引が許可状態か)

  • AccountTradeMode()(口座が取引できる種類か)

  • MarketInfo(Symbol(), MODE_TRADEALLOWED)(銘柄として取引可か)

  • スプレッド(Ask-Bid または MODE_SPREAD

  • StopLevel / FreezeLevel(TP/SLが近すぎて拒否される原因)

  • TradeContextBusy()(取引コンテキストが塞がってないか)

  • 時間帯フィルタがあるなら「今は取引時間内か」

わかること

  • 本番ではスプレッドが広くてフィルタに引っかかってる

  • StopLevel/FreezeLevelのせいでTP/SL設定が通らない

  • 取引許可がオフ、あるいはサーバ都合で取引不可

次の打ち手

  • スプレッドで止まってる → フィルタ基準/時間帯を見直す(特にオープン直後は広がる)

  • StopLevelで止まる → SL/TP距離を最低距離以上にする


C. 「条件がそもそも成立してない」確認ログ(最重要)

バックテストと本番で、ここがズレます。

どこに付ける?

  • エントリー判定の直前(if文の前)

Printで出すべき項目

  • “条件に使っている値”を全部
    例:MA値、RSI、ATR、ボリンジャー上限、直近高値安値、トレンド判定フラグ など

  • 条件の結果を分解して「A=TRUE/B=FALSE/C=TRUE」みたいに出す

Printの形(超大事)

  • EntryCheck: A(spreadOK)=T B(timeOK)=T C(signal)=F ... => ENTER=NO

わかること

  • 本番ではインジ値が違う(データ不足、時間足違い、Symbol違い)

  • “バー確定”のロジックが本番で想定通り動いてない(毎ティック判定してる/逆に一度も判定されない)

次の打ち手

  • インジ値が0や異常値 → ヒストリ不足/別時間足参照ミス/シンボル違い

  • 条件のどれが落ちてるかが一瞬で分かるので、そこだけ集中的に直す


D. 「注文を出したのに通らない」原因ログ

どこに付ける?

  • OrderSend() の直前・直後

  • 失敗時は GetLastError() を必ず出す

Printで出すべき項目(直前)

  • シンボル、注文種別(BUY/SELL)、ロット、価格、SL、TP、スリッページ、Magic

  • 価格が正規化されてるか(Digits)

直後

  • 成功:チケット番号

  • 失敗:エラー番号、エラー内容(番号だけでもOK)

わかること

  • “エントリー条件は成立してるのに発注だけ拒否”を特定できる

  • エラー番号で原因の当たりが付く
    例:無効価格、無効なストップ、証拠金不足、取引禁止、など

次の打ち手

  • エラーが出た瞬間に「価格」「StopLevel」「証拠金」「スプレッド」を合わせて見る
    → どれが原因か切り分けできる


E. 「決済・TP更新が動いてない」原因ログ

どこに付ける?

  • ポジション探索(OrdersTotalループ)の中

  • 決済処理の直前・直後

  • OrderModifyの直前・直後(失敗時GetLastError)

Printで出すべき項目

  • いま見つけたポジション(チケット、種別、ロット、建値、現在損益、SL/TP)

  • 決済条件(達成してるか/してないか)

  • Modify/Closeの結果(成功/失敗とエラー)

わかること

  • そもそもEAが自分のポジションを見つけられてない(Magic違い、シンボル違い)

  • 決済条件が成立してない(計算がズレてる)

  • Modify/Closeが拒否されている(FreezeLevel、TradeContextBusyなど)


3) よくある「本番だけ動かない」をPrintで一発判定する例

パターン1:AutoTradingや許可設定で止まる

  • 症状:OnInitは出るが取引系ログが出ない/取引禁止ログが出る

  • Printで分かる:IsTradeAllowed=false、またはTradeAllowed=false

  • 解決:自動売買ON、EA設定で「ライブ取引許可」、口座側の取引制限確認

パターン2:スプレッドフィルタで常に弾かれる

  • 症状:EntryCheckが毎回「spreadOK=F」

  • 解決:閾値調整、取引時間帯調整、スプレッドの単位(points/pips)勘違い修正

パターン3:StopLevel/FreezeLevelでOrderModify/Sendが拒否

  • 症状:OrderSend/Modify失敗 + エラー、かつSL/TPが近い

  • 解決:最低距離以上に設定、価格をNormalize、指値/逆指値の位置見直し

パターン4:シンボル名違い・桁数違い

  • 症状:テストはXAUUSD、本番はGOLDなど。価格計算がズレる

  • 解決:Symbol吸収(あなたが以前やってたやつ)、Digits/Point前提の見直し

パターン5:ヒストリ不足でインジ値が0/成立しない

  • 症状:MA/ATRなどが0、または極端

  • 解決:起動時に必要本数チェック、足データのダウンロード待ち、別時間足参照の見直し


4) 初心者が迷わない「ログの書き方ルール」

  • ログに必ず タグを付ける
    例:[INIT], [TICK], [ENV], [ENTRY], [SEND], [CLOSE]

  • 1行で結論が分かる形にする
    例:[ENTRY] spreadOK=T timeOK=T signal=F => ENTER=NO

  • エラーは必ず番号を出す
    例:[SEND] FAILED err=130(これだけで相当進む)


5) ここまでやれば“原因は必ず見える”

あなたのEAが本番で動かないときは、だいたい次のどれかがログに出ます:

  • [TICK] が出ない → 動いてない/ティック来てない

  • [ENV] で return してる → 取引不可条件に引っかかってる

  • [ENTRY] で signal=F → 条件不成立(値が違う)

  • [SEND] FAILED err=xxx → 注文拒否(エラー番号が原因)

  • [CLOSE]/[MODIFY] FAILED err=xxx → 決済/更新が拒否