ここでは、MetaTrader4のEAの処理速度を高める方法と、テスターでEAのパラメーターを最適化する方法を紹介します。
前回記事で作成したEAのコードで説明します。EAのコードは前回記事で確認するかEAファイルをダウンロードして確認してください。
前回作成したEA【MA_Doten_EAv1.01.mq4】をダウンロード
EAの処理速度を高める方法
EAの処理速度を高める方法として一番効果的なのが、無駄な処理をしないことです。
前回記事で作成したEAは、バックテストの「始値のみ」と「全ティック」では、異なる結果になります。
このEAの場合、シグナルが発生しているローソク足の途中でTP/SL決済したタイミングではエントリー注文をします。
上記のように、ローソク足の途中で取引注文の処理がある場合、バックテストの「始値のみ」と「全ティック」では、異なる結果になります。
EAをローソク足の始値のみで実行させる方法
EAをローソク足の始値のみで実行させたい場合は、次のコードをOnTick()関数の最初に追加します。
// ローソク足1本につき始めの1回のみ実行する --------- static datetime last_run_time = 0; if (last_run_time == Time[0]) return; last_run_time = Time[0];
変数宣言の前にstaticを付けると、グローバル変数のように格納されている値がティック毎にリセットされることなく次のティックでも利用できるようになります。
datetimeは日時のデータ型です。Time[0]は、現在のローソク足の始値時点での日時です。
これでバックテストを行うと始値のみと全ティックは同じ結果となります。
テストに要する時間は、始値のみの方が圧倒的に短いです。
シグナルをローソク足の始値のみで発生させる方法
このEAには無いですが、トレーリングストップ機能などでローソク足の途中でも実行したい処理がある場合は、EA実行全体を始値時点のみにするのは不都合ですので、ここでは、シグナル発生を始値のみにする方法を紹介します。
(先ほど追加したコードは削除しておいてください。)
int entry_sign = 0; // エントリー用シグナル int exit_sign = 0; // 決済用シグナル
上記コードの次からのシグナル判定部分を次のように変更します。
// ローソク足1本につき始めの1回のみ判定する ---------
static datetime last_calc_time = 0;
if (last_calc_time != Time[0])
{
last_calc_time = Time[0];
// MAの値を取得
(中略)
}
このように、全てのティックで処理する必要のないものを、処理タイミングの限定をすることでバックテストや最適化に必要な時間を短縮することができます。
【MA_Doten_EAv1.02】はコードミスがあったため、次のバージョンをダウンロードしてください。
今回の完成EA修正版【MA_Doten_EAv1.03.mq4】をダウンロード
EAのパラメーターを最適化する方法
MetaTrader4では、EAのパラメーター設定で複数のパターンを一度にバックテストする機能があります。その機能を使って成績がよいパラメーターの組み合わせを見つけていく作業を最適化といいます。
最適化を行う場合の設定方法は、バックテスト+αなので、バックテストの設定方法がわからない方は次の記事をご参照ください。
過去記事【MetaTrader4のテスター機能でEAの良し悪しを判断する】へ
最適化にチェック
セッティングタブの右側に最適化という項目があるので、それにチェックをいれます。無い場合は、MT4を最大化してみてください。
最適化の組み合わせを決める
エキスパート設定のパラメーターの入力タブで、次の画像のように設定パターンを複数にしたいパラメーターの左側のボックスにチェックをいれます。
左側のチェックを入れていないパラメーターは、値の列に入力されている値が使用されます。
チェックを入れたパラメーターは、スタート・ステップ・ストップで指定した値が使用されます。
先ほどの画像でStopLossやTakeProfitは、スタートが100・ステップが100・ストップが1000なので、100, 200, 300, ・・・, 1000の10パターンがテストに使用されます。
MA_Peroidは、10, 20, 30, ・・・, 100の10パターンです。
10パターン3つのそれぞれの組み合わせの1000パターンをテストすることになります。1パターン1分かかるとしたら全部で1000分(約17時間)かかります。
最適化を行う前に、EAの処理速度を高めることと、最適化するパラメーターとその範囲を絞ると時間短縮になります。
最適化を開始する
テスターのスタートボタンをクリックすると、最適化が開始されます。
最適化が開始されると、最適化結果タブと最適化グラフタブが追加され、最適化終了までの推定時間がスタート/ストップボタンの上に表示されます。
最適化結果の見方
最適化結果タブには、テストする組み合わせが終わったものから結果データが追加されていきます。損益がマイナスのものも表示されるようにするには、右クリックして「マイナスの結果を表示しない」のチェックを外します。
表の項目の部分をクリックすると、その項目で昇順・降順にソートできます。
最適化終了後、結果の1つを右クリックして「パラメータの設定」をクリックすると、パラメーターの値にその組み合わせの値がセットされます。
その状態でバックテストをすると、そのパラメーターでのレポート詳細を見ることができます。
あとがき
今回は、EAの処理速度の高め方と、パラメーターの最適化の方法を紹介しました。
オリジナルのEAを作成したら、ぜひこの記事を参考に実行してみてください。
このシリーズですが、自動売買のむずかしい部分を判りやすく説明していただき、大変勉強になります。ありがとうございます。
YUMEさん
こんにちわ!
コメントありがとうございます^^
自動売買のプログラムは難しいところもありますが、慣れてくると楽しいです^^
がんばりましょうね!
はじめまして
EAのプログラムに挑戦してみようと、いろいろと勉強させてもらっています。
非常に解りやすくて、助かります。
プログラムの件で質問があります。
例えば、移動平均線のゴールデンクロス、デットクロスのEAを何とか作成したのですが、
手動で止めてやらないとどんどん売買されてしまします。
一度だけエントリーし決済したら止まるようにするには、どのようにすれば可能ですか?
ATOMさん
こんにちわ^^
エントリしたときに、エントリしたということを記憶用変数に覚えてもらって、
エントリ条件にまだエントリしていないということを加えればOKだとおもいます。
この記事では、
エントリしたときに、
nowbar = Bars;
として、エントリしたローソク足の番号(数)を覚えてもらって、
その足では、もうエントリしないように
if(nowbar != Bars && ・・・
としてますが、
それを、1回エントリしたらもう2度とエントリしない
という条件に変更すればよいです。
1つ注意点があり、記憶用変数(グローバル変数)は、
EAを外したときにリセットされますので、
パラメータ再設定などでは、前の記憶が残ってます。
パラメータ再設定などでも、値をリセットするには、
init()関数の中で初期値を代入するといった処理が必要です。
この記事のEAでいうと
int init()
{
nowbar = 0;
…
として、
エントリ条件文を
if(nowbar == 0 && ・・・
とすれば、1回のみのエントリということになります。
nowbar を、entry_flag としてbool型にして、
true/falseで判定するのが自然ですかね^^;
はじめまして
最近EAのプログラム作りをはじめました。
さっそく質問なんですがつくってみた
ExpertAdvisorをバックテストしてみたのですが
結果やグラフが表示されないのですが
どうしてなのでしょうか?
maronさん
こんにちわ。
>バックテストしてみたのですが結果やグラフが表示されない
取引回数が0だと、結果やグラフが表示されません^^;
質問させてください
今二つの移動平均線のクロスをした際に売買を行い、
合図として矢印を表示させたく、あるひな形をもとに
作成してみたのですが矢印が表示されません。
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Orange
#property indicator_color2 Green
#property indicator_color3 Blue
#property indicator_color4 Red
//指標バッファ
double BufFastMA[];
double BufSlowMA[];
double BufBuy[];
double BufSell[];
//外部パラメーター
extern int FastMA_Period = 10;
extern int SlowMA_Period = 40;
int init()
{
//—- indicators
SetIndexBuffer(0,BufFastMA);
SetIndexBuffer(1,BufSlowMA);
SetIndexBuffer(2,BufBuy);
SetIndexBuffer(3,BufSell);
SetIndexStyle(2,DRAW_ARROW);
SetIndexStyle(3,DRAW_ARROW);
SetIndexArrow(2,233);
SetIndexArrow(3,234);
//—-
return(0);
}
int start()
{
//—-
int counted_bar = IndicatorCounted();
int limit = Bars-counted_bar;
if(counted_bar==0) limit -= SlowMA_Period-1;
for(int i = limit-1 ; i>=0 ; i–)
{
BufFastMA[i]=iMA(NULL,0,FastMA_Period,0,MODE_SMA,PRICE_CLOSE,i);
BufSlowMA[i]=iMA(NULL,0,SlowMA_Period,0,MODE_SMA,PRICE_CLOSE,i);
}
//売買シグナルの生成
if(counted_bar == 0) limit -= 2;
for(i=limit-1; i>=0; i–)
//買いシグナル
BufBuy[i]=EMPTY_VALUE;
if(BufFastMA[i+2] BufSlowMA[i+1])
BufBuy[i] = Open[i];
//売りシグナル
BufSell[i]=EMPTY_VALUE;
if(BufFastMA[i+2]>=BufSlowMA[i+2]
&& BufFastMA[i+1] < BufSlowMA[i+1])
BufSell[i] = Open[i];
//—-
return(0);
どこが悪いのかがわかりません。
どうかご指摘いただけないでしょうか
ながながと申し訳ないですがどうぞよろしくお願いします。
maronさん
こんにちわ^^
途中抜けて表示されているところがありチョット分りづらいですが、
売買シグナルの生成のfor文の{}はありますか??
お返事ありがとうございます。
自己解決できました、すみません。
余談なんですが、現在参考書やサイト等をつかって毎日取り組んでいるのですが
なかなか思うように進めていくことができず、このままやり続けてマスターする
ことができるのかと不安になったりします。
慶次さんをはじめ、みなさん独学でやってきたのでしょうか?
慶次さんがどのように取り組まれたのか、また○○をしたらいいよというのが
あれば是非聞かせてください。
私事で申し訳ないですがよろしくお願いします。
maronさん
こんにちわ!
解決されてよかったです^^
MQLのスキルアップ法ですが、興味のあるフリーのEAやインジケータのコードを
読み解いてみると新しい発見などがあり、面白いかもですね^^
特に、マスターするということを考えず、作りたいEAやインジケータに必要な知識を
身につけていくという感じの方が、楽しく覚えられるのではと思います^^
和訳リファレンス
https://www.dr-ea.com/meta-blog/mql/mqlreference-metaeditor2.html
が便利ですのでオススメです^^
アドバイスありがとうございます^^
さっそく気持ちを切り替えてやっていこうと思います。
いつもいつもお世話になっております。
前のご連絡よりフリーのインジケータに売買シグナルを出したく試みているのですが、まったく上手くいきません。
ちなみに今やっているのは
http://fxforex.sakura.ne.jp/mt4indicators/Big%20trend.mq4
のインジケータで、UptrendとDntrendのかわりめに矢印をひょうじさせたいので、
よろしければ教えていただけないでしょうか。
いつも初歩的なことで恐縮ですがよろしくお願い致します。
maronさん
こんにちわ!
ご連絡いただいたインジケータについてですが、
2つのローソク足にまたがってEMPTY_VALUEでないときに、はじめてそのラインが表示されます。
例えば、
Uptrend[1]とUptrend[0]に値が入っている時は、現在のところに水色を表示するようにしています。
それを踏まえて、条件式をつくるといいのですが、
変わり目の部分は、UptrendとDntrendの両方に値が入っていてその前の状態で判断するとよいかもです。
しかし、1またぎだけ反転してすぐに戻ったときの表示が特殊です。
水色の線を太くして表示させるとその部分の状態がわかります。
(同じ太さに戻すと、水色が弱くて、トマト色が強い感じです)
その特殊な状態も条件式に入れると、よいのではないでしょうか^^
お返事ありがとうございます。
まだまだ勉強不足で中身を解析できていないため、
上手くいかせてないですが、なんとなくは理解できるので、
やってみようとおまいます。
あつかましいのは承知のうえ、これからもアドバイスのほう
おねがいできたらと思います。
よろしくお願致します。
お世話になっております。
今回も質問なのですが、現在、前にとりくんでいた、
http://fxforex.sakura.ne.jp/mt4indicators/Big%20trend.mq4
のインジケータをEA化したく勉強しているのですが、
今の私のレベルでは中身を理解するのは困難で、関数を調べたり
いろいろなサイトやブログで見聞きしているのですが、
理解することができず前に進まないため悩んでいます。
よろしければ、何をすれば(どのように勉強していけば)理解が深まるのか、
ご教授いただけないでしょうか。
よろしくお願いします。
お世話になっております。
今回も質問なのですが、現在、前にとりくんでいた、
http://fxforex.sakura.ne.jp/mt4indicators/Big%20trend.mq4
のインジケータをEA化したく勉強しているのですが、
今の私のレベルでは中身を理解するのは困難で、関数を調べたり
いろいろなサイトやブログで見聞きしているのですが、
理解することができず前に進まないため悩んでいます。
よろしければ、何をすれば(どのように勉強していけば)理解が深まるのか、
ご教授いただけないでしょうか。
よろしくお願いします。
maronさん
こんにちわ!
iCustom関数で値を取得する場合、思い通りの値が取得できているかどうかを、
Comment関数やPrint関数などで、確認しながら進めるといいかもしれませんね^^
初めまして。質問失礼します。
本文中の下記の部分のifの使い方がわかりません。
if( ) return;
{ } ←これは何に掛かる括弧でしょうか?
↓該当箇所
// ローソク足1本につき始めの1回のみ判定する ———
static datetime last_calc_time = 0;
if (last_calc_time == Time[0]) return;
{
last_calc_time = Time[0];
// MAの値を取得
(中略)
}
よろしければ回答お願いします。
hiyokoさん
コメントありがとうございます。
完全にコードミスです。記事とダウンロードファイルを修正しましたのでそちらをご参照ください。
コメント頂けてとても助かりました。ありがとうございました。
ご返信ありがとうございます!MA_Doten_EAv1.03が保存できる形式が訂正前と異なっておりダウンロード後に開くことができませんでした。恐縮ですがよろしければご確認よろしくお願いします。
hiyokoさん
コメントありがとうございます。
ご不便おかけし申し訳ございません。修正しましたので再度お試しくださいませ。