MQL4 取引関数リファレンス|OrderSend・OrderClose・OrderModify・ポジション管理ループ

MQL4 取引関数を体系的にまとめました。OrderSend()による成行・指値・逆指値注文、OrderClose()による決済、OrderModify()によるSL/TP変更、OrderSelect()とOrdersTotal()によるポジション管理ループ、ロット計算、トレーリングストップ、部分決済、マジックナンバーによる複数ロジック管理まで、MT4 EA開発に必要な取引処理のすべてをコード付きで解説します。

MQL4 トレード関数 リファレンスカード
目次

MQL4とMQL5の取引モデルの違い

MQL4の取引モデルはシンプルで直感的です。MQL5では構造体ベースの複雑なモデルに変わりましたが、MQL4では関数に引数を直接渡す方式です。

機能MQL4MQL5
発注OrderSend()に引数を直接渡すMqlTradeRequest構造体を使用
決済OrderClose(ticket, lot, price, slippage)反対売買(CTrade.PositionClose)
SL/TP変更OrderModify(ticket, …)MqlTradeRequest + TRADE_ACTION_SLTP
ポジション管理OrderSelect() + OrdersTotal()ループPositionGetTicket() + PositionsTotal()
注文タイプOP_BUY, OP_SELL等(6種類)ORDER_TYPE_BUY等(8種類)
マジックナンバーOrderSendの引数MqlTradeRequest.magic
ヘッジング標準対応口座設定による

MQL4の取引関数はMQL5では全く異なる関数に置き換わっています。OrderClose()やOrderModify()はMQL5には存在しません。MQL4のコードをMQL5に移植する際は、取引部分を全面的に書き直す必要があります。

OrderSend:新規注文

MQL4のOrderSend()は1つの関数で成行注文・指値注文・逆指値注文すべてを処理します。

関数シグネチャ

int OrderSend(
   string   symbol,           // 通貨ペア
   int      cmd,              // 注文タイプ(OP_BUY等)
   double   volume,           // ロット数
   double   price,            // 注文価格
   int      slippage,         // 許容スリッページ(ポイント)
   double   stoploss,         // ストップロス価格
   double   takeprofit,       // テイクプロフィット価格
   string   comment = NULL,   // コメント(任意)
   int      magic = 0,        // マジックナンバー(任意)
   datetime expiration = 0,   // 有効期限(任意、指値注文用)
   color    arrow_color = clrNONE  // チャート上の矢印色(任意)
);
// 戻り値: 成功時はチケット番号、失敗時は-1

注文タイプ一覧

定数説明
OP_BUY0成行買い
OP_SELL1成行売り
OP_BUYLIMIT2指値買い(現在値より下で待機)
OP_SELLLIMIT3指値売り(現在値より上で待機)
OP_BUYSTOP4逆指値買い(現在値より上で待機)
OP_SELLSTOP5逆指値売り(現在値より下で待機)

成行買い注文

int BuyOrder(double lots, int slPoints, int tpPoints)
  {
   double ask = Ask;  // またはMarketInfo(Symbol(), MODE_ASK)
   double sl  = NormalizeDouble(ask - slPoints * Point, Digits);
   double tp  = NormalizeDouble(ask + tpPoints * Point, Digits);

   int ticket = OrderSend(Symbol(), OP_BUY, lots, ask, 3, sl, tp,"Buy Order", 12345, 0, clrBlue);

   if(ticket < 0)
     {
      Print("買い注文失敗:", GetLastError());
      return -1;
     }

   Print("買い注文成功: ticket=", ticket);
   return ticket;
  }

成行売り注文

int SellOrder(double lots, int slPoints, int tpPoints)
  {
   double bid = Bid;
   double sl  = NormalizeDouble(bid + slPoints * Point, Digits);
   double tp  = NormalizeDouble(bid - tpPoints * Point, Digits);

   int ticket = OrderSend(Symbol(), OP_SELL, lots, bid, 3, sl, tp,"Sell Order", 12345, 0, clrRed);

   if(ticket < 0)
     {
      Print("売り注文失敗:", GetLastError());
      return -1;
     }

   Print("売り注文成功: ticket=", ticket);
   return ticket;
  }

