😽
MQL5で成行エントリー注文をする方法 OrderSend()の説明
MQL5って検索すると、MQL5という言語情報よりも販売サイトにつながるのでMQL5の情報が見つけにくいので検索用にMQL5の情報を書いていきます。
今回は、エントリー注文の方法をまとめます。
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エントリー
}
}
エラーが出たら?
エラーコードを頼りに調べよう。
テクニカル指標の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