ここでは、前回記事に引き続きMetaTrader4のEAの作り方について説明します。
もし前回記事をまだ見ていない方はそちらから読み進めてください。
メタエディタでコードを入力(前編の続き)
前編で作成したEAがこちら
//+------------------------------------------------------------------+ //| MA_Doten_EAv1.00.mq4 | //| Dr.EA Keiji | //| https://www.dr-ea.com/meta-blog/ | //+------------------------------------------------------------------+ #property copyright "Dr.EA Keiji" #property link "https://www.dr-ea.com/meta-blog/" #property version "1.00" #property strict // パラメーター extern double Lots = 0.1; extern int MagicNumber = 20191030; // グローバル変数 int entry_bar; // エントリーした時のバーの数 //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- // 使い回ししそうな変数を宣言 int i, ticket; // 保有ポジションを確認 ------------------------------- int ticket_buy = 0; // 買いポジションの注文番号 double lots_buy = 0; // 買いポジションのロット数 int ticket_sell = 0; // 売りポジションの注文番号 double lots_sell = 0;// 売りポジションのロット数 for (i=0; i<OrdersTotal(); i++) { // ポジション選択 if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) return; // 通貨ペアまたはマジックナンバーが違う場合はスキップ if (OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber) continue; // 保有ポジションの注文番号とロット数を変数に代入 if (OrderType() == OP_BUY) { ticket_buy = OrderTicket(); lots_buy = OrderLots(); } if (OrderType() == OP_SELL) { ticket_sell = OrderTicket(); lots_sell = OrderLots(); } } // 取引シグナルを判定 --------------------------------- int entry_sign = 0; // エントリー用シグナル int exit_sign = 0; // 決済用シグナル // MAの値を取得 double ma_1 = iMA(NULL, 0, 20, 0, MODE_SMA, PRICE_CLOSE, 1); double ma_2 = iMA(NULL, 0, 20, 0, MODE_SMA, PRICE_CLOSE, 2); // 条件を満たしたらシグナル発生 (1: 買いシグナル, -1: 売りシグナル) if (Close[2] <= ma_2 && Close[1] > ma_1) { entry_sign = 1; exit_sign = 1; } if (Close[2] >= ma_2 && Close[1] < ma_1) { entry_sign = -1; exit_sign = -1; } // 決済 ----------------------------------------------- // 買いポジション決済 if (ticket_buy > 0 && exit_sign == -1) { if (OrderClose(ticket_buy, lots_buy, Bid, 0, clrYellow) == true) ticket_buy = 0; else Print("OrderClose error."); } // 売りポジション決済 if (ticket_sell > 0 && exit_sign == 1) { if (OrderClose(ticket_sell, lots_sell, Ask, 0, clrYellow) == true) ticket_sell = 0; else Print("OrderClose error."); } // エントリー------------------------------------------- if (ticket_buy == 0 && ticket_sell == 0 && entry_bar != Bars) { // 買いエントリー if (entry_sign == 1) { ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 0, 0, 0, NULL, MagicNumber, 0, clrBlue); if (ticket > 0) entry_bar = Bars; else Print("OrderSend error."); } // 売りエントリー if (entry_sign == -1) { ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, 0, 0, 0, NULL, MagicNumber, 0, clrRed); if (ticket > 0) entry_bar = Bars; else Print("OrderSend error."); } } } //+------------------------------------------------------------------+
はぅぅ。。
取引シグナルを判定
エントリー用と決済用のシグナルを格納する変数を宣言します。
int entry_sign = 0; // エントリー用シグナル int exit_sign = 0; // 決済用シグナル
次に、iMA()関数で、単純移動平均(期間20)の1つ前と2つ前の値を実数変数「ma_1」と「ma_2」に格納します。
double ma_1 = iMA(NULL, 0, 20, 0, MODE_SMA, PRICE_CLOSE, 1); double ma_2 = iMA(NULL, 0, 20, 0, MODE_SMA, PRICE_CLOSE, 2);
iMA()関数の()括弧内は次のように指定します。
iMA(通貨ペア, 時間足周期, 期間, 表示移動, MAの種類, 適用価格, シフト数)
通貨ペア
通貨ペアを文字列で指定します。NULLとすると稼働チャートの通貨ペアのことになります。
時間足周期
時間足周期を整数または定数で指定します。0またはPERIOD_CURRENTとすると稼働チャートの時間足周期のことになります。
1分足は1またはPERIOD_M1、5分足は5またはPRIOD_M5というように指定します。
期間と表示移動
期間と表示移動は整数で指定します。
MAの種類
MAの種類は、次の4種類から選んで指定します。
単純移動平均 | MODE_SMA |
---|---|
指数移動平均 | MODE_EMA |
平滑移動平均 | MODE_SMMA |
加重移動平均 | MODE_LWMA |
適用価格
適用価格は、次の7種類から選んで指定します。
終値 | PRICE_CLOSE |
---|---|
始値 | PRICE_OPEN |
高値 | PRICE_HIGH |
安値 | PRICE_LOW |
Median price (高値+安値)/2 | PRICE_MEDIAN |
Typical price (高値+安値+終値)/3 | PRICE_TYPICAL |
Weighted close price (高値+安値+終値+終値)/4 | PRICE_WEIGHTED |
シフト数
シフト数は、ローソク足何本分前かを指定します。
取引シグナル判定セクションの最後で、次のようにif()文で条件判定をして、条件を満たしたときに、シグナル用変数に買いシグナル「1」または、売りシグナル「-1」を代入するようにします。
if (Close[2] <= ma_2 && Close[1] > ma_1) { entry_sign = 1; exit_sign = 1; } if (Close[2] >= ma_2 && Close[1] < ma_1) { entry_sign = -1; exit_sign = -1; }
ここではClose[シフト数]で、シフト数本前のローソク足の終値を取得して条件文に使用しています。
決済注文処理
決済注文処理のセクションでは、次のコードのようにif()文で保有ポジションの決済シグナルが出ているかを判定して、OrderClose()関数で決済注文をします。
// 買いポジション決済 if (ticket_buy > 0 && exit_sign == -1) { if (OrderClose(ticket_buy, lots_buy, Bid, 0, clrYellow) == true) ticket_buy = 0; else Print("OrderClose error."); } // 売りポジション決済 if (ticket_sell > 0 && exit_sign == 1) { if (OrderClose(ticket_sell, lots_sell, Ask, 0, clrYellow) == true) ticket_sell = 0; else Print("OrderClose error."); }
OrderClose()関数の()括弧内は次のように指定します。OrderClose()関数の実行に成功したらtrueが返り、失敗したらfalseが返ります。
OrderClose(注文番号, ロット数, 決済価格, 許容スリッページ, 決済マークの色)
注文番号
決済するポジションの注文番号を指定します。
ロット数
決済する取引数量(ロットサイズ)を指定します。
決済価格
決済する価格を指定します。通常、買いポジションはBid、売りポジションはAskで決済します。ポジション選択中はOrderClosePrice()を使用してもよいです。
許容スリッページ
許容スリッページをポイントで指定します。
決済マークの色
EAでの取引でチャート上に自動的に表示される決済マークの色を指定します。
CloseOrder()関数で正常に決済されたら、注文番号格納用の変数の値を0にリセットします。決済注文に失敗したら、エラー出力するようにします。
保有ポジションを確認するセクションで宣言した変数ticket_buyは、買いポジションの注文番号を格納することで、ポジションの有無を判定するのにも使用できます。また、lots_buyにロット数を格納しておくことで、決済時にポジションを選択することなくOrderClose()関数を実行することができます。
OrderClose()関数にパラメーターのLotsでロット数を指定すると、ポジション保有中にパラメーターのLotsを変更した場合に部分決済するなど想定外の取引になる可能性があります。
エントリー注文処理
エントリー注文処理のセクションでは、次のコードのように最初のif()文を保有ポジション無し・エントリーしたローソク足ではないという条件にします。それを満たした上で、エントリーシグナルが出ている場合に、OrderSend()関数でエントリー注文をします。
if (ticket_buy == 0 && ticket_sell == 0 && entry_bar != Bars) { // 買いエントリー if (entry_sign == 1) { ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 0, 0, 0, NULL, MagicNumber, 0, clrBlue); if (ticket > 0) entry_bar = Bars; else Print("OrderSend error."); } // 売りエントリー if (entry_sign == -1) { ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, 0, 0, 0, NULL, MagicNumber, 0, clrRed); if (ticket > 0) entry_bar = Bars; else Print("OrderSend error."); } }
OrderSend()関数の()括弧内は次のように指定します。OrderSend()関数の実行に成功したらその注文番号が返り、失敗したら-1が返ります。
OrderSend(通貨ペア, 注文の種類, ロット数, 注文価格, 許容スリッページ, 逆指値決済価格, 指値決済価格, コメント, マジックナンバー, 有効期限, エントリーマークの色)
通貨ペア
通貨ペアを文字列で指定します。稼働チャートの通貨ペアを指定する場合は、Symbol()とします。
注文の種類
注文の種類は、次の6種類から選んで指定します。
買い成行き注文 | OP_BUY |
---|---|
売り成行き注文 | OP_SELL |
買い指値注文 | OP_BUYLIMIT |
売り指値注文 | OP_SELLLIMIT |
買い逆指値注文 | OP_BUYSTOP |
売り逆指値注文 | OP_SELLSTOP |
ロット数
取引数量(ロットサイズ)を指定します。
注文価格
エントリーする価格を指定します。成行き注文の場合、買い注文はAsk、売り注文はBidを指定します。
許容スリッページ
許容スリッページをポイントで指定します。
逆指値決済価格
ストップロス(SL)の価格を指定します。0を指定するとSL無しになります。
指値決済価格
テイクプロフィット(TP)の価格を指定します。0を指定するとTP無しになります。
コメント
注文のコメントを指定します。NULLを指定するとコメント無しになります。
マジックナンバー
注文のマジックナンバーを指定します。ちなみに手動取引のマジックナンバーは0です。
有効期限
指値・逆指値注文の場合、有効期限を指定できます。0を指定すると無期限になります。
エントリーマークの色
EAでの取引でチャート上に自動的に表示されるエントリーマークの色を指定します。
OrderSend()関数で正常に注文できたら、グローバル変数entry_barに現在のローソク足の本数を代入しておきます。注文に失敗したら、エラー出力するようにしています。
テスターでEA動作をチェック
コード入力が終わったらコンパイルボタンでコンパイルします。エラーなくコンパイルできたらテスターのビジュアルモードでEA動作を確認しましょう。
ビジュアルモードで表示されるチャートには、インジケーターを表示させることができるので、今回の場合でいうと単純移動平均線(期間20)のものを表示させて確認すると良いです。
移動平均線は、ナビゲーターウィンドウのインディケータ→トレンド→Moving Averageです。
あとがき
今回は初めてのEA作成される方に向けたシンプルなEAで解説してきましたが、いかがでしたか?
わからないところがあったらコメントくださいね^^
次回は、今回のEAをさらにカスタマイズする方法を紹介します。お楽しみに!
こんにちは
ブログ見ました。MT4の各種機能及びプログラムのことを詳しく述べられているのを見てただただ凄いなと感心しています。私にはまだまだできません。。。私は、素人ながら今、メタエディターを使用してプログラムを書いています。内容はMACDのシグナルが上向きになったら買い、下向きになったら売りというのを作っています。ですが、今躓いています。売買シグナルが作れないのですし、エラーが出ます。そこで、できればアドバイスをお願いしたいのですが。よければ後ほど不完全なプログラムを送りたいと思います。よろしくお願いします。
blockさん
こんにちわ。
慣れるまでは、分からないことがいっぱいで
意味不明なエラーが出てしまいますよね^^;
少しずつ、勉強して慣れていきましょうね!
はじめまして こんにちわ 自動売買システムを作りたくて、こちらのサイトにたどり着いた初心者です。
質問です。
// ポジション無しの場合
if(OrdersTotal()<1)という記述になっていますが、&l(エル?)t1というのは、1未満を指すお決まりの記号?みたいなものなのでしょうか?
宜しくお願いします
ぽんすけさん
こんにちわ!
&ltと表示されている場合は、『<』に置き換えて読んでください。
ブラウザの環境などで『<』に変換されないままになってしまってう場合があります。
Best Site Good Work
はじめまして
以前からこちらのサイトを参考に勉強させていただいています。
プログラミングのど素人の私でも理解できるよう書かれており
非常に感謝しております。
ただ、プログラムを作成していく中でどうしても思い通りに動いてくれず四苦八苦して
アドバイスをいただければと思いコメントさせていただきました。
内容は
Forceを使って目標値(judga)を一旦上回った後、目標値(judga-blank)を下回れば 売り。 といったものです。
プログラムは
if( iForce >= judga)
{
sig_a = 1;
}
if( sig_a == 1 && iForce < judga-blank)
{
sig_a = 2;
}
if( sig_a == 2 && CurrentPosition != -1)
{
sig_a = 0;
}
といった判別式の後sig_a==2の時に売りといった内容ですが
目標値を上回った段階で売りのサインが出てしまいます。
どうしてでしょうか?
突然の質問で申し訳ありませんがよろしくお願いします。
ぜんごんさん
こんにちわ!
適所に
Print(sig_a, “, “, iForce, “, “, judga, “, “, blank);
を入れて変数の値を調べると原因が判るかもです^^
はじめまして、素人の私のバイブルとして利用させてもらっています。
分かりやすい内容は、とても助かってます。
逆指値を移動平均線と同じ値で設定する事って出来ますでしょうか?
アドバイス下さい。
みんさん
こんにちわ^^
買い注文の時に、ストップをmaの値で設定する場合、
OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, NormalizeDouble(ma, Digits), 0, “Buy”, 10, 0, Blue);
とします。
注文時にTP・SLを設定できないブローカーの場合は、
ポジションを選択してから、OrderModifyでSLを設定します^^
慶次さん、はじめまして。
とってもわかりやすく説明してあり、とても勉強になります。
さて早速ですが、
下記のような変数の宣言を書いてみたのですが、
コンパイルすると、ものすごくエラーが出てしまいます。???…
void OnTick()
//変数の宣言—
double SIG2,SIG1,SIG0,SIG_1,SIG_2;
SIG2 = iBands(NULL,0,21,2,0,PRICE_CLOSE,MODE_UPPER,1);
SIG1 = iBands(NULL,0,21,1,0,PRICE_CLOSE,MODE_UPPER,1):
SIG0 = iBands(NULL,0,21,0,0,PRICE_CLOSE,MODE_MAIN,1);
SIG_1 = iBands(NULL,0,21,1,0,PRICE_CLOSE,MODE_LOWER,1);
SIG_2 = iBands(NULL,0,21,2,0,PRICE_CLOSE,MODE_LOWER,1);
真ん中を
SIG0 = iMA(NULL, 0, 21, 0, MODE_SMA, PRICE_CLOSE, 1);
に代えたりもしてみたのですが…
ボリンジャーバンドの2σ、1σ、移動平均線、-1σ、-2σの5本線で、
ひとつ前の終値での数値を得たい…と考えているのですが…。
う~ん?さっぱり
問題は解決しました。
エラーが出なくなりました。
ありがとうございました。
こんにちは、いつもブログを拝見させて頂いています。
とても勉強になります。
早速ですが、今あるeaの売りとても買いを逆に設定する事は可能でしょうか?
お忙しいところ申し訳ありませんが、御教授願います。
宜しくお願い致します。
お肉さん
コメントありがとうございます。
EAごとで適切な変更編集が違うと思いますが、条件文を売買逆に記述すればよいかと思います。決済条件も編集が必要になる場合もあります。