指値注文(Buy Limit / Sell Limit)

// Buy Limit: 現在値より下で買い待機
int BuyLimitOrder(double lots, double entryPrice, int slPoints, int tpPoints)
  {
   double sl = NormalizeDouble(entryPrice - slPoints * Point, Digits);
   double tp = NormalizeDouble(entryPrice + tpPoints * Point, Digits);

   int ticket = OrderSend(Symbol(), OP_BUYLIMIT, lots,
                           NormalizeDouble(entryPrice, Digits),
                           3, sl, tp,"BuyLimit", 12345, 0, clrBlue);
   if(ticket < 0)
      Print("BuyLimit失敗:", GetLastError());
   return ticket;
  }

// Sell Limit: 現在値より上で売り待機
int SellLimitOrder(double lots, double entryPrice, int slPoints, int tpPoints)
  {
   double sl = NormalizeDouble(entryPrice + slPoints * Point, Digits);
   double tp = NormalizeDouble(entryPrice - tpPoints * Point, Digits);

   int ticket = OrderSend(Symbol(), OP_SELLLIMIT, lots,
                           NormalizeDouble(entryPrice, Digits),
                           3, sl, tp,"SellLimit", 12345, 0, clrRed);
   if(ticket < 0)
      Print("SellLimit失敗:", GetLastError());
   return ticket;
  }

逆指値注文(Buy Stop / Sell Stop)

// Buy Stop: 現在値より上で買い待機(ブレイクアウト狙い)
int BuyStopOrder(double lots, double entryPrice, int slPoints, int tpPoints)
  {
   double sl = NormalizeDouble(entryPrice - slPoints * Point, Digits);
   double tp = NormalizeDouble(entryPrice + tpPoints * Point, Digits);

   int ticket = OrderSend(Symbol(), OP_BUYSTOP, lots,
                           NormalizeDouble(entryPrice, Digits),
                           3, sl, tp,"BuyStop", 12345, 0, clrBlue);
   if(ticket < 0)
      Print("BuyStop失敗:", GetLastError());
   return ticket;
  }

// Sell Stop: 現在値より下で売り待機(ブレイクダウン狙い)
int SellStopOrder(double lots, double entryPrice, int slPoints, int tpPoints)
  {
   double sl = NormalizeDouble(entryPrice + slPoints * Point, Digits);
   double tp = NormalizeDouble(entryPrice - tpPoints * Point, Digits);

   int ticket = OrderSend(Symbol(), OP_SELLSTOP, lots,
                           NormalizeDouble(entryPrice, Digits),
                           3, sl, tp,"SellStop", 12345, 0, clrRed);
   if(ticket < 0)
      Print("SellStop失敗:", GetLastError());
   return ticket;
  }
OrderSendの注意点
  • 成行注文のpriceにはAsk(買い)/ Bid(売り)を使う。逆にするとエラー(ERR_INVALID_PRICE)
  • SL/TPはNormalizeDouble()で正規化が必須
  • ECN口座ではSL/TPを0にして発注後、OrderModify()で設定する必要がある場合あり
  • スリッページはポイント単位(5桁ブローカーなら3=0.3pips)
  • expirationを指定する場合、ブローカーが有効期限付き注文をサポートしている必要がある

OrderClose / OrderCloseBy:ポジション決済

OrderClose

bool OrderClose(
   int      ticket,      // 注文チケット番号
   double   lots,         // 決済ロット数
   double   price,        // 決済価格
   int      slippage,     // 許容スリッページ
   color    arrow_color = clrNONE  // 矢印色
);
// 戻り値: 成功=true, 失敗=false
// 買いポジションの決済
bool CloseBuyOrder(int ticket)
  {
   if(!OrderSelect(ticket, SELECT_BY_TICKET))
     {
      Print("チケット選択失敗:", ticket);
      return false;
     }

   // 買いポジションはBidで決済
   bool result = OrderClose(ticket, OrderLots(), Bid, 3, clrBlue);

   if(!result)
      Print("決済失敗:", GetLastError());
   else
      Print("決済成功: ticket=", ticket);

   return result;
  }

