今回は、遂にエキスパートを完成します。
エキスパートの主機能である「発注」を実装いたします。
MT4で一行で済んでいた「OrderSend」関数が、なんやらヘンチクリンなことになっています。
今回のステップ
・MT5を使おう<基礎編>
□.MT5をインストールする。
↓
□.何もしないEAを作り、動作させる。
↓
□.何か適当なメッセージをログ出力してみる。
↓
□.過去一定期の四本値を取得してみる。
↓
□.単純な売買ルール「山越えで売り・谷越えで買い」を実装する。
↓
□.オーダーを実装する。
↓
□.バックテスト。
実習
早速実習です。今回は前回作成した「test04.mq5」を使用いたします。
①エディターを起動し「test04.mq5」を開きます。
②ソースコードに、以下を追加します。
場所はソースコード先頭部。
赤字部分をコピーし、ソースコードに貼り付けてください。
//+------------------------------------------------------------------+
//| test01.mq5 |
//| Copyright 2020, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#define EXPERT_MAGIC 123456 //外部変数 input int Kikan = 60; input double MinBand = 40;
|
③ソースコードの以下を一旦削除します。
前回「工事中」の「Ordr」関数
double valPips(double pips)
{
double price = 0;
int digits = (int)Digits();
if(digits == 3 || digits == 5){
price = pips / MathPow(10, digits) * 10;
} else {
price = pips / MathPow(10, digits);
}
price = NormalizeDouble(price, digits);
return(price);
}
void Ordr(string BuySell,double Lots) {
//工事中
}
|
④ソースコードに以下を貼り付けます。
場所はソースコード末尾。
赤字部分をコピーし、ソースコードに貼り付けてください。
double valPips(double pips)
{
double price = 0;
int digits = (int)Digits();
if(digits == 3 || digits == 5){
price = pips / MathPow(10, digits) * 10;
} else {
price = pips / MathPow(10, digits);
}
price = NormalizeDouble(price, digits);
return(price);
}
void Ordr(string strOdr,double valLots)
{
MqlTradeRequest request={0};
MqlTradeResult result={0};
bool ret;
request.magic = EXPERT_MAGIC;
request.action = TRADE_ACTION_DEAL;
request.symbol = Symbol();
request.volume = valLots;
if (strOdr == "BUY") {
request.type = ORDER_TYPE_BUY;
request.price = SymbolInfoDouble(Symbol(),SYMBOL_ASK);
request.sl = SymbolInfoDouble(Symbol(),SYMBOL_BID) - valPips(20);
request.tp = SymbolInfoDouble(Symbol(),SYMBOL_BID) + valPips(20);
} else {
request.type = ORDER_TYPE_SELL;
request.price = SymbolInfoDouble(Symbol(),SYMBOL_BID);
request.sl = SymbolInfoDouble(Symbol(),SYMBOL_ASK) + valPips(20);
request.tp = SymbolInfoDouble(Symbol(),SYMBOL_ASK) - valPips(20);
}
ret = OrderSend(request,result);
}
|
⑤別名で保存
今回は正式名「YamaTani.mq5」で保存してください。
⑥コンパイル
前回同様エラーにならない事を確認してください。
⑦テスト
今回動作させると、「ストラテジーテスター」の「バックテスト」に、売買を行った結果が反映されます。
同様にグラフにも反映されます。
~ 以上で終了です。
実習の説明
構造体
構造体は「変数の詰め合わせ」です。
MT4のときは、関数の引数は変数だけでした。
MT5では、引数に複数の変数を渡す必要が関数は、この構造体を使ってまとめて渡す必要があります。
関数で使用する構造体は、あらかじめ準備されているので、新たに宣言する必要はありません。
普段使いのプログラムで便利と感じないので、積極的に使わなくて構わないかと。
MT5の仕様で、嫌嫌使わされる感覚でいいと思います。
関数「Ordr」について
まず、2つの引数を受け取ります。
そのオーダーが「買い」なのか「売り」なのかを示す文字型変数「strOdr」と、どれだけの数量をオーダーするかを示す実数型変数「valLots」の2つです。
void Ordr(string strOdr,double valLots) {
|
次に発注関数「OrderSend()」への受け渡しのための「MqlTradeRequest型構造体」の「request」と、逆に実行結果を返却する「MqlTradeResult型構造体」の「result」を初期化しています。
MqlTradeRequest request={0}; MqlTradeResult result={0};
|
「売り」「買い」に関係ない共通の構造体変数を設定しています。
request.magic = EXPERT_MAGIC; ←マジックナンバー request.action = TRADE_ACTION_DEAL; ←アクション request.symbol = Symbol(); ←通貨ペア request.volume = valLots; ←ロット数
|
説明 |
内容 |
マジックナンバー |
エキスパートの個体ナンバーです。同じ証券口座で複数エキスパートを実働する場合にしか意味ないです。適当な番号を実習工程②で指定しました。 |
アクション |
この関数、発注する以外にも様々な機能があります。ここでは「TRADE_ACTION_DEAL(発注)」を指定しています。 |
通貨ペア |
ストラテジーテスターで指定した通貨ペアを「Symbol()」関数で取得しています。 |
ロット数 |
引数「valLots」を渡しています。1ロット10万通貨(ドルなら10万ドル、ユーローなら10万ユーロ)に対し、0.01ロットは1000通貨となります。 |
引数「strOdr」の「売り」「買い」で処理を分岐しています。
if (strOdr == "BUY")
request.type = ORDER_TYPE_BUY; ←買い
request.price = SymbolInfoDouble(Symbol(),SYMBOL_ASK); ←買い値
request.sl = SymbolInfoDouble(Symbol(),SYMBOL_BID) - valPips(20); ←損切り値
request.tp = SymbolInfoDouble(Symbol(),SYMBOL_BID) + valPips(20); ←利得値
} else {
request.type = ORDER_TYPE_SELL; ←売り
request.price = SymbolInfoDouble(Symbol(),SYMBOL_BID); ←売り値
request.sl = SymbolInfoDouble(Symbol(),SYMBOL_ASK) + valPips(20); ←損切り値
request.tp = SymbolInfoDouble(Symbol(),SYMBOL_ASK) - valPips(20); ←利得値
}
|
今回の場合「成り行き=そのときの値段で売買」でオーダーしています。
注文と同時に、20Pips以上の損失時にロスカット、20Pips以上の利益に利食いするよう設定しています。
発注関数「OrderSend」を実行します。
結果が「result」に返却されますが、バックテストでは、こちらの提示した売買値・数量で100%取引が成立するので、例外処理などは一切していません。
ret = OrderSend(request,result);
|
~ 今回は以上となります。オツカレサマでした。