MQL4MQL5 EA(エキスパートアドバイザー) ポジション管理
ポジションは1つだけにしたい(重複エントリーを防ぎたい)
結論:注文の前に、この EA のポジションがすでにあるかを数え、あれば注文しないようにします。
考え方
エントリー条件を満たしている間は毎ティック注文してしまうため、「ポジションを持っていないときだけ注文する」チェックが必要です。この EA のポジション(同じ通貨ペア・同じマジックナンバー)の数を数え、上限未満のときだけ注文します。ここでは、価格が移動平均より上なら買う単純な条件に、このチェックを組み合わせた EA を例にしています。
- この EA のポジション数を数える関数を作る
- 注文の前に、その数が上限(ここでは 1)未満かを確認する
- 新しい足ができたときだけ判定すると、同じ足での二重注文も防げる
そのまま使えるコード
MetaEditor の「新規作成」で「エキスパートアドバイザ(テンプレート)」を選び、できたファイルの中身をすべてこのコードに置き換えてコンパイル(F7)します。ファイルは Experts フォルダに保存され、ナビゲーターからチャートにドラッグして使います。
MQL4(MT4)
#property strict
// ポジションを1つに制限する EA の例(MT4)
input double InpLots = 0.1; // ロット
input int InpMaxPos = 1; // 最大ポジション数
input int InpMagic = 1001; // マジックナンバー
int MyPositions()
{
int n = 0;
for(int i = OrdersTotal() - 1; i >= 0; i--)
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) && OrderSymbol() == _Symbol
&& OrderMagicNumber() == InpMagic && OrderType() <= OP_SELL)
n++;
return n;
}
int OnInit()
{
return INIT_SUCCEEDED;
}
void OnTick()
{
if(MyPositions() >= InpMaxPos) return; // すでに持っていれば何もしない
// 例:確定足の終値が 20 MA より上なら買う(実際の条件に置き換える)
double ma = iMA(_Symbol, 0, 20, 0, MODE_SMA, PRICE_CLOSE, 1);
if(iClose(_Symbol, PERIOD_CURRENT, 1) > ma)
if(OrderSend(_Symbol, OP_BUY, InpLots, Ask, 30, 0, 0, "", InpMagic) < 0)
Print("注文失敗 error=", GetLastError());
}MQL5(MT5)
// ポジションを1つに制限する EA の例(MT5)
#include <Trade\Trade.mqh>
input double InpLots = 0.1; // ロット
input int InpMaxPos = 1; // 最大ポジション数
input ulong InpMagic = 1001; // マジックナンバー
CTrade trade;
int hMa = INVALID_HANDLE;
int MyPositions()
{
int n = 0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
if(PositionGetTicket(i) > 0 && PositionGetString(POSITION_SYMBOL) == _Symbol
&& (ulong)PositionGetInteger(POSITION_MAGIC) == InpMagic)
n++;
return n;
}
int OnInit()
{
trade.SetExpertMagicNumber(InpMagic);
hMa = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE);
return hMa == INVALID_HANDLE ? INIT_FAILED : INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
IndicatorRelease(hMa);
}
void OnTick()
{
if(MyPositions() >= InpMaxPos) return; // すでに持っていれば何もしない
// 例:確定足の終値が 20 MA より上なら買う(実際の条件に置き換える)
double ma[];
if(CopyBuffer(hMa, 0, 1, 1, ma) < 1) return;
if(iClose(_Symbol, PERIOD_CURRENT, 1) > ma[0])
if(!trade.Buy(InpLots))
Print("注文失敗 ", trade.ResultRetcodeDescription());
}MT4 版・MT5 版とも MetaEditor でコンパイル(エラー・警告なし)を確認済みです。実際の口座で使う前に、デモ口座やストラテジーテスターで動作を確かめてください。
カスタマイズのポイント
- 買い・売りそれぞれ1つまでにしたいときは、「ポジション数を数える」レシピのように向きごとに数えます。
注意点
- 注文直後は、ポジションの一覧への反映がわずかに遅れることがあります。新しい足ができたときだけ判定する形にすると、二重注文をより確実に防げます。
このコードで使っている関数
あわせて読みたいレシピ
- 保有中のポジション数を数えたいポジションの一覧をループし、通貨ペア・マジックナンバー・売買の向きで絞って数えます。
- 新しい足ができたときだけ処理したい今の足の開始時刻 iTime(_Symbol, PERIOD_CURRENT, 0) を前回の値と比べ、変わったら新しい足と判定します。
- マジックナンバーで自分の EA の注文を区別したい注文にマジックナンバーを付け(MQL4 は OrderSend の引数、MQL5 は trade.SetExpertMagicNumber)、ポジションを扱うときに同じ番号のものだけを選びます。
- ゴールデンクロス・デッドクロスで売買したい短期 MA と長期 MA の値を「2本前」と「1本前」で比べ、上下が入れ替わったらクロスと判定します。
「ポジション管理」のレシピ一覧
- 保有中のポジション数を数えたい
- ポジションは1つだけにしたい(重複エントリーを防ぎたい)
- トレーリングストップを入れたい
- 含み益が出たら損切りを建値に移動したい
- 含み損益の合計を計算したい
- 一定時間たったポジションを決済したい
- 前回の取引が勝ちか負けかを調べたい