// 売りポジションの決済
bool CloseSellOrder(int ticket)
  {
   if(!OrderSelect(ticket, SELECT_BY_TICKET))
      return false;

   // 売りポジションはAskで決済
   return OrderClose(ticket, OrderLots(), Ask, 3, clrRed);
  }

OrderCloseBy:両建て決済

bool OrderCloseBy(
   int   ticket,       // 決済する注文チケット
   int   opposite,     // 反対ポジションのチケット
   color arrow_color = clrNONE
);
// 同じ通貨ペアの反対ポジション同士を相殺決済する

OrderCloseBy()はスプレッド節約に有効です。Closeでの決済はスプレッドが発生しますが、OrderCloseBy()での両建て決済はスプレッドが1回分で済みます。

OrderModify:SL/TP・待機注文の変更

bool OrderModify(
   int      ticket,       // チケット番号
   double   price,        // 新しい注文価格(成行ポジションの場合はOrderOpenPrice())
   double   stoploss,     // 新しいSL
   double   takeprofit,   // 新しいTP
   datetime expiration,   // 新しい有効期限(0=変更なし)
   color    arrow_color = clrNONE
);
// 戻り値: 成功=true, 失敗=false
// 成行ポジションのSL/TPを変更
bool ModifySLTP(int ticket, double newSL, double newTP)
  {
   if(!OrderSelect(ticket, SELECT_BY_TICKET))
      return false;

   // 成行ポジションではpriceにOrderOpenPrice()を渡す
   bool result = OrderModify(ticket, OrderOpenPrice(),
                              NormalizeDouble(newSL, Digits),
                              NormalizeDouble(newTP, Digits),
                              0, clrYellow);
   if(!result)
      Print("SL/TP変更失敗:", GetLastError());

   return result;
  }

// 待機注文の価格を変更
bool ModifyPendingPrice(int ticket, double newPrice, double newSL, double newTP)
  {
   if(!OrderSelect(ticket, SELECT_BY_TICKET))
      return false;

   return OrderModify(ticket, NormalizeDouble(newPrice, Digits),
                       NormalizeDouble(newSL, Digits),
                       NormalizeDouble(newTP, Digits),
                       0, clrYellow);
  }
OrderModifyの注意点
  • 成行ポジションのpriceにはOrderOpenPrice()を渡す(変更不可のため元の値を返す)
  • SL/TPを変更しない場合も、現在の値を渡す必要がある(0にするとSL/TPが削除される)
  • 同じ値で再度OrderModify()を呼ぶとERR_NO_RESULT(1)エラーになる
  • StopLevel(MODE_STOPLEVEL)より近い位置にSL/TPは設定できない

OrderDelete:待機注文の削除

bool OrderDelete(
   int   ticket,          // チケット番号
   color arrow_color = clrNONE
);
// 待機注文(Limit/Stop)を削除する。成行ポジションには使用不可
void DeleteAllPendingOrders(int magic)
  {
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         continue;
      if(OrderSymbol() != Symbol() || OrderMagicNumber() != magic)
         continue;
      if(OrderType() > OP_SELL)  // 2以上=待機注文
        {
         if(!OrderDelete(OrderTicket()))
            Print("待機注文削除失敗:", GetLastError());
        }
     }
  }

OrderSelect / OrdersTotal:ポジション管理ループ

MQL4のポジション管理で基本となるパターンは、OrdersTotal()とOrderSelect()を使ったループです。

OrderSelect

bool OrderSelect(
   int    index,            // インデックスまたはチケット番号
   int    select,           // SELECT_BY_POS または SELECT_BY_TICKET
   int    pool = MODE_TRADES  // MODE_TRADES(保有中)またはMODE_HISTORY(履歴)
);
// OrderSelect成功後に各種Order情報関数が使用可能になる

保有ポジションのループ

