この記事は、MT4のMetaEditorを使ってMT4の自作EAを作る方法を紹介しています。
- MT4で自動売買がしてみたい
- MT4でバックテストがしてみたい
- 自動売買のEAを自作してみたい
MT4を使い始めると、EAを自分で作って自動売買することや、自分の取引手法を過去検証するためにバックテストをすることをしてみたくなります。しかし、私自身もそうですがプログラム作成なんてしたことがない初心者の方は、ネット上にアップされている無料のEAをダウンロードし、パラメータを変えることくらいしかできません。
・・・『ネットでダウンロードしたEA。。。決済をトレールにしたらもっと伸びるのに。。。』・・・
なんて思ったことないですか?MT4のエキスパート編集からEAをMetaEditorで開いてみると、訳の分からない文字が並んでいて、いきなりアレルギー反応。せっかく思いついた自分のアイデアを形に出来ずに悩んでいる方も多いと思います。
そんなMT4自作EA初心者を脱却し、自分で思い通りにEAを作成し、バックテストするまでを簡単に5つのステップだけで出来る方法を紹介します。
MT4自作EAの作り方 バックテストまでの5つのステップ
ここでは、短期の移動平均線と長期の移動平均線の交差で売買を行うEAの作成を紹介します。これさえマスターすれば、あとは仕掛け部分や決済方法などを書き変えるだけで、あなたのアイデアを形にしていくことができるようになります。
① MetaEditorでEA(エキスパートアドバイザ)を新規作成する
MT4の上部に並ぶアイコンの中から、虫眼鏡マーク(ストラテジーテスター)を探してクリックします。
虫眼鏡マーク(ストラテジーテスター)をクリックしたらこんな感じで四角い箱が出てきます。
右側に並んでいるボタンの中から『エキスパート編集』を選び、クリックしてください。
こんな感じで、MetaEditorのウィンドウが開きます。
MetaEditorの左上、『新規作成』ボタンをクリックします。
一番上の『エキスパートアドバイザ(テンプレート)』が選ばれている状態で、次へをクリック。
名前: Experts¥ のあとに作成するEAの名前を入力します。
こんな感じで、今回作るEAの名前は『test1』としました。
MetaEditorのWindow上に『test1.mq4』ってウィンドウが作成されていれば、1ステップ目終了です。これでほとんどEAが完成したも同然です。
② void OnTickの下に買い注文のEAプログラムを書く(コピペOK)
ステップ①で作成したEAを見てください。訳の分からない文字列の一番下あたりにOnTick()ってありましたか?
1 2 3 4 5 |
void OnTick() { //--- } |
ここにまずは買い注文を書いてみましょう。コピペでOKです。
1 2 3 4 5 |
void OnTick() { //--- OrderSend(Symbol(),OP_BUY,0.1,Ask,3,0,0); } |
OrderSend(***)って部分を新しく書きました。これが買い注文のプログラムです。OrderSendのかっこの中身は左から順番に書く内容が決まっています。
- 1つ目:Symbol() 売買する通貨ペア
- 2つ目:OP_BUY 買い注文 (売り注文ならOP_SELL)
- 3つ目:0.1 注文サイズ (国内業者なら0.1で1000通貨、XMとか海外業者なら0.1で10000通貨)
- 4つ目:Ask 買う価格 (成行買いなのでAsk、成行売りならBid)
- 5つ目:3 許容するスリッページ (pips単位、これ以上スベったら注文しない)
- 6つ目:0 損切価格の価格 (指定しないなら0)
- 7つ目:0 利益確定の価格 (指定しないなら0)
これだけです。
これを応用して注文するだけです。例を下に列挙します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//① 売りの注文を出したいなら OrderSend(Symbol(),OP_SELL,0.1,Bid,3,0,0); //OP_BUYをOP_SELLに変えるだけ ※売りの場合はAskをBidに //② 注文のサイズを0.2にしたいなら OrderSend(Symbol(),OP_BUY,0.2,Ask,3,0,0); //3つ目の0.1を0.2に変えるだけ //③ 20pips下落で損切にしたいなら OrderSend(Symbol(),OP_BUY,0.1,Ask,3,Ask-0.2,0); //6つ目の0をAsk-0.2に変えるだけ(クロス円とかの場合) // ユーロドルとかの場合、価格のpipsが違うので OrderSend(Symbol(),OP_BUY,0.1,Ask,3,Ask-0.002,0); //6つ目の0をAsk-0.002に変えるだけ //③ 30pips上昇で利確にしたいなら OrderSend(Symbol(),OP_BUY,0.1,Ask,3,0,Ask+0.3); //6つ目の0をAsk+0.3に変えるだけ(クロス円とかの場合) // ユーロドルとかの場合、価格のpipsが違うので OrderSend(Symbol(),OP_BUY,0.1,Ask,3,0,Ask+0.003); //6つ目の0をAsk+0.003に変えるだけ |
このOnTick()の下の波かっこに囲まれた部分は、Tickが動くたびに実行される部分です。つまり、108.92、108.93、108.94、108.91。。。って価格が変動するたびにここに書いたことが行われるってことです。もう一度プログラムを見てみましょう。
1 2 3 4 5 |
void OnTick() { //--- OrderSend(Symbol(),OP_BUY,0.1,Ask,3,0,0); } |
このままだと、注文サイズ0.1でTickごとに買い続ける怖ろしいEAになってしまいます。そこで次のステップでは、ポジションが無いときだけ注文するように変更していきます。
③ ポジションが無い時だけ注文するようにEAプログラムを変更する(コピペでOK)
1 2 3 4 5 6 7 8 |
void OnTick() { //--- if(OrdersTotal()==0) { OrderSend(Symbol(),OP_BUY,0.1,Ask,3,0,0); } } |
ここでifとOrdersTotal()って見たこともない文字が出てきてアレルギーを起こす方もいるでしょうが、これもコピペで大丈夫です。意味はこんな感じ。
OrdersTotal() は、すべての注文とポジションを合算した数のこと。買いのポジションが1つ、指値買いの注文が1つなら OrderTotal()=2ってことです。もちろん何も注文やポジションがなければOrderTotal()=0です。
1 2 3 4 5 6 |
//もし***ってことになったら、xxxxxxxを実行して! if(***) { xxxxxxx; } |
『if』って英語で『もしも***ならば』ってことですよね?プログラムでは条件分岐って言ったりするそうですが、結局『もしも』ってことです。このifの後ろのカッコの中に『もしも***ならば』の『***』部分を書きます。
で、波かっこの中に実行してほしい内容を書きます。
1 2 3 4 5 |
//今回の場合、『OrdersTotal()が0の時、買いの注文を入れて!』って命令なので if(OrdersTotal()==0) // ここがもしも~の部分 { OrderSend(Symbol(),OP_BUY,0.1,Ask,3,0,0); //波かっこの中に実行したい内容 } |
ついでに売りの注文も並べておきましょう。
1 2 3 4 5 6 7 8 9 10 11 |
void OnTick() { //--- if(OrdersTotal()==0) { OrderSend(Symbol(),OP_BUY,0.1,Ask,3,0,0); OrderSend(Symbol(),OP_SELL,0.1,Bid,3,0,0); } } |
次に移動平均線のロジックを書いていきます。
④ 移動平均線でEA仕掛けのロジックを書く (コピペOK)
ここから移動平均線のゴールデンクロスで買い、デッドクロスで売りのロジックを書いていきます。
- 2つ前のローソク足で、短期移動平均線<長期移動平均線、1つ前のローソク足で、短期移動平均線>長期移動平均線となれば買い
- 2つ前のローソク足で、短期移動平均線>長期移動平均線、1つ前のローソク足で、短期移動平均線<長期移動平均線となれば売り
まずは4つの移動平均線の値を取得します。長期は75日、短期は25日で作成。
1 2 3 4 5 6 7 8 9 10 11 |
// 2本前の短期移動平均線の値 double shortMA_2 = iMA(NULL,0,25,0,MODE_SMA,PRICE_CLOSE,2); // 2本前の長期移動平均線の値 double longMA_2 = iMA(NULL,0,75,0,MODE_SMA,PRICE_CLOSE,2); // 1本前の短期移動平均線の値 double shortMA_1 = iMA(NULL,0,25,0,MODE_SMA,PRICE_CLOSE,1); // 1本前の長期移動平均線の値 double longMA_1 = iMA(NULL,0,75,0,MODE_SMA,PRICE_CLOSE,1); |
iMAもカッコの中身の意味が左から決まっています。
- 1つ目:NULL (通貨ペア 指定が無い場合NULL)
- 2つ目:0 (時間足 指定が無い場合0)
- 3つ目:25 (移動平均足を計算する期間 今回は短期25日 長期75日で設定)
- 4つ目:0 (移動平均線をそのままの形で動かす足の本数 動かさなければ0)
- 5つ目:MODE_SMA (移動平均の計算方法 指数移動平均ならMODE_EMA)
- 6つ目:PRICE_CLOSE (どの価格で計算するか指定)
- 7つ目:1 (現在の足を0として、何本前の足にするか)
期間を変えたい場合は、25や75の値を変えればOKです。
次にロジックですが、これも上に書いた『if』を使って『もしも***ならば、買い』みたいな感じで書きます。大なり小なりは中学校くらいで習った不等号(<とか>とか)で書きます。
1 2 3 4 5 6 |
// もしも2つ前の短期が長期より下で、1つ前の短期が長期より上(短期が長期をゴールデンクロス)ならば買い if(shortMA_2 < longMA_2 && shortMA_1 > longMA_1) { OrderSend(Symbol(),OP_BUY,0.1,Ask,3,0,0); } |
同じようにして、デッドクロスで売り注文も書いていきます。
1 2 3 4 5 6 |
// もしも2つ前の短期が長期より上で、1つ前の短期が長期より下(短期が長期をデッドクロス)ならば売り if(shortMA_2 > longMA_2 && shortMA_1 < longMA_1) { OrderSend(Symbol(),OP_SELL,0.1,Bid,3,0,0); } |
EAって単純で、結局このif文の繰り返しだけでOKです。こういう条件になったら買いたい、こういう条件になったら売りたいって条件をifの後ろのカッコの中に書くだけでOKです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
void OnTick() { //--- double shortMA_2 = iMA(NULL,0,25,0,MODE_SMA,PRICE_CLOSE,2); double longMA_2 = iMA(NULL,0,75,0,MODE_SMA,PRICE_CLOSE,2); double shortMA_1 = iMA(NULL,0,25,0,MODE_SMA,PRICE_CLOSE,1); double longMA_1 = iMA(NULL,0,75,0,MODE_SMA,PRICE_CLOSE,1); if(OrdersTotal()==0) { if(shortMA_2 < longMA_2 && shortMA_1 > longMA_1) { OrderSend(Symbol(),OP_BUY,0.1,Ask,3,0,0); } if(shortMA_2 > longMA_2 && shortMA_1 < longMA_1) { OrderSend(Symbol(),OP_SELL,0.1,Bid,3,0,0); } } } |
まとめるとこんな感じです。でもこれではまだ決済がされないので、最後のステップで決済注文を作っていきます。
⑤ 決済注文を作成する
例えば、損切20pips、利確30pipsの場合、以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
void OnTick() { //--- double shortMA_2 = iMA(NULL,0,25,0,MODE_SMA,PRICE_CLOSE,2); double longMA_2 = iMA(NULL,0,75,0,MODE_SMA,PRICE_CLOSE,2); double shortMA_1 = iMA(NULL,0,25,0,MODE_SMA,PRICE_CLOSE,1); double longMA_1 = iMA(NULL,0,75,0,MODE_SMA,PRICE_CLOSE,1); if(OrdersTotal()==0) { if(shortMA_2 < longMA_2 && shortMA_1 > longMA_1) { OrderSend(Symbol(),OP_BUY,0.1,Ask,3,Ask-0.2,Ask+0.3); } if(shortMA_2 > longMA_2 && shortMA_1 < longMA_1) { OrderSend(Symbol(),OP_SELL,0.1,Bid,3,Bid+0.2,Bid-0.3); } } } // ドル円などの場合はAsk-0.2ですが、ユーロドルなどならAsk-0.002になります。 |
ゴールデンクロスで買い、デッドクロスで売りを繰り返す場合。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
void OnTick() { //--- double shortMA_2 = iMA(NULL,0,25,0,MODE_SMA,PRICE_CLOSE,2); double longMA_2 = iMA(NULL,0,75,0,MODE_SMA,PRICE_CLOSE,2); double shortMA_1 = iMA(NULL,0,25,0,MODE_SMA,PRICE_CLOSE,1); double longMA_1 = iMA(NULL,0,75,0,MODE_SMA,PRICE_CLOSE,1); // ポジションが無い場合、普通に注文 if(OrdersTotal()==0) { if(shortMA_2 < longMA_2 && shortMA_1 > longMA_1) { OrderSend(Symbol(),OP_BUY,0.1,Ask,3,0,0); } if(shortMA_2 > longMA_2 && shortMA_1 < longMA_1) { OrderSend(Symbol(),OP_SELL,0.1,Bid,3,0,0); } } //もし逆方向のポジションがあるなら、そのポジションを決済してから注文 if(OrdersTotal()>0) { if(shortMA_2 < longMA_2 && shortMA_1 > longMA_1) { if(OrderSelect(0, SELECT_BY_POS, MODE_TRADES) == true && OrderType()==OP_SELL) { OrderClose(OrderTicket(),0.1,Ask,3); OrderSend(Symbol(),OP_BUY,0.1,Ask,3,0,0); } } if(shortMA_2 > longMA_2 && shortMA_1 < longMA_1) { if(OrderSelect(0, SELECT_BY_POS, MODE_TRADES) == true && OrderType()==OP_BUY) { OrderClose(OrderTicket(),0.1,Bid,3); OrderSend(Symbol(),OP_SELL,0.1,Bid,3,0,0); } } } } |
追加したのは以下の3点です。
- if(OrdersTotal()>0) : 注文がある場合にだけ実行
- if(OrderSelect(0, SELECT_BY_POS, MODE_TRADES) == true && OrderType()==OP_SELL)
売りのポジションがある時だけ実行する命令
if(OrderSelect(0, SELECT_BY_POS, MODE_TRADES) == true && OrderType()==OP_BUY)
買いのポジションがある時だけ実行する命令 - OrderClose(OrderTicket(),0.1,Ask,3)
売りポジションを決済するための命令
左から、チケット番号、注文サイズ、価格(成行だとAskかBid)、スリッページです。
どちらも『if』で『もし***ならば』で書いているだけです。『もしポジションが0以上ならば』とか、『ポジションが売りポジションならば』とか。
最後にコンパイルボタンを押せば、EA完成です。お疲れさまでした。
MetaEditorで自作したEAでバックテスト検証してみる
① MT4でストラテジーテスタを表示する
エキスパート編集する前のこの画面を表示します。
② 通貨ペアや期間を指定する
上から順番に以下のように設定します。
- EAは、今回作成したEAである『test1.ex4』を選択します。
- 通貨ペアは、今回はUSD/JPYにしました。
- モデルは始値で動かすロジックなので、『始値のみ』でOKです。
- 期間を指定にチェックを入れ、お好きな開始日と終了日を選択します。
- ビジュアルモードはチェック無しでOKです。
今回は、期間を15分足(M15)、スプレッドを10(1pips)で計算しました。スプレッドが0.3pipsとかなら、スプレッドを3とかにしてください。
最適化はチェック無しで、右下のスタートを押します。
③ チャートを開くで売買ポイント確認
エキスパート編集の上の『チャートを開く』ボタンを押すと、売買ポイントが示されたチャートを開くことが出来ます。
ロジック通りの正しい位置で売買が出来ているか確認しましょう。
④ グラフとレポートで結果を確認
ストラテジーテスタの下には5つのタブがあります。
- セッティング : 最初の画面
- 結果 : 全売買記録
- グラフ : 損益曲線
- レポート : 詳細な数値結果(PFとか)
- 操作履歴 : いわゆるログです。売買エラーとかここで分かります。
まずは、グラフタブをクリックして損益曲線を見てみましょう。
バックテストの結果を表したグラフです。たった2週間分なので、何とも言えませんが12月頭から動かしていたら、現在プラスのようです。なお、20ドルくらいマイナスの期間もあったことが分かります。
次に、レポートで詳細を確認します。
プロフィットファクタが1.1以上でドローダウンが小さいEAが出来たら、なかなか良いEAと言えるでしょう。
⑤ 検証期間を伸ばして、再度バックテストしてみる
最後に、2015年1月1日から今日(2019年12月15日)まで動かした結果を見てみます。
見事に右下下がりです。
つまり、USD/JPYの15分足で25日移動平均線と75日移動平均線のクロスだけでトレードしても勝てないってことが分かったかと思います。
この次に考えることとしては、以下のような手法があるかと思います。
- 時間軸を変えてみる。長い時間軸の方が、クロスに正直に動く???
- 損切と利確を入れてみる。損小利大になるPipsは???
- 利益を最大化するために、トレール注文にしてみる。
- 利確に別のロジックを入れてみる。ボリンジャーバンドの2シグマを超えたら決済とか。。。
- そもそも移動平均ではなくて、ローソク足やトレンドラインでロジックを考え直す?
- 玉操作を取り入れたナンピン手法などを取り入れてみる?
- 価格の上下を予想せずに、トラリピでコツコツ稼いでみる?
今後、これらのロジックをMT4にて作成し、バックテストを行い、結果を公開していこうと思います。
長文読んでいただき、ありがとうございます。MT4自作EAの参考になれば幸いです。
まとめ
MT4で自作EAを5つのステップで簡単に作成する方法を紹介しました。
- MetaEditorで新規作成
- onTickにOrderSendで注文を書く
- if文とOrdersTotalで、ポジション数に応じた条件分岐
- 適切なタイミングで注文されるように、if文にロジックを書く
- 決済方法を書く
EA作成時に注意すべきは、以下の3点だけです。
- 注文は、onTickの中に書いていく
- ロジックは、ifを使い『もしも***ならば』で書いていく
- バックテストの結果を見て、ロジックを調整していく
アイデアはあるけど、書けない方などいましたら、コメントいただけると頑張って作ってみようと思います。