MQL4MQL5 EA(エキスパートアドバイザー) ポジション管理
トレーリングストップを入れたい
結論:現在値から一定の幅をとった位置に損切りを計算し、今の損切りより有利なときだけ OrderModify()・PositionModify() で動かします。
考え方
トレーリングストップは、価格が有利な方向に動くたびに損切りを追いかけて動かす方法です。買いなら「Bid − 幅」、売りなら「Ask + 幅」を新しい損切りにし、今の損切りより有利な場合だけ変更します。不利な方向には動かさないことと、同じ値で何度も変更しない(MT4 エラー1、MT5 10025 を防ぐ)ことがポイントです。
- この EA のポジションを順に調べる
- 含み益が開始幅に達していれば、新しい損切りを計算する
- 今の損切りより有利(買いなら高い、売りなら低い)なときだけ変更する
そのまま使えるコード
MetaEditor の「新規作成」で「エキスパートアドバイザ(テンプレート)」を選び、できたファイルの中身をすべてこのコードに置き換えてコンパイル(F7)します。ファイルは Experts フォルダに保存され、ナビゲーターからチャートにドラッグして使います。
MQL4(MT4)
#property strict
// トレーリングストップの EA(MT4)
input double InpStart = 20; // トレールを始める含み益(pips)
input double InpTrail = 15; // 現在値から損切りまでの幅(pips)
input int InpMagic = 1001; // 対象のマジックナンバー(-1 ならすべて)
int OnInit()
{
return INIT_SUCCEEDED;
}
void OnTick()
{
double pip = (_Digits == 3 || _Digits == 5) ? _Point * 10 : _Point;
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
if(OrderSymbol() != _Symbol || (InpMagic >= 0 && OrderMagicNumber() != InpMagic)) continue;
if(OrderType() == OP_BUY && Bid - OrderOpenPrice() >= InpStart * pip)
{
double sl = NormalizeDouble(Bid - InpTrail * pip, _Digits);
if(OrderStopLoss() == 0 || sl > OrderStopLoss() + _Point / 2)
if(!OrderModify(OrderTicket(), OrderOpenPrice(), sl, OrderTakeProfit(), 0))
Print("変更失敗 error=", GetLastError());
}
if(OrderType() == OP_SELL && OrderOpenPrice() - Ask >= InpStart * pip)
{
double sl = NormalizeDouble(Ask + InpTrail * pip, _Digits);
if(OrderStopLoss() == 0 || sl < OrderStopLoss() - _Point / 2)
if(!OrderModify(OrderTicket(), OrderOpenPrice(), sl, OrderTakeProfit(), 0))
Print("変更失敗 error=", GetLastError());
}
}
}MQL5(MT5)
// トレーリングストップの EA(MT5)
#include <Trade\Trade.mqh>
input double InpStart = 20; // トレールを始める含み益(pips)
input double InpTrail = 15; // 現在値から損切りまでの幅(pips)
input long InpMagic = 1001; // 対象のマジックナンバー(-1 ならすべて)
CTrade trade;
int OnInit()
{
return INIT_SUCCEEDED;
}
void OnTick()
{
double pip = (_Digits == 3 || _Digits == 5) ? _Point * 10 : _Point;
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(InpMagic >= 0 && PositionGetInteger(POSITION_MAGIC) != InpMagic) continue;
double open = PositionGetDouble(POSITION_PRICE_OPEN);
double cur = PositionGetDouble(POSITION_SL);
double tp = PositionGetDouble(POSITION_TP);
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && bid - open >= InpStart * pip)
{
double sl = NormalizeDouble(bid - InpTrail * pip, _Digits);
if(cur == 0 || sl > cur + _Point / 2)
if(!trade.PositionModify(ticket, sl, tp))
Print("変更失敗 ", trade.ResultRetcodeDescription());
}
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && open - ask >= InpStart * pip)
{
double sl = NormalizeDouble(ask + InpTrail * pip, _Digits);
if(cur == 0 || sl < cur - _Point / 2)
if(!trade.PositionModify(ticket, sl, tp))
Print("変更失敗 ", trade.ResultRetcodeDescription());
}
}
}MT4 版・MT5 版とも MetaEditor でコンパイル(エラー・警告なし)を確認済みです。実際の口座で使う前に、デモ口座やストラテジーテスターで動作を確かめてください。
カスタマイズのポイント
- トレール幅を ATR(平均的な値幅)に合わせると、相場の動きの大きさに応じて調整できます。
- 1pips 動くたびに変更すると変更の回数が多くなります。「一定 pips 以上有利になったときだけ」動かす条件を足すと減らせます。
注意点
- 損切りは現在値からストップレベル以上離す必要があります。トレール幅が狭すぎるとエラーになります。
- EA を止めている間(パソコンを切っている間)はトレールされません。