void ScanOpenOrders(int magic)
  {
   int buyCount = 0, sellCount = 0;
   double totalProfit = 0;

   // 逆順ループ(決済時にインデックスがずれるのを防ぐ)
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         continue;

      // 通貨ペアとマジックナンバーでフィルタ
      if(OrderSymbol() != Symbol())
         continue;
      if(OrderMagicNumber() != magic)
         continue;

      // ポジション情報を取得
      int    type   = OrderType();
      int    ticket = OrderTicket();
      double lots   = OrderLots();
      double profit = OrderProfit() + OrderSwap() + OrderCommission();
      double openPrice = OrderOpenPrice();

      totalProfit += profit;

      if(type == OP_BUY)
        {
         buyCount++;
         Print("BUY: ticket=", ticket," lots=", lots," profit=", profit);
        }
      else if(type == OP_SELL)
        {
         sellCount++;
         Print("SELL: ticket=", ticket," lots=", lots," profit=", profit);
        }
     }

   Print("合計: Buy=", buyCount," Sell=", sellCount," Profit=", totalProfit);
  }
ループの注意点
  • 逆順ループ(i–)が必須:決済するとインデックスがずれるため、順方向ループだとポジションを飛ばしてしまう
  • Symbol()とMagicNumber()のフィルタは必ず入れる(他のEAや手動注文を操作しないため)
  • OrderProfit()だけでなく、OrderSwap()とOrderCommission()も加算して正確な損益を計算する

Order情報取得関数一覧

関数戻り値説明
OrderTicket()intチケット番号
OrderType()int注文タイプ(OP_BUY=0, OP_SELL=1等)
OrderSymbol()string通貨ペア
OrderLots()doubleロット数
OrderOpenPrice()double約定価格
OrderClosePrice()double決済価格(保有中は現在価格)
OrderOpenTime()datetime約定時刻
OrderCloseTime()datetime決済時刻(保有中は0)
OrderStopLoss()doubleSL価格
OrderTakeProfit()doubleTP価格
OrderProfit()double損益(スワップ・手数料除く)
OrderSwap()doubleスワップポイント
OrderCommission()double手数料
OrderMagicNumber()intマジックナンバー
OrderComment()stringコメント
OrderExpiration()datetime有効期限

OrderHistoryTotal:取引履歴

void AnalyzeHistory(int magic, datetime fromDate)
  {
   int    wins = 0, losses = 0;
   double totalWin = 0, totalLoss = 0;

   for(int i = OrdersHistoryTotal() - 1; i >= 0; i--)
     {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
         continue;
      if(OrderSymbol() != Symbol() || OrderMagicNumber() != magic)
         continue;
      if(OrderType() > OP_SELL)  // 待機注文は除外
         continue;
      if(OrderCloseTime() < fromDate)  // 期間フィルタ
         continue;

      double profit = OrderProfit() + OrderSwap() + OrderCommission();

      if(profit >= 0)
        {
         wins++;
         totalWin += profit;
        }
      else
        {
         losses++;
         totalLoss += MathAbs(profit);
        }
     }

   int total = wins + losses;
   if(total > 0)
     {
      double winRate = (double)wins / total * 100.0;
      double pf = (totalLoss > 0) ? totalWin / totalLoss : 0;
      Print("勝率:", DoubleToStr(winRate, 1),"% (",
            wins,"勝", losses,"敗) PF=", DoubleToStr(pf, 2));
     }
  }

ロット計算

リスク管理の基本は、1トレードあたりの損失を口座残高の1〜2%に抑えることです。ロット数はSL幅(ポイント)とTickValueから逆算します。固定ロットは絶対に避け、必ずリスクベースで計算しましょう。

double CalcLotSize(double riskPercent, int slPoints)
  {
   double balance    = AccountBalance();
   double riskAmount = balance * riskPercent / 100.0;
   double tickValue  = MarketInfo(Symbol(), MODE_TICKVALUE);
   double tickSize   = MarketInfo(Symbol(), MODE_TICKSIZE);
   double minLot     = MarketInfo(Symbol(), MODE_MINLOT);
   double maxLot     = MarketInfo(Symbol(), MODE_MAXLOT);
   double lotStep    = MarketInfo(Symbol(), MODE_LOTSTEP);

   if(tickValue == 0 || slPoints == 0)
      return minLot;

   // 1ロットあたりのSL損失額を計算
   double slMoney = slPoints * Point / tickSize * tickValue;

   // リスク額からロット数を逆算
   double lots = riskAmount / slMoney;

   // ロットステップに丸める
   lots = MathFloor(lots / lotStep) * lotStep;

   // 範囲制限
   if(lots < minLot) lots = minLot;
   if(lots > maxLot) lots = maxLot;

   return NormalizeDouble(lots, 2);
  }

