- 1 1. MQL5におけるEAアーキテクチャとは
- 2 2. EAアーキテクチャの全体構成
- 3 3. EAアーキテクチャの実装手順
- 4 4. なぜこの構造が必要なのか
- 5 5. EA設計の代表パターン
- 6 6. 他手法との比較
- 7 7. よくある失敗と注意点
- 8 8. 実務での使いどころ
- 9 9. FAQ(よくある質問)
- 10 10. まとめ
1. MQL5におけるEAアーキテクチャとは
【結論】
EAアーキテクチャとは「自動売買ロジックをどのような構造で設計・分割するか」を指す。
設計を理解していないと、バグ・再現性の欠如・運用破綻につながる。
【定義】
EA(Expert Advisor)アーキテクチャとは、MQL5で作成する自動売買プログラムを「データ取得・判断・注文・管理」といった機能単位に分解し、再現性と拡張性を担保するための設計構造である。
1.1 EAアーキテクチャの基本的な考え方
MQL5におけるEAは、単なる「売買ロジックの記述」ではなく、以下のような構造で動作する。
- 市場データ(価格・indicator)を取得
- 条件に基づいてシグナルを生成
- 注文を実行(execution)
- ポジションやリスクを管理
この一連の流れを「整理された構造」として設計するのがEAアーキテクチャである。
重要なポイントは次の通り。
- ロジックと実行処理を分離する
- 再利用可能な構造にする
- 実運用(スプレッド・スリッページ)を考慮する
この設計を行わない場合、以下の問題が発生しやすい。
- OnTickに全処理を書いて可読性が崩壊する
- 同じ条件で複数回エントリーしてしまう
- バックテストでは動くが実運用で崩れる
1.2 MQL5の基本構造(イベント駆動モデル)
MQL5のEAは「イベント駆動」で動作する。
つまり、特定のタイミング(イベント)で関数が呼ばれる仕組みである。
代表的なイベントは以下の3つ。
- OnInit:初期化処理(EA起動時に1回だけ実行)
- OnTick:価格更新時に実行(メイン処理)
- OnDeinit:終了処理(EA停止時)
最小構成の例は以下。
int OnInit()
{
// 初期化(インジケータ作成など)
return(INIT_SUCCEEDED);
}
void OnTick()
{
// 毎Tickで実行される
// シグナル判定 → 注文処理
}
void OnDeinit(const int reason)
{
// 後処理
}
この構造を理解していないと、
- 不要な処理を毎Tickで実行してしまう
- パフォーマンス低下
- ロジックの誤作動
といった問題が発生する。
特にOnTickは「毎回呼ばれる」ため、処理を最小限に設計することが重要である。
1.3 なぜEAアーキテクチャが重要なのか
EAアーキテクチャが重要な理由は、主に3つある。
① 再現性の確保
EAの最大の価値は「同じ条件で同じ動作をすること」である。
しかし、設計が曖昧だと以下のズレが発生する。
- バックテストとフォワードの乖離
- execution条件(slippage・spread)による差
- タイミング依存のバグ
構造化された設計により、このズレを最小化できる。
② バグの抑制
設計が整理されていない場合、
- 条件分岐が複雑化
- 状態管理が不明確
- デバッグ困難
といった問題が発生する。
特に初心者は「1つの関数に全て書く」傾向があり、これが最大の失敗要因となる。
③ 拡張性・実運用対応
EAは一度作って終わりではない。
- ロジック追加
- フィルター(spread / slippage)追加
- リスク制御強化
など、継続的な改善が必要になる。
アーキテクチャが適切であれば、
- 機能追加が容易
- 他EAへの流用が可能
- ポートフォリオ運用にも対応
となる。
逆に設計がない場合、後からの修正コストは指数的に増加する。
2. EAアーキテクチャの全体構成
【結論】
EAは「データ取得 → シグナル生成 → 注文実行 → リスク管理 → 状態管理」の5要素で構成する。
この分割ができれば、再現性・デバッグ性・拡張性が大幅に向上する。
2.1 基本コンポーネント一覧
EAは以下の5つのコンポーネントに分解して設計するのが基本である。
① データ取得(Market Data)
- 価格(Bid / Ask)
- 時系列データ(CopyRates)
- インジケータ(iMA, iRSIなど)
役割:判断に必要な入力データを取得する
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
注意点:
- 毎Tickで重いデータ取得を行うとパフォーマンス低下
- CopyBufferの呼びすぎは遅延の原因
② シグナル生成(Signal Logic)
- エントリー条件
- 決済条件
- フィルター(時間・トレンドなど)
役割:「売る・買う・何もしない」を決定する
bool isBuy = (ma_fast > ma_slow);
注意点:
- ロジックと注文処理を混ぜない
- シグナルは「状態」ではなく「判断」に限定する
③ 注文処理(Execution)
- OrderSend
- 注文条件(価格・ロット・SL/TP)
- executionタイミング
役割:実際に市場へ注文を出す
MqlTradeRequest request;
MqlTradeResult result;
// request設定 → OrderSend
重要ポイント:
- slippage(許容価格ズレ)を考慮
- 約定失敗(requote, off quotes)への対応
④ リスク管理(Risk Control)
- ロットサイズ(lot)
- ストップロス(SL)
- スプレッドフィルター(spread)
役割:損失を制御する
if(spread > max_spread) return;
注意点:
- spread未考慮は実運用で破綻しやすい
- 固定ロットはリスク管理として不十分
⑤ 状態管理(State Management)
- ポジション有無
- エントリー済フラグ
- 複数ポジション管理
役割:EAの現在状態を保持する
bool hasPosition = PositionSelect(_Symbol);
重要:
- 状態管理がないと「多重エントリー」になる
- 実運用では最重要コンポーネント
2.2 データフロー(処理の流れ)
EAは以下の流れで動作する。
- Tick発生(OnTick呼び出し)
- データ取得(価格・indicator)
- シグナル判定
- 条件を満たせば注文実行
- 状態更新
この流れをコードで整理すると以下のようになる。
void OnTick()
{
// 1. データ取得
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
// 2. シグナル生成
bool isBuySignal = CheckBuySignal();
// 3. 状態確認
bool hasPosition = PositionSelect(_Symbol);
// 4. 注文実行
if(isBuySignal && !hasPosition)
{
ExecuteBuy();
}
}
この「流れを崩さない」ことが最も重要である。
2.3 よくある構造ミス(初心者が詰まるポイント)
以下は典型的な失敗例。
① 全処理をOnTickに直書き
- 可読性が低下
- 修正時にバグ混入
② 状態管理がない
- 同じ条件で何度もエントリー
- ポジション爆発
③ データ取得とロジックが混在
- 再利用できない
- テスト困難
④ executionを軽視
- slippage未考慮
- 約定失敗でロジック崩壊
2.4 なぜこの分割が有効なのか
この5分割構造にすることで以下が実現できる。
- ロジック単体テストが可能
- デバッグが局所化される
- 機能追加が容易
- 他EAへ流用可能
特に重要なのは、
「シグナル」と「execution」を分離すること
である。
理由:
- シグナルは理想条件
- executionは現実条件(spread・slippage)
この2つを混ぜると、バックテストと実運用の乖離が発生する。
3. EAアーキテクチャの実装手順
【結論】
EAは「テンプレ構造を作る → 各機能を分離実装 → 実運用条件を追加」の順で構築する。
最初から完璧を目指さず、動く最小構成 → 改善が最も再現性が高い。
3.1 最短構築ステップ(テンプレ)
初心者は以下の順序で実装する。
- EAファイル作成(MetaEditor)
- OnInitで初期化
- OnTickに最小ロジックを書く
- 注文関数を作る(Buy/Sell)
- バックテストで確認
最小構成の流れ:
int OnInit()
{
return(INIT_SUCCEEDED);
}
void OnTick()
{
if(CheckBuySignal())
{
ExecuteBuy();
}
}
ここでは「まず動かす」ことが目的。
注意点:
- 初期段階ではリスク管理を簡略化してOK
- ただし、後で必ず追加する
3.2 実装テンプレ(構造分離)
次に、アーキテクチャとして重要な「分離」を行う。
推奨構造
- CheckSignal(判断)
- ExecuteOrder(注文)
- RiskControl(制御)
bool CheckBuySignal()
{
// シグナルのみ判定
return(true);
}
void ExecuteBuy()
{
// 注文処理のみ
}
void OnTick()
{
if(CheckBuySignal())
{
ExecuteBuy();
}
}
重要ポイント:
- 「判定」と「実行」を絶対に混ぜない
- シグナルは「true/false」で返す
理由:
- ロジック検証が容易になる
- execution依存のバグを分離できる
3.3 実務向け改善手順(必須)
実運用では以下を追加する。
① スプレッドフィルター
double spread = (Ask - Bid) / _Point;
if(spread > 20) return;
理由:
- spreadが広いと不利な価格で約定する
② ポジション制御(多重エントリー防止)
if(PositionSelect(_Symbol)) return;
理由:
- 同条件で連続エントリーを防ぐ
③ スリッページ考慮
注文時に許容価格ズレを設定。
ポイント:
- executionは理論通りに動かない
- slippageは必ず発生する
④ ロットサイズ管理
double lot = 0.1; // 仮(実務ではリスクベース)
注意:
- 固定ロットは長期運用で破綻リスクあり
- 将来的に「risk per trade」へ移行する
3.4 実装時によくある失敗
① いきなり複雑なロジックを書く
→ デバッグ不能になる
② OnTickに全て書く
→ 可読性崩壊・修正困難
③ 状態管理を後回しにする
→ 多重エントリー発生
④ バックテストのみで判断
→ 実運用で崩れる(execution差)
3.5 最小構成→実運用構成への進化
段階的に改善するのが最適。
ステップ1(最小)
- シグナル + 注文
ステップ2(中間)
- 状態管理追加
- spreadフィルター
ステップ3(実運用)
- リスク管理
- execution最適化
- ロジック分離
この順序を守ることで、
- 無駄な作り直しを防げる
- 検証精度が上がる
3.6 他手法との違い(軽い補足)
- 初心者:OnTick直書き → 短期は速いが破綻しやすい
- 本手法:分離設計 → 初期コストは高いが長期安定
4. なぜこの構造が必要なのか
【結論】
EAアーキテクチャが必要なのは、MQL5のEAが「毎Tick動く不確実な実行環境」で動作するからである。
ロジックを分離しないと、価格変動・約定差・状態ずれに耐えられず、バックテストと実運用が乖離しやすい。
4.1 MQL5のEAは毎回同じ条件で動くとは限らない
MQL5のEAは、OnTick が呼ばれるたびに処理される。
しかし、Tickは一定間隔では来ない。相場が静かな時間は少なく、指標発表時や急変時は非常に多くなる。
この性質により、EAには次の問題が発生しやすい。
- 同じロジックでも実行タイミングが毎回違う
- 条件判定の直後に価格が変わる
- 連続Tickで同じ条件が何度も成立する
- 約定前後で状態がずれる
つまり、EAは「静的なプログラム」ではなく、変動する市場環境に追従するプログラムである。
このため、単純に「条件が成立したら買う」と書くだけでは不十分になる。
たとえば、次のようなコードは初心者に多い。
void OnTick()
{
if(CheckBuySignal())
{
ExecuteBuy();
}
}
この形自体は間違いではないが、以下が不足しやすい。
- すでにポジションを持っているか
- spreadが広すぎないか
- 注文可能な状態か
- 同一バー内の重複エントリーを防げているか
そのため、実務では「シグナル判定」と「実行条件」を分ける必要がある。
4.2 市場では理論通りに約定しない
EAのロジックが正しくても、注文は理論通りには通らない場合がある。
主な原因は、executionまわりの不確実性である。
代表例は以下。
- spreadの拡大
- slippageの発生
- requote
- 約定拒否
- 市場クローズ
- volume条件不一致
たとえば、バックテストでは狭いspread前提で成立していた戦略でも、実運用ではコスト増で崩れることがある。
特に短期売買やスキャルピング寄りのロジックでは、この影響が大きい。
そのため、EAアーキテクチャでは次の分離が重要になる。
- シグナル:理論上の売買判断
- execution:実際に発注してよいかの確認
この分離をしないと、ロジックの良し悪しと約定環境の悪さが混ざってしまう。
結果として、「戦略が悪いのか」「執行条件が悪いのか」が判別できなくなる。
4.3 モジュール化しないと修正コストが急増する
EAは一度作ったら終わりではない。
実際には、以下のような改善が繰り返し発生する。
- フィルターを追加したい
- ロット計算を変えたい
- 損切り条件を調整したい
- 複数通貨対応にしたい
- ログ出力を増やしたい
このとき、全処理が OnTick に密集していると、1か所の修正が別の不具合を生みやすい。
典型例は次の通り。
- エントリー条件を修正したら決済条件まで壊れた
- spreadフィルター追加で既存ロジックの順序が崩れた
- ポジション判定の追加で多重エントリーが発生した
これを防ぐには、機能ごとに役割を分ける必要がある。
- データ取得関数
- シグナル判定関数
- 注文実行関数
- リスク管理関数
- 状態管理関数
この構造なら、どこに問題があるか切り分けやすい。
また、特定の関数だけ差し替えることもできる。
4.4 状態管理がないEAは実運用で崩れやすい
初心者が見落としやすいのが「状態管理」である。
状態管理とは、EAが今どの状態にあるかを把握する仕組みである。
代表的な状態は以下。
- ポジションなし
- 買いポジション保有中
- 売りポジション保有中
- 注文直後
- 決済待ち
- 同一バー内でエントリー済み
これを持たないEAは、相場が速い場面で同じ条件に何度も反応しやすい。
その結果、次のような問題が起きる。
- 同時に複数回エントリーする
- 決済前に逆方向へ新規注文する
- バックテストでは見えにくい重複発注が起きる
状態管理は、見た目には地味だが、実運用では中核である。
特に、複数ポジション・複数通貨・時間足またぎのロジックでは必須に近い。
4.5 なぜ最初から構造化したほうが有利なのか
「最初は簡単に作って、後で整理すればよい」と考える人も多い。
これは小規模な検証用EAなら一部正しいが、実務では不利になりやすい。
理由は次の通り。
- 動いたコードほど後で触りにくい
- 成果が出たロジックほど複雑化しやすい
- 後からの分離は、最初から分けるより手間が大きい
特に、売買ロジックに利益が出始めると、そのコードを中心に追加修正が積み重なる。
その状態で設計し直すと、既存の挙動を壊さずに再構成する必要があり、難易度が一気に上がる。
そのため、初心者でも最低限は次の方針を守ったほうがよい。
- 判定と発注を分ける
- 状態確認を入れる
- 実運用コスト(spread, slippage)を無視しない
この3点だけでも、EAの耐久性は大きく変わる。
5. EA設計の代表パターン
【結論】
EAの設計は「シンプル型 → モジュール型 → ステートマシン型」の順で進化させるのが最も効率的である。
実運用ではモジュール型以上がほぼ必須になる。
5.1 シンプル構造(初心者向け)
最も基本的な構造は、すべての処理を OnTick にまとめる方法である。
void OnTick()
{
double ma_fast = iMA(_Symbol, 0, 5, 0, MODE_SMA, PRICE_CLOSE, 0);
double ma_slow = iMA(_Symbol, 0, 20, 0, MODE_SMA, PRICE_CLOSE, 0);
if(ma_fast > ma_slow)
{
// Buy処理
}
}
特徴:
- 実装が最も簡単
- 学習コストが低い
- 短時間で動くものが作れる
デメリット:
- 可読性が急速に悪化する
- ロジック追加で破綻しやすい
- 状態管理が難しい
- 実運用に耐えにくい
よくある失敗:
- 条件が増えて if がネスト地獄になる
- 同じコードが複数箇所に分散する
- 多重エントリーが発生する
この構造は「検証用」または「超シンプル戦略」に限定するのが現実的である。
5.2 モジュール型(推奨構造)
シンプル構造を改善したものが「モジュール型」である。
機能ごとに処理を分離する。
bool CheckBuySignal()
{
return(true);
}
bool CanExecute()
{
double spread = (Ask - Bid) / _Point;
if(spread > 20) return(false);
if(PositionSelect(_Symbol)) return(false);
return(true);
}
void ExecuteBuy()
{
// OrderSend処理
}
void OnTick()
{
if(CheckBuySignal() && CanExecute())
{
ExecuteBuy();
}
}
特徴:
- ロジックが整理される
- デバッグしやすい
- 機能追加が容易
メリット:
- シグナルとexecutionを分離できる
- spread / slippageなど現実条件を組み込める
- 再利用性が高い
デメリット:
- 初期実装の手間が増える
- 設計意識が必要
実務評価:
- 最もバランスが良い
- 単体EA〜複数戦略まで対応可能
重要ポイント:
- CheckSignal(理論)
- CanExecute(現実条件)
- Execute(発注)
この3分割が基本となる。
5.3 ステートマシン型(中級者〜上級者)
状態遷移でEAを制御する構造。
例:
enum State
{
STATE_NONE,
STATE_ENTRY,
STATE_HOLD,
STATE_EXIT
};
State currentState = STATE_NONE;
void OnTick()
{
switch(currentState)
{
case STATE_NONE:
if(CheckBuySignal())
{
ExecuteBuy();
currentState = STATE_HOLD;
}
break;
case STATE_HOLD:
if(CheckExitSignal())
{
ExecuteSell();
currentState = STATE_NONE;
}
break;
}
}
特徴:
- 状態を明示的に管理
- ロジックの流れが可視化される
メリット:
- 多段階ロジックに強い
- 複数条件の整合性を保てる
- ポジション管理が安定する
デメリット:
- 実装難易度が高い
- 設計ミスで複雑化しやすい
向いているケース:
- 複数エントリー条件
- ナンピン・グリッド
- 複数ポジション制御
5.4 どの構造を選ぶべきか
結論としては以下。
- 学習段階 → シンプル構造
- 実運用 → モジュール型
- 高度戦略 → ステートマシン型
判断基準:
- ロジックが単純か
- ポジション数が1か複数か
- execution条件が複雑か
5.5 他手法との違い(軽い比較)
他の実装スタイルとの違い:
- スクリプト型(単発実行)
→ EAと異なり継続監視できない - インジケータ型
→ シグナルは出るが発注できない - EA(本記事の対象)
→ 自動実行+状態管理が可能
5.6 よくある設計ミス
- モジュール化せず巨大関数化
- 状態遷移を考えず条件追加
- executionを軽視
- ロジックと表示(Print等)が混在
特に注意:
「設計を後回しにすると、後で修正できなくなる」
6. 他手法との比較
【結論】
EAアーキテクチャは「シンプル型・モジュール型・ステートマシン型」で選択する。
実運用では、モジュール型以上でないとexecution(約定条件)やリスク管理に対応できない。
6.1 比較対象の整理
比較する設計パターンは以下の3つ。
- シンプル型:OnTickに直接記述
- モジュール型:機能ごとに分離
- ステートマシン型:状態遷移で制御
それぞれは「目的」と「適用範囲」が異なる。
6.2 比較表(全体像)
| 構造 | 難易度 | 拡張性 | バグ耐性 | 実務適性 | 向いている用途 |
|---|---|---|---|---|---|
| シンプル型 | 低 | 低 | 低 | △ | 学習・検証 |
| モジュール型 | 中 | 高 | 中 | ◎ | 単体EA・実運用 |
| ステートマシン型 | 高 | 高 | 高 | ◎ | 複雑戦略 |
重要ポイント:
- 実運用では「拡張性」と「バグ耐性」が最優先
- 難易度だけで選ぶと後で破綻する
6.3 シンプル型 vs モジュール型
違いの本質
- シンプル型:ロジックとexecutionが混在
- モジュール型:ロジックとexecutionが分離
この違いが最も重要である。
実務上の差
| 観点 | シンプル型 | モジュール型 |
|---|---|---|
| デバッグ | 困難 | 容易 |
| ロジック変更 | 影響大 | 局所修正 |
| spread対応 | 難しい | 容易 |
| slippage対応 | 難しい | 容易 |
結論:
- シンプル型は短期効率
- モジュール型は長期安定
6.4 モジュール型 vs ステートマシン型
違いの本質
- モジュール型:処理を分離
- ステートマシン型:状態を制御
実務上の差
| 観点 | モジュール型 | ステートマシン型 |
|---|---|---|
| 実装難易度 | 中 | 高 |
| 状態管理 | 簡易 | 厳密 |
| 多ポジション対応 | △ | ◎ |
| ロジック表現力 | 中 | 高 |
結論:
- 単純〜中程度のEA → モジュール型で十分
- 複雑ロジック → ステートマシン型が有利
6.5 実運用での最適選択
実務ベースでの推奨は以下。
- 単一通貨・単純戦略 → モジュール型
- 複数条件・分岐あり → モジュール型+状態管理
- グリッド・複数ポジション → ステートマシン型
判断基準:
- ポジションが1つか複数か
- エントリー条件が単一か複数か
- execution条件が厳しいか
6.6 よくある選択ミス
① シンプル型で実運用しようとする
→ spread・slippageで崩壊
② ステートマシンを過剰に使う
→ 設計過多でバグ増加
③ モジュール化が中途半端
→ 結局OnTick肥大化
6.7 他手法との位置づけ
EAアーキテクチャは、他の手法と以下の関係にある。
| 手法 | 特徴 | EAとの違い |
|---|---|---|
| インジケータ | シグナルのみ | 注文不可 |
| スクリプト | 単発実行 | 継続監視不可 |
| EA | 自動売買 | フル制御可能 |
つまり、
- EAは最も自由度が高い
- その分、設計(アーキテクチャ)が重要
7. よくある失敗と注意点
【結論】
EAが実運用で崩れる原因の多くは「設計不足」ではなく「基本ミスの積み重ね」である。
特に、状態管理・execution条件・過剰最適化の3点を外すと再現性が失われる。
7.1 ロジックをOnTickに詰め込みすぎる
最も多い失敗は、すべての処理を OnTick に直接書くことである。
void OnTick()
{
if(condition1 && condition2 && condition3)
{
// 注文処理
}
}
問題点:
- 条件が増えると可読性が崩壊
- バグの発見が困難
- 修正時に他ロジックへ影響
対策:
- CheckSignal関数に分離
- 条件ごとに関数化
- ロジックを「意味単位」で分ける
理由:
構造化することで「どこが壊れているか」を特定できるようになる。
7.2 状態管理がなく多重エントリーする
初心者が見落としやすいが、最も危険なミス。
if(CheckBuySignal())
{
ExecuteBuy();
}
このコードは、条件が成立する限り何度でも注文する。
結果:
- 同一条件で連続エントリー
- ポジションが急増
- 想定外のリスク拡大
対策:
if(CheckBuySignal() && !PositionSelect(_Symbol))
{
ExecuteBuy();
}
さらに厳密にするなら:
- 同一バーで1回制限
- フラグ管理(isEnteredなど)
理由:
EAは「状態を持つプログラム」であり、条件だけでは制御できない。
7.3 スプレッド・スリッページ未考慮
バックテストでは問題なく見えても、実運用で崩れる典型例。
// フィルターなし
ExecuteBuy();
問題:
- spread拡大時に不利な価格で約定
- slippageでエントリー位置がズレる
- 利益がコストで消える
対策:
double spread = (Ask - Bid) / _Point;
if(spread > maxSpread) return;
補足:
- スキャルピング系ほど影響が大きい
- executionは戦略の一部と考える
7.4 バックテスト結果を過信する
非常に多い誤解。
バックテストでは:
- spread固定
- slippageなし
- 約定成功前提
実運用では:
- spread変動
- 約定拒否
- execution遅延
結果:
- PF(プロフィットファクター)が崩れる
- DD(ドローダウン)が増加
対策:
- フォワードテスト必須
- execution条件を再現する
- 保守的なパラメータ設定
重要:
バックテストは「仮説検証」であり、結果保証ではない。
7.5 ロットサイズ管理が不適切
固定ロットのまま運用するケース。
double lot = 0.1;
問題:
- 資金増減に対応できない
- DD時に過剰リスク
- 長期運用で破綻しやすい
対策:
- リスクベースロット(risk per trade)
- 証拠金・残高に応じた調整
理由:
EAは継続運用が前提のため、資金管理が最重要になる。
7.6 条件の過剰最適化(オーバーフィッティング)
バックテスト結果を良くするために条件を増やしすぎる。
例:
- MA期間を細かく調整
- 特定期間に最適化
- 条件を追加しすぎる
問題:
- 過去データにのみ適合
- 未来で再現しない
対策:
- シンプルなロジック維持
- パラメータを少なくする
- 異なる期間で検証
重要:
「再現性 > 最適化精度」
7.7 execution失敗を考慮しない
注文は必ず成功するとは限らない。
問題例:
- OrderSendの戻り値を確認しない
- エラー処理なし
結果:
- 注文失敗に気づかない
- ロジックと実際の状態が乖離
対策:
- 戻り値チェック
- エラーハンドリング
7.8 ログ・検証不足
問題が起きても原因が追えないケース。
対策:
- Printでログ出力
- 条件成立ログを残す
- execution結果を記録
理由:
EAはブラックボックス化しやすいため、可視化が重要。
7.9 まとめ(重要ポイントの短文化)
- OnTick肥大化は設計崩壊の原因
- 状態管理がないと多重エントリーになる
- spread・slippageは必ず考慮する
- バックテストは参考値に過ぎない
- ロット管理は長期生存の核心
8. 実務での使いどころ
【結論】
EAアーキテクチャは「検証用」「単体運用」「複数戦略運用」で設計レベルを変えるべきである。
目的に応じて構造を選ばないと、過剰設計または設計不足で非効率になる。
8.1 検証用EA(プロトタイプ段階)
最もシンプルな用途は「ロジック検証」である。
特徴:
- 単一ロジック
- 短期間テスト
- バックテスト中心
推奨構造:
- シンプル構造 or 軽量モジュール型
void OnTick()
{
if(CheckBuySignal())
{
ExecuteBuy();
}
}
ポイント:
- 実装速度を優先
- 完璧な設計は不要
- 条件検証に集中
注意点:
- このまま実運用に移行しない
- execution(spread / slippage)は後で必ず追加
8.2 単体EAの実運用
最も一般的な用途。
特徴:
- 単一通貨(例:EURUSD)
- 1戦略
- 継続運用
推奨構造:
- モジュール型(必須)
void OnTick()
{
if(CheckSignal() && CanExecute())
{
ExecuteOrder();
}
}
追加すべき要素:
- spreadフィルター
- slippage考慮
- ロット管理(riskベース)
- 状態管理
重要ポイント:
- executionは戦略の一部
- ロジック単体では利益は出ない
失敗例:
- バックテスト結果だけで投入
- 固定ロット運用
- 状態管理なし
8.3 複数通貨・ポートフォリオ運用
より高度な運用。
特徴:
- 複数シンボル(EURUSD / USDJPYなど)
- 複数ロジック
- リスク分散
推奨構造:
- モジュール型 + 状態管理強化
- 必要に応じてステートマシン型
追加要素:
- シンボルごとの状態管理
- ポジション総量制御
- 相関(correlation)管理
重要:
- 単体EAより設計の重要性が高い
- リスク管理が最優先
8.4 高度戦略(グリッド・ナンピン・複数ポジション)
難易度が高い領域。
特徴:
- 同時に複数ポジション
- エントリー段階が複数
- 状態遷移が複雑
推奨構造:
- ステートマシン型(ほぼ必須)
理由:
- 状態が複雑すぎてif文では管理不能
- ポジションの整合性が重要
典型的な状態:
- 初回エントリー
- 追加エントリー
- 平均価格管理
- 全決済
注意点:
- 設計ミス=即破綻リスク
- テスト環境必須
8.5 VPS・実運用環境でのポイント
EAは環境にも依存する。
重要要素:
- VPS(低遅延)
- 安定した通信
- MT5ログ監視
影響する要素:
- execution速度
- slippage
- 約定成功率
注意:
- ローカルとVPSで挙動が変わることがある
- ログ分析(エラー・約定)必須
8.6 実務での設計優先順位
実運用で重要な順序は以下。
- リスク管理(最優先)
- execution条件(spread / slippage)
- 状態管理
- ロジック精度
初心者がやりがちな誤り:
- ロジック精度ばかり追う
- executionとリスクを軽視
結果:
- バックテストは良いが実運用で崩壊
8.7 戦略レベルでの設計思考
EAは「コード」ではなく「システム」として設計する。
重要視点:
- どの場面で取引しないか
- どの条件で停止するか
- DD(ドローダウン)許容範囲
補足:
- フィルター(時間・ニュース)
- ボラティリティ制御(ATRなど)
8.8 まとめ(短文化)
- 検証段階 → シンプル構造
- 実運用 → モジュール型必須
- 高度戦略 → ステートマシン型
- executionとリスクが最重要
9. FAQ(よくある質問)
【結論】
EAアーキテクチャは「最初に最低限の設計を入れる」ことで、その後の開発効率と再現性が大きく変わる。
迷った場合は「モジュール型」を基準に考えると失敗しにくい。
9.1 EAアーキテクチャは初心者でも必要?
必要。
最初から完璧な設計は不要だが、「シグナルと注文を分離する」だけでも大きく安定する。
設計なしで作ると、後から修正コストが急増する。
9.2 OnTickだけでEAを作っても問題ない?
小規模な検証用なら問題ない。
ただし実運用では、状態管理・spread・slippage未対応になりやすく、破綻リスクが高い。
実運用に移行する段階で必ず分離設計にする。
9.3 モジュール化はどこから始めるべき?
最低限、以下の3分割から始める。
- シグナル判定(CheckSignal)
- 実行条件(CanExecute)
- 注文処理(ExecuteOrder)
この分離だけで、ほとんどのバグを回避できる。
9.4 ステートマシンは必須?
必須ではない。
単一ポジション・単純戦略ならモジュール型で十分。
必要になるケース:
- 複数ポジション管理
- ナンピン・グリッド
- 複数段階のエントリー
9.5 スプレッド(spread)はどの程度考慮すべき?
必須。
特に短期売買では、spreadが利益を直接削る。
対策:
- エントリー前に上限チェック
- 通貨ペアごとに閾値調整
9.6 スリッページ(slippage)はどこまで影響する?
無視できない。
特に以下で影響が大きい。
- 指標発表時
- 流動性が低い時間帯
- 急変相場
executionは理論ではなく「実環境」で評価する必要がある。
9.7 バックテスト結果はどこまで信用できる?
完全には信用できない。
バックテストは以下が簡略化されている。
- slippageなし
- 約定100%前提
- spread固定
そのため、必ずフォワードテストで確認する。
9.8 最適なEAアーキテクチャはどれ?
結論:
- 初心者 → シンプル構造(短期)
- 実運用 → モジュール型(基本)
- 高度戦略 → ステートマシン型
迷った場合は「モジュール型」を選べば問題ない。
9.9 ロットサイズは固定でもよい?
短期検証なら問題ない。
実運用ではリスクベース(資金割合)にするべき。
理由:
- DD耐性が変わる
- 長期運用での生存率に直結
9.10 EAで最も重要な要素は何?
優先順位は以下。
- リスク管理
- execution条件(spread / slippage)
- 状態管理
- ロジック精度
ロジックだけでは利益は出ない。
10. まとめ
【結論】
EAアーキテクチャは「再現性・安定性・拡張性」を担保するための設計であり、実運用では必須である。
特に「シグナル・execution・リスク管理の分離」が最重要ポイントになる。
10.1 本記事の要点整理
- EAは「データ取得 → 判断 → 実行 → 管理」で構成する
- OnTickに全て書くと設計が破綻する
- シグナルとexecutionは必ず分離する
- 状態管理がないと多重エントリーが発生する
- spread・slippageは必ず考慮する
- バックテストは参考であり、実運用とは異なる
10.2 実務での最適アプローチ
実務では以下の流れが最も効率的。
- 最小構成で動作確認
- モジュール化して分離
- リスク管理とexecution条件を追加
- フォワードテストで検証
この順序により、
- 開発効率
- 再現性
- 安定性
を同時に高めることができる。
10.3 設計レベル別の指針
- 検証段階 → シンプル構造
- 実運用 → モジュール型必須
- 高度戦略 → ステートマシン型
無理に高度な設計を使う必要はないが、
実運用でシンプル構造を使い続けるのはリスクが高い。
10.4 最も重要な考え方
EAは「コード」ではなく「システム」である。
重要なのは以下。
- どの条件で取引しないか
- どの条件で停止するか
- どの程度の損失を許容するか
これらを含めて設計することで、
初めて実運用に耐えるEAになる。
10.5 次のステップ
次に取り組むべき内容:
- モジュール型テンプレの実装
- ロットサイズ計算(risk per trade)
- spreadフィルター設計
- フォワードテスト環境構築
これらを実装することで、
EAは「検証ツール」から「運用システム」へ進化する。