1. MQL5のEA基本構造とは何か
MQL5で自動売買プログラム(EA:Expert Advisor)を作る場合、まず理解すべきなのがEAの基本構造(EA Basic Structure)です。
EAは通常のプログラムのように「最初から最後まで順番に実行される処理」ではなく、イベント駆動型プログラムとして動作します。
イベント駆動型とは、特定の出来事(イベント)が発生したときに処理が実行される仕組みです。
MQL5のEAでは主に次のイベントが重要になります。
- EAが起動したとき
- 価格が更新されたとき
- EAが終了するとき
このイベントごとに処理を書くことで、EAの動作が構成されます。
そのためMQL5のEAは、基本的に次の3つの関数(イベントハンドラ)で構成されます。
| 関数 | 役割 |
|---|---|
| OnInit() | EA起動時の初期化処理 |
| OnTick() | 価格更新時のメイン処理 |
| OnDeinit() | EA終了時の後処理 |
この3つを理解することで、すべてのEAの基礎構造を理解できると言っても過言ではありません。
1.1 EA(Expert Advisor)とは
EA(Expert Advisor)とは、MetaTraderで自動売買を行うプログラムです。
あらかじめプログラムされた条件に従い、売買判断から注文実行までを自動で行います。
一般的なEAの処理は次の流れになります。
価格データ取得
↓
テクニカル指標計算
↓
売買条件判定
↓
注文実行
↓
ポジション管理
例えば以下のようなロジックがEAに組み込まれます。
- 移動平均線がクロスしたら買い
- RSIが30以下なら買い
- ATRが一定以上ならトレード
EAはこのようなロジックを24時間自動で実行できるため、裁量トレードでは難しいルールの厳格な運用が可能になります。
1.2 EAが動作する仕組み
初心者が最も誤解しやすいのは、EAの処理の動き方です。
多くのプログラミング言語では次のような「ループ処理」でプログラムが動きます。
while(true){
処理
}
しかし、MQL5のEAはこのような無限ループでは動きません。
代わりにTickイベントという仕組みで動作します。
Tick(ティック)
→ 市場価格が更新された瞬間のデータ
価格が更新されるたびに、次の関数が自動的に呼び出されます。
void OnTick()
{
// 売買ロジック
}
つまりEAは
価格更新(Tick)
↓
OnTick() 実行
↓
売買判断
という流れで動きます。
重要ポイント
EAは「常に動いている」のではなく
Tickが来たときだけ処理される
という構造になっています。
1.3 EAとインジケーターの違い
MetaTraderには主に次の3種類のプログラムがあります。
| 種類 | 目的 |
|---|---|
| EA(Expert Advisor) | 自動売買 |
| Indicator(インジケーター) | 分析表示 |
| Script(スクリプト) | 単発処理 |
それぞれの特徴は次の通りです。
EA
- 自動売買を行う
- 注文を出せる
- OnTickイベントで動作
インジケーター
- チャート分析用
- 売買は行わない
- OnCalculateで動作
スクリプト
- 一度だけ実行
- 例:全ポジション決済
初心者がよく混乱するポイントは次です。
インジケーターは注文できない
売買を行う場合は必ずEAを使用する必要があります。
初心者がつまずきやすいポイント
EA開発の初期段階では、次のミスがよく発生します。
① EAは常にループしていると思ってしまう
誤った例
while(true)
{
// 処理
}
このコードを書くと、MT5がフリーズする可能性があります。
EAはOnTickイベントで処理を書くのが基本です。
② EAとインジケーターの役割を混同する
よくある例
- インジケーターで売買しようとする
- EAにチャート描画を書きすぎる
基本ルール
分析 → インジケーター
売買 → EA
③ EAをチャートにセットしていない
EAはチャートにドラッグして初めて動作します。
また、次の設定も必要です。
- 自動売買ボタンON
- EAの設定許可
環境によっては、これらの設定が無効だとEAは動作しません。
2. MQL5のEA基本構造(最小テンプレート)
MQL5でEAを作成すると、MetaEditorは自動的に基本テンプレート(EAの骨組み)を生成します。
このテンプレートには、EAを動作させるために必要なイベント関数(イベントハンドラ)が最初から含まれています。
典型的なEAの最小構造は次のようになります。
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
}
この3つの関数が、EAの基本構造です。
| 関数 | 実行タイミング | 用途 |
|---|---|---|
| OnInit() | EA起動時 | 初期化処理 |
| OnTick() | 価格更新時 | 売買ロジック |
| OnDeinit() | EA終了時 | 後処理 |
この構造を理解すると、すべてのEAの仕組みが見えるようになります。
2.1 OnInit():EA起動時の初期化処理
OnInit() は、EAがチャートにセットされた瞬間に1回だけ実行される関数です。
主に次のような処理を書きます。
- インジケーターの作成
- 変数の初期化
- パラメータチェック
- ログ出力
例
int OnInit()
{
Print("EA started");
return(INIT_SUCCEEDED);
}
INIT_SUCCEEDED は
初期化成功を意味する定数です。
もし初期化に失敗した場合は、次のようにします。
return(INIT_FAILED);
これを返すと、EAは停止します。
OnInit()でよく行う処理
実務では次の処理を書くことが多いです。
インジケーターハンドル作成
int maHandle;
int OnInit()
{
maHandle = iMA(Symbol(), PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE);
if(maHandle == INVALID_HANDLE)
{
Print("Indicator creation failed");
return(INIT_FAILED);
}
return(INIT_SUCCEEDED);
}
ここで重要なのがハンドルという概念です。
ハンドル
→ インジケーターを操作するためのID
このIDを使って、あとでデータを取得します。
2.2 OnTick():EAのメイン処理
OnTick() は、価格が更新されるたびに実行される関数です。
EAのメインロジックは、すべてここに書きます。
例えば以下のような処理です。
- テクニカル指標取得
- 売買条件判定
- 注文実行
- ポジション管理
例
void OnTick()
{
Print("New Tick: ", Symbol());
}
このコードは、Tickが発生するたびにログを出力します。
実際のEAでは次のような流れになります。
Tick発生
↓
指標計算
↓
売買条件チェック
↓
注文
簡単な例
void OnTick()
{
double price = SymbolInfoDouble(Symbol(), SYMBOL_BID);
if(price > 1.2000)
{
Print("Condition met");
}
}
ここでは
- 現在価格取得
- 条件判定
を行っています。
2.3 OnDeinit():EA終了時の処理
OnDeinit() は、EAが終了するときに呼ばれる関数です。
終了する理由には次のようなものがあります。
- EAを削除した
- MT5を終了した
- チャート変更
- コンパイル
例
void OnDeinit(const int reason)
{
Print("EA stopped");
}
reason には、終了理由が入ります。
例えば
REASON_REMOVE
REASON_CHARTCHANGE
REASON_RECOMPILE
などです。
OnDeinit()で行う処理
一般的には次の処理を書きます。
- インジケーター解放
- メモリ解放
- ログ出力
例
void OnDeinit(const int reason)
{
IndicatorRelease(maHandle);
}
これを行わないと、環境によってはリソースが残る可能性があります。
初心者がよくやる失敗
① OnTick()に重い処理を書く
Tickは1秒に数回〜数十回発生します。
そのため、次のようなコードは危険です。
for(int i=0;i<1000000;i++)
{
}
Tick処理が遅くなると
- EAが遅延する
- 注文タイミングがずれる
可能性があります。
② OnInit()でエラー処理を書かない
インジケーター作成は失敗することがあります。
例えば
- 銘柄データ不足
- パラメータエラー
そのため、必ず次のチェックを行います。
if(handle == INVALID_HANDLE)
③ OnDeinit()を空のままにする
小さなEAでは問題ありませんが、
大きなEAではリソース管理が重要になります。
特に
- IndicatorRelease
- FileClose
などを忘れるケースが多いです。
3. EAの基本テンプレートコード(実務で使う構造)
前章では、MQL5のEAが次の3つのイベント関数で構成されることを説明しました。
OnInit()(初期化)OnTick()(メイン処理)OnDeinit()(終了処理)
しかし、実務のEAではこれだけでは不十分です。
保守性・拡張性を考えると、ロジックを関数に分割したテンプレート構造にするのが一般的です。
ここでは、実際のEA開発で使いやすい基本テンプレートを紹介します。
3.1 実務で使うEA基本テンプレート
まずはシンプルで実用的な構造を示します。
//+------------------------------------------------------------------+
//| Expert Advisor Template |
//+------------------------------------------------------------------+
// パラメータ
input double Lots = 0.1;
// 初期化
int OnInit()
{
Print("EA initialized");
return(INIT_SUCCEEDED);
}
// Tick処理
void OnTick()
{
CheckTradeSignal();
}
// 終了処理
void OnDeinit(const int reason)
{
Print("EA stopped");
}
// 売買ロジック
void CheckTradeSignal()
{
double price = SymbolInfoDouble(Symbol(), SYMBOL_BID);
if(price > 1.2000)
{
Print("Buy condition detected");
}
}
この構造では、OnTick() に直接ロジックを書かず、
専用関数に処理を分離しています。
OnTick()
↓
CheckTradeSignal()
この方法にすると
- コードが読みやすくなる
- ロジックを追加しやすい
- バグを減らせる
というメリットがあります。
3.2 EA構造を整理した処理フロー
実務のEAは、次のような構造に整理すると管理しやすくなります。
OnInit()
↓
環境初期化
↓
OnTick()
↓
市場データ取得
↓
シグナル判定
↓
注文処理
↓
ポジション管理
これをコード構造にすると、次のようになります。
void OnTick()
{
UpdateMarketData();
CheckSignal();
ExecuteTrade();
ManagePosition();
}
それぞれの役割は以下の通りです。
| 関数 | 役割 |
|---|---|
| UpdateMarketData() | 価格・指標取得 |
| CheckSignal() | 売買条件判定 |
| ExecuteTrade() | 注文処理 |
| ManagePosition() | ポジション管理 |
このように構造化すると、EAの規模が大きくなっても管理しやすくなります。
3.3 EAパラメータ(input)の基本
EAでは、ユーザーが設定できるパラメータを用意するのが一般的です。
MQL5では input キーワードを使用します。
input double Lots = 0.1;
input int StopLoss = 100;
input int TakeProfit = 200;
このように定義すると、EAの設定画面に表示されます。
例
Lots 0.1
StopLoss 100
TakeProfit 200
これにより
- ロットサイズ
- 損切り
- 利確
などをコードを変更せずに調整できます。
EA開発では、次のようなパラメータがよく使われます。
ロットサイズ
ストップロス
テイクプロフィット
インジケーター期間
スプレッド制限
3.4 EAのフォルダ構造(保存場所)
EAはMetaTraderの特定フォルダに保存されます。
通常の保存場所
MQL5
└ Experts
└ YourEA.mq5
MetaEditorでEAを作成すると、自動的にこの場所に保存されます。
コンパイルすると、次のファイルが生成されます。
YourEA.mq5 ソースコード
YourEA.ex5 実行ファイル
MT5が実行するのは .ex5ファイルです。
初心者がつまずきやすいポイント
① OnTick()にすべて書いてしまう
初心者は次のようなコードを書きがちです。
void OnTick()
{
// 数百行のロジック
}
これは非常に危険な設計です。
理由
- バグが見つけにくい
- 修正が難しい
- 拡張できない
対策
ロジックは関数分割する
② inputパラメータを使わない
初心者のEAは次のようになりがちです。
double lot = 0.1;
これでは、設定を変更するたびに再コンパイルが必要になります。
正しい書き方
input double Lots = 0.1;
③ Symbol()を固定しない
複数通貨対応EAでは、必ず次を使います。
Symbol()
誤った例
"EURUSD"
これを書くと、EAが特定通貨専用になります。
4. EAのイベントモデル(Tick・Timer・Tradeイベント)
MQL5のEAは、イベント駆動型プログラムとして動作します。
これは、特定の出来事(イベント)が発生したときに、対応する関数が自動的に実行される仕組みです。
初心者が最初に理解するのは OnTick() ですが、実際のEAではそれ以外にも複数のイベントが存在します。
代表的なイベントは次の通りです。
| イベント関数 | 発生タイミング | 用途 |
|---|---|---|
| OnTick() | 価格更新 | 売買ロジック |
| OnTimer() | 指定時間ごと | 定期処理 |
| OnTrade() | 取引変化 | 注文監視 |
| OnTradeTransaction() | 取引イベント | 詳細監視 |
EAの設計では、これらのイベントを適切に使い分けることで、より安定した自動売買システムを構築できます。
4.1 Tickイベント(OnTick)
OnTick() は、価格が更新されるたびに実行されるイベント関数です。
EAの中心となる処理は、通常ここに書きます。
例
void OnTick()
{
Print("Tick received");
}
Tickは、市場の価格更新単位です。
そのため、通貨ペアや市場の状況によって発生頻度が異なります。
例
| 市場状況 | Tick頻度 |
|---|---|
| 流動性が高い時間 | 非常に多い |
| 夜間・休日 | 少ない |
重要な点は次です。
Tickは一定間隔ではない
つまり
Tick
Tick
Tick
(数秒空く)
Tick
のような不規則な発生になります。
そのため、次のような処理には向きません。
- 1秒ごとの処理
- 定期チェック
その場合は OnTimer() を使用します。
4.2 Timerイベント(OnTimer)
OnTimer() は、一定時間ごとに実行されるイベントです。
使用するには、EventSetTimer() を設定します。
例
int OnInit()
{
EventSetTimer(60);
return(INIT_SUCCEEDED);
}
この設定では
60秒ごと
に OnTimer() が呼ばれます。
Timer処理
void OnTimer()
{
Print("Timer event");
}
Timerイベントは次の用途でよく使われます。
- 定期ログ出力
- 市場状態チェック
- EA状態監視
EA終了時には、Timerを解除する必要があります。
void OnDeinit(const int reason)
{
EventKillTimer();
}
環境によってはTimerが残る可能性があるため、
必ず解除処理を書くことが推奨されます。
4.3 Tradeイベント(OnTrade)
OnTrade() は、取引状態が変化したときに呼ばれるイベントです。
例
- 注文成立
- ポジション変更
- 決済
例
void OnTrade()
{
Print("Trade event occurred");
}
このイベントを使うと
注文が約定した瞬間
を検知できます。
用途
- 約定確認
- ポジション更新
- ログ管理
ただし、詳細な情報が必要な場合は
OnTradeTransaction() を使います。
4.4 TradeTransactionイベント(OnTradeTransaction)
OnTradeTransaction() は、取引の詳細イベントを取得できる関数です。
例
void OnTradeTransaction(
const MqlTradeTransaction& trans,
const MqlTradeRequest& request,
const MqlTradeResult& result
)
{
Print("Trade transaction detected");
}
このイベントでは、次の情報を取得できます。
- 注文ID
- 約定価格
- ロット
- 取引タイプ
EAのログ管理や、高精度のポジション管理に使われます。
初心者がつまずきやすいポイント
① Tickで時間処理を書いてしまう
初心者は次のようなコードを書きがちです。
if(TimeCurrent() - last_time > 60)
{
処理
}
Tickは不規則なので、
正確な時間処理には向きません。
解決策
Timerイベントを使用
② Timerを解除しない
Timerを設定した場合は必ず次を書く必要があります。
EventKillTimer();
解除しないと、環境によってはTimerイベントが残る可能性があります。
③ OnTradeとOnTickを混同する
初心者がよく混乱するポイントです。
| 関数 | 役割 |
|---|---|
| OnTick | 価格更新 |
| OnTrade | 取引更新 |
売買ロジックは
OnTick
約定監視は
OnTrade
で行います。
5. EAで注文を出す基本処理(CTrade / OrderSend)
EAの最も重要な機能は、自動で注文を出すことです。
MQL5では、注文処理の方法として主に次の2つがあります。
| 方法 | 特徴 |
|---|---|
| CTradeクラス | シンプルで初心者向け |
| OrderSend() | 低レベルAPI(詳細制御可能) |
現在のMQL5では、CTradeクラスを使う方法が一般的です。
そのため、初心者はまず CTradeベースの注文方法を理解することが重要です。
5.1 CTradeクラスを使った注文
CTradeは、MQL5標準ライブラリのトレードクラスです。
売買注文を簡単に実装できます。
まずヘッダを読み込みます。
#include <Trade/Trade.mqh>
次にオブジェクトを作成します。
CTrade trade;
これで注文を出せるようになります。
成行買い注文(Buy)
#include <Trade/Trade.mqh>
CTrade trade;
void OnTick()
{
double lot = 0.1;
trade.Buy(lot);
}
このコードは
0.1ロットの買い注文
を実行します。
実際には次の情報が自動的に使われます。
- 現在価格
- 現在銘柄
- スリッページ設定
成行売り注文(Sell)
trade.Sell(0.1);
5.2 ストップロスとテイクプロフィット
注文時には、損切り(SL)と利確(TP)を設定できます。
例
double sl = 1.1900;
double tp = 1.2100;
trade.Buy(0.1, NULL, 0, sl, tp);
引数の意味
| 引数 | 意味 |
|---|---|
| lot | ロット |
| symbol | 銘柄 |
| price | 価格 |
| sl | ストップロス |
| tp | テイクプロフィット |
通常は
NULL
を指定すると
現在チャートの通貨ペア
が使用されます。
5.3 注文結果の確認
注文は、必ず成功するとは限りません。
そのため、結果を確認する必要があります。
if(trade.Buy(0.1))
{
Print("Buy order success");
}
else
{
Print("Buy order failed");
}
さらに詳細な情報は次で取得できます。
trade.ResultRetcode();
例
Print(trade.ResultRetcode());
5.4 OrderSend()(低レベル注文)
より細かい制御を行う場合は OrderSend() を使います。
例
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
request.action = TRADE_ACTION_DEAL;
request.symbol = Symbol();
request.volume = 0.1;
request.type = ORDER_TYPE_BUY;
OrderSend(request, result);
この方法は
- 注文条件
- 価格
- スリッページ
などを細かく制御できます。
ただしコード量が増えるため、
通常のEAでは CTradeが推奨されます。
初心者がつまずきやすいポイント
① 自動売買ボタンをONにしていない
EAが注文できない原因の多くはこれです。
確認ポイント
MT5上部
自動売買ボタン
これがOFFだと、EAは注文できません。
② スプレッド制限を考えていない
スプレッドが広いと
- 不利な価格で約定
- ロジック崩壊
する可能性があります。
対策例
double spread = SymbolInfoInteger(Symbol(), SYMBOL_SPREAD);
if(spread > 30)
{
return;
}
③ 連続注文してしまう
Tickごとに注文すると、次のようになります。
Tick
注文
Tick
注文
Tick
注文
その結果
大量ポジション
が発生します。
対策
ポジションチェック
例
if(PositionsTotal() == 0)
{
trade.Buy(0.1);
}
6. EA開発でよく発生するエラーと対処法
MQL5でEAを開発する際、初心者が最も時間を消費するのがエラーや想定外の動作の原因調査です。
特に次の3つは、EA開発で非常によく発生します。
| エラー種別 | 発生原因 |
|---|---|
| 価格取得エラー | データ取得方法の誤り |
| 配列エラー | インデックス管理ミス |
| 注文エラー | 取引条件・環境設定 |
これらを理解しておくと、デバッグ時間を大きく短縮できます。
6.1 価格取得エラー(SymbolInfoDouble)
EAでは、現在価格を取得する処理を頻繁に使います。
MQL5では SymbolInfoDouble() を使用します。
例
double bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
double ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
意味
| 変数 | 意味 |
|---|---|
| bid | 売値(売る価格) |
| ask | 買値(買う価格) |
売買の基本ルール
買い注文 → Ask価格
売り注文 → Bid価格
よくあるミス
初心者がよく書く誤ったコード
double price = Bid;
これは MQL4の書き方です。
MQL5では、SymbolInfoDouble() を使うのが基本です。
安全な書き方
double bid;
if(SymbolInfoDouble(Symbol(), SYMBOL_BID, bid))
{
Print(bid);
}
このように書くと、環境によって取得できない場合でもエラーを防げます。
6.2 配列エラー(Array out of range)
EA開発で非常に多いエラーが
array out of range
です。
これは
配列の範囲外アクセス
を意味します。
例
double arr[10];
arr[10] = 1;
このコードはエラーになります。
理由
配列の最大インデックス
0〜9
だからです。
よくある原因
EA開発では、インジケーターデータ取得でよく発生します。
例
CopyBuffer(handle, 0, 0, 10, buffer);
取得したデータ数を確認せずに
buffer[10]
にアクセスするとエラーになります。
安全な書き方
int copied = CopyBuffer(handle,0,0,10,buffer);
if(copied > 0)
{
Print(buffer[0]);
}
このように、取得成功を確認してから使用します。
6.3 注文エラー(Trade Retcode)
EAで注文を出しても、必ず成功するとは限りません。
ブローカーや市場状況によって、注文が拒否されることがあります。
注文結果は次で確認できます。
trade.ResultRetcode();
代表的なエラー
| コード | 意味 |
|---|---|
| 10004 | TRADE_RETCODE_REQUOTE |
| 10006 | TRADE_RETCODE_REJECT |
| 10019 | TRADE_RETCODE_NO_MONEY |
エラー確認の例
if(!trade.Buy(0.1))
{
Print("Error code: ", trade.ResultRetcode());
}
このログは、EAデバッグの重要情報になります。
初心者がつまずきやすいポイント
① Printログを使わない
EAはバックグラウンドで動くため、
ログを出さないと原因が分かりません。
例
Print("Signal detected");
ログは
MT5 → Expertsタブ
で確認できます。
② バックテストとリアル環境の違い
バックテストでは問題なくても、
リアル環境では失敗することがあります。
理由
- スプレッド変動
- スリッページ
- 約定遅延
そのため、EAは必ず
デモ口座
で検証することが重要です。
③ 配列サイズを固定してしまう
インジケーターデータは動的です。
そのため、配列は通常
ArrayResize()
を使います。
例
ArrayResize(buffer,100);
デバッグの基本手順
EAの問題を調査する基本手順は次です。
1 Printログを追加
2 エラーコード確認
3 配列サイズ確認
4 価格取得確認
この順序で調べると、多くの問題を解決できます。
7. EA開発で重要な設計ポイント(再現性・安全性・保守性)
MQL5でEAを作成する際、単に「動くコード」を書くだけでは不十分です。
長期運用を前提とした自動売買では、次の3つの設計要素が非常に重要になります。
| 設計要素 | 目的 |
|---|---|
| 再現性 | バックテストと実運用の差を減らす |
| 安全性 | 予期しない注文や暴走を防ぐ |
| 保守性 | EAの改良・修正を容易にする |
これらを考慮した設計を行うことで、EAは安定して長期間運用できるプログラムになります。
7.1 再現性を高める設計
EA開発では、バックテスト結果と実運用の差が問題になることがあります。
原因の多くは、次のような設計ミスです。
- Tick依存ロジック
- スプレッド未考慮
- 実行タイミングの不一致
例えば、以下のコードは注意が必要です。
if(SymbolInfoDouble(Symbol(),SYMBOL_BID) > ma)
{
trade.Buy(0.1);
}
この場合
- Tick更新タイミング
- 指標更新タイミング
によって結果が変わる可能性があります。
対策として、確定バー(確定足)でロジックを動かす設計がよく使われます。
例
static datetime last_bar = 0;
datetime current_bar = iTime(Symbol(), PERIOD_CURRENT, 0);
if(current_bar != last_bar)
{
last_bar = current_bar;
// 売買ロジック
}
この方法により、1本の足につき1回だけロジックを実行できます。
メリット
- バックテスト再現性向上
- 過剰注文防止
- ロジック安定化
7.2 安全性を高める設計
EAでは、想定外の注文を防ぐための安全チェックが重要です。
代表的なチェック項目は次の通りです。
スプレッド制限
ポジション数制限
最大ロット制限
取引時間制限
例えばスプレッドチェック。
double spread = SymbolInfoInteger(Symbol(),SYMBOL_SPREAD);
if(spread > 30)
{
return;
}
これにより
スプレッド拡大時の取引
を防げます。
ポジション制限
連続注文を防ぐ例。
if(PositionsTotal() > 0)
{
return;
}
このチェックがない場合、Tickごとに注文される可能性があります。
取引時間制限
市場流動性が低い時間帯を避ける設計もよく使われます。
例
int hour = TimeHour(TimeCurrent());
if(hour < 7 || hour > 22)
{
return;
}
環境や戦略によって、最適時間は異なる可能性があります。
7.3 保守性を高めるコード構造
EAが複雑になるほど、コード構造の整理が重要になります。
典型的なEA構造は次のようになります。
OnInit
OnTick
├ 市場データ取得
├ シグナル判定
├ 注文処理
└ ポジション管理
これを関数で整理すると、次のようになります。
void OnTick()
{
UpdateMarketData();
CheckSignal();
ExecuteTrade();
ManagePosition();
}
メリット
- 可読性向上
- バグ調査容易
- 機能追加が簡単
EAが数千行になる場合、この構造がないと管理が非常に困難になります。
7.4 パラメータ管理
EAでは、設定を柔軟に変更できるようにする必要があります。
MQL5では input パラメータを使います。
例
input double Lots = 0.1;
input int StopLoss = 100;
input int TakeProfit = 200;
これにより
EA設定画面
からパラメータを変更できます。
パラメータ化するべき代表項目
- ロットサイズ
- SL / TP
- 指標期間
- 取引時間
- スプレッド制限
初心者がつまずきやすいポイント
① ロジックをTick単位で動かす
初心者は次のようなEAを書きがちです。
void OnTick()
{
trade.Buy(0.1);
}
この場合
Tickごとに注文
されます。
対策
バー確定ロジック
② ポジションチェックをしない
ポジション管理を行わないEAは、すぐに暴走します。
必ず以下を確認します。
PositionsTotal()
③ 安全制御を書かない
EAには必ず
スプレッド制限
時間制限
ロット制限
などの安全設計を入れる必要があります。
8. MQL5 EA基本構造のまとめ
ここまで、MQL5のEA(Expert Advisor)の基本構造について解説してきました。
EA開発では、まずイベント駆動型プログラムであることを理解することが重要です。
通常のプログラムとは異なり、EAは特定のイベントが発生したときに処理が実行される構造になっています。
EAの基本構造は、次の3つの関数で構成されます。
| 関数 | 役割 | 実行タイミング |
|---|---|---|
| OnInit() | 初期化処理 | EA起動時 |
| OnTick() | メイン処理 | 価格更新時 |
| OnDeinit() | 終了処理 | EA停止時 |
EAの動作は、次のような流れになります。
EA起動
↓
OnInit()
↓
Tick発生
↓
OnTick()
↓
売買判断
↓
注文実行
↓
EA終了
↓
OnDeinit()
この構造を理解すると、EAの設計は次のように整理できます。
OnInit()
↓
環境初期化
↓
OnTick()
↓
市場データ取得
↓
売買シグナル判定
↓
注文処理
↓
ポジション管理
さらに、実務レベルのEAでは次の設計が重要になります。
- ロジックを関数分割する
- inputパラメータを使う
- スプレッド制限を入れる
- ポジション数を管理する
- バー確定ロジックを使う
これらを実装することで、EAは安定した自動売買プログラムになります。
また、EA開発では次の点を常に意識することが重要です。
再現性(バックテストとの一致)
安全性(暴走防止)
保守性(コード管理)
これらの要素を満たす設計を行うことで、EAの品質は大きく向上します。
9. FAQ(よくある質問)
9.1 MQL5のEA基本構造とは何ですか?
EAはイベント駆動型プログラムで、主に OnInit()、OnTick()、OnDeinit() の3つの関数で構成されます。
これらの関数が、EAの初期化・売買ロジック・終了処理を担当します。
9.2 EAはなぜOnTick()で動くのですか?
EAは市場価格が更新されたとき(Tick)に処理を実行する仕組みです。
そのため、売買ロジックは通常 OnTick() 内に書きます。
9.3 OnInit()とOnTick()の違いは何ですか?
OnInit() はEA起動時に1回だけ実行される初期化関数です。
OnTick() は価格更新ごとに実行されるメイン処理の関数です。
9.4 EAが注文を出せない原因は何ですか?
よくある原因は次の通りです。
- MT5の自動売買ボタンがOFF
- EA設定で取引許可が無効
- スプレッド制限
- ロットサイズエラー
環境やブローカー設定によって異なる場合があります。
9.5 EAはどこに保存されますか?
EAは通常、次のフォルダに保存されます。
MQL5/Experts/
コンパイルすると .mq5(ソースコード)と .ex5(実行ファイル)が生成されます。
9.6 EAがTickごとに注文してしまうのはなぜですか?
OnTick() 内で注文条件を制御していない場合、Tickごとに注文が実行される可能性があります。
ポジションチェックやバー確定ロジックを入れることで防げます。
9.7 EA開発で最初に覚えるべき関数は何ですか?
初心者が最初に覚えるべき関数は次の3つです。
OnInit()(初期化)OnTick()(売買ロジック)OnDeinit()(終了処理)
これらを理解することで、EAの基本構造を理解できます。