トレーリングストップ

void TrailingStop(int magic, int trailPoints, int trailStart)
  {
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         continue;
      if(OrderSymbol() != Symbol() || OrderMagicNumber() != magic)
         continue;

      double newSL;
      double currentSL = OrderStopLoss();
      int    stopLevel = (int)MarketInfo(Symbol(), MODE_STOPLEVEL);
      double minDist   = stopLevel * Point;

      if(OrderType() == OP_BUY)
        {
         // 含み益がtrailStart以上あるときだけ発動
         if(Bid - OrderOpenPrice() < trailStart * Point)
            continue;

         newSL = NormalizeDouble(Bid - trailPoints * Point, Digits);

         // 現在のSLより上にある場合のみ更新
         if(newSL > currentSL + Point && Bid - newSL > minDist)
           {
            if(!OrderModify(OrderTicket(), OrderOpenPrice(), newSL,
                             OrderTakeProfit(), 0, clrBlue))
               Print("トレーリング失敗:", GetLastError());
           }
        }
      else if(OrderType() == OP_SELL)
        {
         if(OrderOpenPrice() - Ask < trailStart * Point)
            continue;

         newSL = NormalizeDouble(Ask + trailPoints * Point, Digits);

         if((currentSL == 0 || newSL < currentSL - Point) && newSL - Ask > minDist)
           {
            if(!OrderModify(OrderTicket(), OrderOpenPrice(), newSL,
                             OrderTakeProfit(), 0, clrRed))
               Print("トレーリング失敗:", GetLastError());
           }
        }
     }
  }

部分決済

bool PartialClose(int ticket, double closePercent)
  {
   if(!OrderSelect(ticket, SELECT_BY_TICKET))
      return false;

   double totalLots = OrderLots();
   double closeLots = NormalizeDouble(totalLots * closePercent / 100.0, 2);
   double minLot    = MarketInfo(Symbol(), MODE_MINLOT);
   double lotStep   = MarketInfo(Symbol(), MODE_LOTSTEP);

   // ロットステップに丸める
   closeLots = MathFloor(closeLots / lotStep) * lotStep;

   // 最小ロット未満なら全決済
   if(closeLots < minLot)
      closeLots = totalLots;

   double price = (OrderType() == OP_BUY) ? Bid : Ask;

   bool result = OrderClose(ticket, closeLots, price, 3, clrYellow);
   if(!result)
      Print("部分決済失敗:", GetLastError());
   else
      Print("部分決済成功:", closeLots," /", totalLots," lots");

   return result;
  }
部分決済の注意点
  • 部分決済すると新しいチケット番号が発行される(残りのポジションは別チケットになる)
  • closeLots が minLot 未満の場合は全決済にフォールバックする
  • ブローカーによっては部分決済がサポートされていない場合がある

マジックナンバーによる複数ロジック管理

1つのEAで複数のロジックを管理する場合、マジックナンバーでポジションを識別します。

#define MAGIC_LOGIC_A  100001  // ロジックA
#define MAGIC_LOGIC_B  100002  // ロジックB
#define MAGIC_LOGIC_C  100003  // ロジックC
#define MAX_POSITIONS  3       // 全体の最大ポジション数

// 指定マジックナンバーのポジション数をカウント
int CountPositions(int magic)
  {
   int count = 0;
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         continue;
      if(OrderSymbol() != Symbol())
         continue;
      if(OrderMagicNumber() != magic)
         continue;
      if(OrderType() <= OP_SELL)
         count++;
     }
   return count;
  }

// 全ロジックの合計ポジション数
int CountAllPositions()
  {
   return CountPositions(MAGIC_LOGIC_A)
        + CountPositions(MAGIC_LOGIC_B)
        + CountPositions(MAGIC_LOGIC_C);
  }

