😽

MQL5で成行エントリー注文をする方法 OrderSend()の説明

2023/10/07に公開

MQL5って検索すると、MQL5という言語情報よりも販売サイトにつながるのでMQL5の情報が見つけにくいので検索用にMQL5の情報を書いていきます。

https://www.mql5.com/ja

今回は、エントリー注文の方法をまとめます。

OrderSend関数

公式ドキュメント
https://www.mql5.com/ja/docs/trading/ordersend

bool  OrderSend(
  MqlTradeRequest&  request,      // 問の構造体
  MqlTradeResult&   result       // 答えの構造体
  );

パラメータ

request

[in] クライエントの取引アクティビティを記述する MqlTradeRequest 型の構造体へのポインタ

result

[in,out] 成功した場合(true が返される場合)取引操作の結果を表す MqlTradeResult 型の構造体へのポインタ

戻り値

基本的な構造体チェック(ポインタチェック)が成功した場合、trueが戻されます。しかし、これは取引操作が成功することを表すものではありません。 関数実行結果の詳細には、result 構造体のフィールドが分析されるべきです。

MQL4よりもグッと難易度が上がっていますね。

これ初見だと使うの難しいです。

ドキュメントの日本語も怪しいし、読み解くの苦労すると思います。

MQL5 エントリー注文の構造体の内容

struct MqlTradeRequest 
  { 
   ENUM_TRADE_REQUEST_ACTIONS   action;           // 取引の種類 
  ulong                         magic;           // エキスパートアドバイザー ID(マジックナンバー) 
  ulong                         order;           // 注文チケット 
  string                       symbol;           // 取引シンボル 
  double                       volume;           // 約定のための要求されたボリューム(ロット単位) 
  double                       price;           // 価格 
  double                       stoplimit;       // 注文のストップリミットレベル 
  double                       sl;               // 注文の決済逆指値レベル 
  double                       tp;               // 注文の決済指値レベル 
  ulong                         deviation;       // リクエストされた価格からの可能な最大偏差 
  ENUM_ORDER_TYPE               type;             // 注文の種類 
  ENUM_ORDER_TYPE_FILLING       type_filling;     // 注文実行の種類 
  ENUM_ORDER_TYPE_TIME        type_time;       // 注文期限切れの種類 
  datetime                     expiration;       // 注文期限切れの時刻 (ORDER_TIME_SPECIFIED 型の注文) 
  string                       comment;         // 注文コメント
  ulong                         position;         // Position ticket
   ulong                         position_by;     // The ticket of an opposite position 
  };
struct MqlTradeResult 
{ 
 uint    retcode;         // 操作のリターンコード 
ulong   deal;             // 実行された場合の 約定チケット 
ulong   order;           // 注文された場合のチケット 
double   volume;           // ブローカーによって確認された約定ボリューム 
double   price;           // ブローカーによって確認された約定価格 
double   bid;             // 現在の売値 
double   ask;             // 現在の買値 
string   comment;         // 操作に対するブローカーコメント(デフォルトは取引サーバの返したコードの記述) 
uint    request_id;       // ディスパッチの際に、端末によって設定されたリクエストID  
 int      retcode_external; // 外部取引システムのリターンコード 
};

MQL5 成行エントリー注文の関数

entry.mq5
int MagicNumber = 123;       // マジックナンバー
double lots = 0.01;         // ロットサイズ
int slippage = 10;          // スリッページ


void position_entry(ENUM_ORDER_TYPE order_type) {
    MqlTradeRequest req = {};
    MqlTradeResult res = {};

    req.action = TRADE_ACTION_DEAL;  // 成行注文
    req.symbol = Symbol();
    req.volume = lots;               // 注文数量
    req.type = order_type;           // 売買方向 ORDER_TYPE_BUY or ORDER_TYPE_SELL
    req.deviation = slippage;        // スリッページ
    req.magic = MagicNumber;         // マジックナンバー
    req.comment = "";                // コメント

    // Filling typeの設定
    if (IsFillingTypeAllowed(_Symbol, ORDER_FILLING_FOK)) {
        req.type_filling = ORDER_FILLING_FOK;
    } else if (IsFillingTypeAllowed(_Symbol, ORDER_FILLING_IOC)) {
        req.type_filling = ORDER_FILLING_IOC;
    } else {
        req.type_filling = ORDER_FILLING_RETURN;
    }

    bool order_result = OrderSend(req, res);

    if (order_result == false) {
        Print(res.retcode);
    }
}

bool IsFillingTypeAllowed(string symbol, int fill_type) {
    int filling = (int)SymbolInfoInteger(symbol, SYMBOL_FILLING_MODE);
    return ((filling & fill_type) == fill_type);
}

MQL5 ストップリミットを設定する場合の成行エントリー注文の関数

