「バックテストでは動くのに本番で動かない」は、ほぼ必ず
“どこかの条件で処理が止まってる / 発注が拒否されてる / そもそもEAが走ってない” のどれかです。
Print をどこに付けるか → それで何が分かるか → 次の打ち手の順でまとめます。
0) まず大前提:Printの出る場所は2つ
-
エキスパートタブ:
Print()のログ -
操作履歴(口座履歴):実際に注文が通った/決済した結果(通らなければ基本出ない)
-
注文が通らない場合は「操作履歴」には何も出ないので、原因調査はエキスパートが本丸です。
-
1) Printを付ける目的は「どこで止まったか」を特定すること
EAの処理はざっくりこう進みます:
-
EAが起動しているか(OnInit/OnTickが呼ばれているか)
-
環境チェックで止まってないか(取引許可/スプレッド/時間帯など)
-
エントリー条件が満たされているか(テストと本番で値が違うことが多い)
-
注文を出したか(OrderSend呼んだか)
-
注文が通ったか(エラー番号は何か)
-
その後の管理(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 → 決済/更新が拒否