void OnTick()
  {
   // 最大ポジション数チェック
   if(CountAllPositions() >= MAX_POSITIONS)
      return;

   // ロジックA: 条件チェック & エントリー
   if(CountPositions(MAGIC_LOGIC_A) == 0 && LogicA_Signal())
     {
      OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0,"LogicA", MAGIC_LOGIC_A, 0, clrBlue);
     }

   // ロジックB: 条件チェック & エントリー
   if(CountPositions(MAGIC_LOGIC_B) == 0 && LogicB_Signal())
     {
      OrderSend(Symbol(), OP_SELL, 0.1, Bid, 3, 0, 0,"LogicB", MAGIC_LOGIC_B, 0, clrRed);
     }

   // ロジックC: 条件チェック & エントリー
   if(CountPositions(MAGIC_LOGIC_C) == 0 && LogicC_Signal())
     {
      OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0,"LogicC", MAGIC_LOGIC_C, 0, clrGreen);
     }
  }

ECN口座対応パターン

ECN口座ではOrderSend時にSL/TPを同時に設定できないブローカーがあります。その場合はStep1: SL/TPなしで発注 → Step2: OrderModifyでSL/TP設定の2段階で処理します。STP口座でも同様のエラーが出る場合があるため、汎用的にこのパターンを実装するのがベストプラクティスです。

int BuyOrderECN(double lots, int slPoints, int tpPoints, int magic)
  {
   // Step 1: SL/TPなしで発注
   int ticket = OrderSend(Symbol(), OP_BUY, lots, Ask, 3,
                            0, 0,"ECN Buy", magic, 0, clrBlue);

   if(ticket < 0)
     {
      Print("発注失敗:", GetLastError());
      return -1;
     }

   // Step 2: SL/TPを後から設定
   if(slPoints > 0 || tpPoints > 0)
     {
      if(!OrderSelect(ticket, SELECT_BY_TICKET))
         return ticket;

      double openPrice = OrderOpenPrice();
      double sl = (slPoints > 0) ? NormalizeDouble(openPrice - slPoints * Point, Digits) : 0;
      double tp = (tpPoints > 0) ? NormalizeDouble(openPrice + tpPoints * Point, Digits) : 0;

      // リトライ付きでSL/TP設定
      for(int retry = 0; retry < 3; retry++)
        {
         if(OrderModify(ticket, openPrice, sl, tp, 0, clrBlue))
            break;
         Print("SL/TP設定リトライ:", GetLastError());
         Sleep(500);
        }
     }

   return ticket;
  }

取引関数一覧

MQL4関数MQL5対応説明
OrderSend()OrderSend() + MqlTradeRequest新規注文(成行/指値/逆指値)
OrderClose()CTrade::PositionClose()ポジション決済
OrderCloseBy()CTrade::PositionCloseBy()両建て決済
OrderModify()OrderSend() + TRADE_ACTION_SLTP/MODIFYSL/TP・待機注文変更
OrderDelete()CTrade::OrderDelete()待機注文の削除
OrderSelect()PositionSelectByTicket() / OrderGetTicket()注文を選択
OrdersTotal()PositionsTotal() / OrdersTotal()保有注文数
OrdersHistoryTotal()HistoryOrdersTotal()履歴注文数
OrderTicket()PositionGetTicket()チケット番号
OrderType()PositionGetInteger(POSITION_TYPE)注文タイプ
OrderLots()PositionGetDouble(POSITION_VOLUME)ロット数
OrderOpenPrice()PositionGetDouble(POSITION_PRICE_OPEN)約定価格
OrderProfit()PositionGetDouble(POSITION_PROFIT)損益
OrderMagicNumber()PositionGetInteger(POSITION_MAGIC)マジックナンバー
OrderStopLoss()PositionGetDouble(POSITION_SL)SL価格
OrderTakeProfit()PositionGetDouble(POSITION_TP)TP価格

まとめ

MQL4の取引関数はMQL5と比べてシンプルで直感的です。OrderSend()に引数を直接渡すだけで注文でき、OrderClose()で決済、OrderModify()でSL/TP変更と、関数名が処理内容をそのまま表しています。実際に試したところ、ポジションループをOrdersTotal()-1から逆順で回さないと、決済後にインデックスがずれて一部のポジションが処理されないケースがありました。