entry.mq5
int MagicNumber = 123;       // マジックナンバー
double lots = 0.01;         // ロットサイズ
int slippage = 10;          // スリッページ
double stoploss = 500.0;     // ストップロス (_Point単位)
double takeprofit = 1000.0;  // テイクプロフィット (_Point単位)

void position_entry_with_sltp(ENUM_ORDER_TYPE order_type) {
    MqlTradeRequest req = {};
    MqlTradeResult res = {};

    double entryPrice = 0;
    if (order_type == ORDER_TYPE_BUY) {
        entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
        req.sl = entryPrice - stoploss * _Point;  // ストップロス設定
        req.tp = entryPrice + takeprofit * _Point;  // テイクプロフィット設定
    } else if (order_type == ORDER_TYPE_SELL) {
        entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
        req.sl = entryPrice + stoploss * _Point;
        req.tp = entryPrice - takeprofit * _Point;
    }

    req.action = TRADE_ACTION_DEAL;  // 成行注文
    req.symbol = Symbol();
    req.volume = lots;               // 注文数量
    req.type = order_type;           // 売買方向 ORDER_TYPE_BUY or ORDER_TYPE_SELL
    req.deviation = slippage;        // スリッページ
    req.magic = MagicNumber;         // マジックナンバー
    req.comment = "";                // コメント

    // Filling typeの設定
    if (IsFillingTypeAllowed(_Symbol, ORDER_FILLING_FOK)) {
        req.type_filling = ORDER_FILLING_FOK;
    } else if (IsFillingTypeAllowed(_Symbol, ORDER_FILLING_IOC)) {
        req.type_filling = ORDER_FILLING_IOC;
    } else {
        req.type_filling = ORDER_FILLING_RETURN;
    }

    bool order_result = OrderSend(req, res);

    if (order_result == false) {
        Print(res.retcode);
    }
}

bool IsFillingTypeAllowed(string symbol, int fill_type) {
    int filling = (int)SymbolInfoInteger(symbol, SYMBOL_FILLING_MODE);
    return ((filling & fill_type) == fill_type);
}

MQL5 標準クラスを使った成行エントリー注文の関数

上記の方法だと難易度が高いのでクラスを使ったエントリー注文が人気です。エントリー注文のラッパークラスです。

entry.mq5
#include <Trade\Trade.mqh>
CTrade trade;

int MagicNumber = 123;       // マジックナンバー
double input_lots = 0.01;         // ロットサイズ
int slippage = 10;          // スリッページ
double input_sl = 0.0;      // ストップロスなし
double input_tp = 0.0;      // テイクプロフィットなし

void position_entry(ENUM_ORDER_TYPE order_type) {
trade.SetExpertMagicNumber(MagicNumber);
    if(order_type == ORDER_TYPE_BUY) {
        if(!trade.Buy(input_lots, _Symbol, 0, input_sl, input_tp, "Buy Entry")) {
            Print("Buy注文のエラー: ", GetLastError());
        }
    } else if(order_type == ORDER_TYPE_SELL) {
        if(!trade.Sell(input_lots, _Symbol, 0, input_sl, input_tp, "Sell Entry")) {
            Print("Sell注文のエラー: ", GetLastError());
        }
    }
}

使い方

void OnTick()
  {
bool A = PositionsTotal() == 0;//ポジション数が0
bool B = OrdersTotal() == 0;//オーダー数が0

if(A && B){
position_entry(0);//BUYエントリー
}
   
  }

エラーが出たら?

エラーコードを頼りに調べよう。

https://www.mql5.com/ja/docs/constants/errorswarnings/enum_trade_return_codes

テクニカル指標のRSIを使った成行注文、成行決済EA

RSI30を下回ったらロング、70を超えたら決済

bool IsFillingTypeAllowed(string symbol, int fill_type) {
    int filling = (int)SymbolInfoInteger(symbol, SYMBOL_FILLING_MODE);
    return ((filling & fill_type) == fill_type);
}

void position_entry(ENUM_ORDER_TYPE order_type) {
    MqlTradeRequest req = {};
    MqlTradeResult res = {};

    req.action = TRADE_ACTION_DEAL;  // 成行注文
    req.symbol = Symbol();
    req.volume = lots;               // 注文数量
    req.type = order_type;           // 売買方向 ORDER_TYPE_BUY or ORDER_TYPE_SELL
    req.deviation = slippage;        // スリッページ
    req.magic = MagicNumber;         // マジックナンバー
    req.comment = "";                // コメント

    // Filling typeの設定
    if (IsFillingTypeAllowed(_Symbol, ORDER_FILLING_FOK)) {
        req.type_filling = ORDER_FILLING_FOK;
    } else if (IsFillingTypeAllowed(_Symbol, ORDER_FILLING_IOC)) {
        req.type_filling = ORDER_FILLING_IOC;
    } else {
        req.type_filling = ORDER_FILLING_RETURN;
    }

    bool order_result = OrderSend(req, res);

    if (order_result == false) {
        Print(res.retcode);
    }
}