EA開発で押さえておきたいポイントは以下の3つです。

  • ポジションループは逆順(i–)で回す:決済時のインデックスずれを防ぐ
  • Symbol()とMagicNumber()で必ずフィルタする:他のEAや手動注文を誤操作しない
  • NormalizeDouble()で価格を正規化する:浮動小数点の誤差によるエラーを防ぐ

次のステップとして、MQLリファレンス総合ガイドから他のカテゴリも学習しましょう。インジケーター関数と組み合わせることで、実用的なEAを開発できます。

MQL4取引関数 よくある質問

MQL4のOrderSend()の使い方は?

OrderSend(symbol, cmd, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrow_color)で注文を送信します。成功時は注文チケット番号を返し、失敗時は-1を返します。失敗後はGetLastError()でエラーコードを確認してください。

MQL4でポジション数を確認する方法は?

OrdersTotal()で全オープンオーダー数、OrderSelect()でループして各オーダーを選択し、OrderType()でOP_BUY/OP_SELLのポジションを確認します。マジックナンバーをOrderMagicNumber()と比較することで自分のEAのポジションのみカウントできます。

MQL4でOrderClose()を正しく使う方法は?

OrderClose(ticket, lots, price, slippage, arrow_color)でポジションをクローズします。priceにはBid(売りポジション)またはAsk(買いポジション)を使用します。一部決済の場合はlotsに決済量を指定します。失敗時はGetLastError()でエラーを確認します。

MQL4でストップロスを後から変更する方法は?

OrderModify(ticket, price, stoploss, takeprofit, expiration, arrow_color)でSL/TPを変更します。priceには現在のオープン価格(OrderOpenPrice())、stoplossには新しいストップロス価格を指定します。ストップロス変更にはMarketInfo()のMODE_STOPLEVELで最小距離の確認が必要です。

MQL4でマジックナンバーを使う目的は?

同一口座で複数EAを実行する際に、自分のEAの注文を識別するために使用します。OrderMagicNumber()で取得した値と比較して自EAの注文のみを操作します。マジックナンバーは一意の値(例:チャートの時間足+通貨ペアのハッシュ)を設定してください。

MQL4とMQL5の取引関数の主な違いは?

MQL5ではOrderSend()が1つの関数に統合され、MqlTradeRequest構造体でパラメータを設定します。ポジション管理もOrdersTotal()からPositionsTotal()/PositionSelect()に変わり、より型安全な設計になっています。MQL4のシンプルな関数形式に慣れている場合はラッパークラス(CTrade)の使用を推奨します。

MQL4リファレンス 関連記事

シストレ.COM編集部|200種類以上のEAをフォワード計測する運営3年の検証メディア。MetaTrader (MT4/MT5) を実運用してきた編集部が監修・執筆しています。

⚠ リスクに関する注意事項

本記事は情報提供を目的としており、特定の金融商品の売買を推奨するものではありません。FX取引はレバレッジ取引の特性上、預託した証拠金以上の損失が生じる可能性があります。取引の際は、ご自身の判断と責任において行ってください。詳しくは特定商取引法に基づく表記をご確認ください。

シストレ.COMで実績のあるEAが使い放題!/
無料会員登録はこちら
FX自動売買でEAを探すなら
シストレ.COM 記事下バナー
実績あるEAが無料
厳格な審査を乗り越えた実績のあるEAが無料で使えます!
自由な口座選び
有料版を購入し柔軟な口座選びが可能!
フォワードテスト公開
全EAのフォワードテスト結果を公開中!
FX初心者も安心
初心者の方も安心して取引を始められます。
多様なEA選択肢
様々な種別のEAをご用意!自分の手法にあった取引が可能です。
信頼のFX会社と提携
人気のFX会社と提携中!様々なFX会社から選べます。
1分で登録完了!EA探すならシストレ.COM!/
無料会員登録はこちら

この記事が気に入ったら
フォローしてね!

お役立ち情報をシェアする
  • URLをコピーしました!

この記事を書いた人

シストレ.COM編集部は、FX自動売買(EA)とテクニカル分析を専門とするインターネットメディア「シストレ.COM」の編集チームです。200本以上のEAのフォワードテスト結果を公開し、実際の運用データに基づいた客観的な情報を発信しています。記事の執筆・監修はMetaTrader(MT4/MT5)での実運用経験を持つスタッフが担当。

目次