void position_entry_with_sltp(ENUM_ORDER_TYPE order_type) {
    MqlTradeRequest req = {};
    MqlTradeResult res = {};

    double entryPrice = 0;
    if (order_type == ORDER_TYPE_BUY) {
        entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
        req.sl = entryPrice - stoploss * _Point;  // ストップロス設定
        req.tp = entryPrice + takeprofit * _Point;  // テイクプロフィット設定
    } else if (order_type == ORDER_TYPE_SELL) {
        entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
        req.sl = entryPrice + stoploss * _Point;
        req.tp = entryPrice - takeprofit * _Point;
    }

    req.action = TRADE_ACTION_DEAL;  // 成行注文
    req.symbol = Symbol();
    req.volume = lots;               // 注文数量
    req.type = order_type;           // 売買方向 ORDER_TYPE_BUY or ORDER_TYPE_SELL
    req.deviation = slippage;        // スリッページ
    req.magic = MagicNumber;         // マジックナンバー
    req.comment = "";                // コメント

    // Filling typeの設定
    if (IsFillingTypeAllowed(_Symbol, ORDER_FILLING_FOK)) {
        req.type_filling = ORDER_FILLING_FOK;
    } else if (IsFillingTypeAllowed(_Symbol, ORDER_FILLING_IOC)) {
        req.type_filling = ORDER_FILLING_IOC;
    } else {
        req.type_filling = ORDER_FILLING_RETURN;
    }

    bool order_result = OrderSend(req, res);

    if (order_result == false) {
        Print(res.retcode);
    }
}

void position_close(ENUM_ORDER_TYPE order_type, ulong position_ticket) {
    MqlTradeRequest req = {};
    MqlTradeResult res = {};

    order_type = order_type == ORDER_TYPE_BUY ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;

    req.action = TRADE_ACTION_DEAL;  // 成行注文
    req.symbol = Symbol();
    req.volume = lots;               // 注文数量
    req.type = order_type;           // 売買方向 ORDER_TYPE_BUY or ORDER_TYPE_SELL
    req.deviation = slippage;        // スリップページ
    req.magic = MagicNumber;         // マジックナンバー
    req.comment = "";                // コメント
    req.position = position_ticket;  // 決済するポジションを指定する

    // Filling typeの設定
    if (IsFillingTypeAllowed(_Symbol, ORDER_FILLING_FOK)) {
        req.type_filling = ORDER_FILLING_FOK;
    } else if (IsFillingTypeAllowed(_Symbol, ORDER_FILLING_IOC)) {
        req.type_filling = ORDER_FILLING_IOC;
    } else {
        req.type_filling = ORDER_FILLING_RETURN;
    }

    bool order_result = OrderSend(req, res);

    if (order_result == false) {
        Print(res.retcode);
    }
}

void position_all_close(ENUM_ORDER_TYPE side) {
    for (int i = PositionsTotal() - 1; i >= 0; i--) {
        if ("" != PositionGetSymbol(i)) {
            if (PositionGetInteger(POSITION_TYPE) == side) {
                if (Symbol() == PositionGetString(POSITION_SYMBOL)) {
                    if (PositionGetInteger(POSITION_MAGIC) == MagicNumber) {
                        position_close(side, PositionGetInteger(POSITION_TICKET));
                    }
                }
            }
        }
    }
}

int position_count(ENUM_ORDER_TYPE side) {
    int count = 0;
    for (int i = PositionsTotal() - 1; i >= 0; i--) {
        if ("" != PositionGetSymbol(i)) {
            if (PositionGetInteger(POSITION_TYPE) == side) {
                if (Symbol() == PositionGetString(POSITION_SYMBOL)) {
                    if (PositionGetInteger(POSITION_MAGIC) == MagicNumber) {
                        count++;
                    }
                }
            }
        }
    }
    return count;
}

double getRSIValue(int shift) {
    static int handle = -1;

    // RSI指標のハンドルを取得
    if (handle == -1) {
        handle = iRSI(_Symbol, PERIOD_CURRENT, 21, PRICE_CLOSE);
    }

    double rsiValue[];

    // バッファをコピーしてRSIの値を取得
    CopyBuffer(handle, 0, shift, 1, rsiValue);

    return rsiValue[0];
}

void OnTick() {
    bool P0 = position_count(ORDER_TYPE_BUY) == 0;

    // RSI30で逆張りロング
    bool A = getRSIValue(1) < 30;
    if (A && P0) {
        position_entry_with_sltp(ORDER_TYPE_BUY); // BUY
    }

    bool B = getRSIValue(1) > 70;
    bool P1 = position_count(ORDER_TYPE_BUY) == 1;

    if (B && P1) {
        position_all_close(ORDER_TYPE_BUY);
    }
}

Discussion