EA開発 Part4 パラメーターと最適化
前回は「買い」と「決済」の条件に時刻を追加し、「9時に買い、18時に決済する」というEAを作りました。
今回は「9持」と「18持」を「パラメーター」に変更して、「最適化」できるようにしていきます。
パラメーターに変更
まずは今回使うパラメーターを定義してみましょう。
一般的にソースコードの上部、OnInit()の上に定義します。
input int StartHour = 9; input int StopHour = 18; //+------------------------------------+ //| Expert initialization function | //+------------------------------------+ int OnInit()
最初の2行が追加した行です。
パラメーターを定義する際には最初にinputをつけた後に、型、そして名前と初期値を定義します。
1行目の場合、int は「整数型(整数のみ)」を意味しており、名前はStartHour、初期値は9です。
2行目も同様、StopHourという名前で初期値は18としています。
ちなみにint(整数型)以外では、double(倍精度浮動小数点型)とstring(文字列型)をよく使います。
「倍精度浮動小数点型」というのは何か難しそうですが「小数を使う場合にはdoubleを使用する」くらいに考えておけば問題ないと思います。
次に、前回追加した条件文(if文)を変更して、このパラメーターに置き換えます。
if(Hour() == StartHour && OrdersTotal() == 0)
9という数字をStartHourに置き換えました。
同様に18も置き換えます。
if(Hour() == StopHour && OrdersTotal() > 0)
これでパラメーターへの置き換えは終了です。
簡単ですね!これをコンパイルして実行すると、前回と同じ結果になります。
初期値が9と18ですから、StartHourに9、StopHourに18が代入されるからです。
パラメーターにすることで実行時に値を変更できる
バックテストの「エキスパート設定」の「パラメーター入力」を御覧ください。
先ほど追加したパラメーターが表示されています。
値はStartHourが9、StopHourが18です。この値を書き換えることで「異なる条件」でバックテストすることができます。
しかし、1回1回設定を書き換えて実行するのは面倒です。そこで「最適化」という機能を使います。
(この最適化を使うことが、パラメーターに変えた最大の理由です)
※「初心者向け」の記事ですので、最適化の手順も以下に書きます。「最適化の方法は知っているよ!」という方は「OrderSend関数について」まで飛ばしてください。
最適化
最適化の設定は簡単です。値の範囲と増加させる値を指定します。
たとえばStartHourを0から11まで増加させるとして、1ずつ増加させる場合には以下のように設定します。
スタートが0、ステップが1、ストップが11。
同様にStopHourも設定します。スタート12、ステップ1、ストップは23とします。
設定したらOKボタンを押してください。
※StartHourとStopHourにチェックがついていることも確認してください。チェックが無いと最適化の対象になりません。
次にバックテストの右にある「最適化」のチェックを付けてスタートボタンを押します。
これで自動的に「指定した範囲(スタートからストップ)」の値を代入して実行してくれます。
※実行回数はStartHourが12パターン、StopHourが12パターンですので、144回となります。
※期間を長くするとすごく時間がかかります。短めに設定してください。
2015年1月から2016年7月でバックテストした結果は以下のようになっています。(最適化した場合、最適化結果タブに結果が表示されます)
私の実行結果ではStartHourが10、StopHourが23の場合にPF(プロフィットファクター)が1.04で、損益+344.04ドルと一番良い結果になるようです。
任意の結果をダブルクリックすると、その設定が適用されます。
早速、一番良かった結果をダブルクリックしてスタートボタンを押し、バックテストの結果を確認してみました。
とりあえずバックテストで「利益が出る」EAができました。
OrderSend関数について
少し短いので、ここでOrderSend関数の使い方について簡単にご説明いたします。
OrderSendo関数は以前紹介しましたように「発注」をする関数です。
OrderSend(Symbol(),OP_BUY,0.1,Ask,2,0,0,"",123456,0,clrBlue);
()の中にカンマ区切りで書いている値を「引数」と言って、関数が実行する際に渡す値です。
最初にシンボル(通貨ペア)を指定します。Symbol()と書くと自動的に「現在の通貨ペア」が渡されます。
次に注文方法、OP_BUYは成行買い、OP_SELLは成行売りです。
他にOP_BUYSTOPとOP_SELLSTOPという逆指値注文、OP_BUYLIMMIT、OP_SELLLIMMITという指値注文があります。
その後ろがLot(サイズ)です。これはパラメーターにするべきですね。
次は売買価格です。Askと書くと現在のAsk(買値)、Bidと書くと現在のBid(売値)が指定されます。
成行でとにかく発注したい場合にはAsk、Bidと書けばよいでしょう。
逆指値や指値で注文する場合には、ここに売買したい価格を指定します。
その次の2と書いている所は許容するスリッページです。これもパラメーターにすると良いでしょう。
その後ろがストップロス価格の設定です。今回は設定していないので0としています。
次の0はテイクプロフィット価格の設定です。こちらも設定していないので0にしています。
その次がコメントです。発注時にコメントを付加したい場合には文字列を渡します。
その次の123456というのはMagicナンバーと言って、EAで発注した場合にどのEAが発注したのか判別できるように他のEAと異なる値を設定します。
これもパラメーターにしておいて、変更できるようにしておくと良いでしょう。
その後ろは注文の有効期限です。有効期限が不要の場合には0を指定します。(期限はdatetime型という型で指定する必要があります)
最後が色の指定です。売買の矢印の色などが指定した色になります。clrBlueは青です。clrと入力すると色のリストが表示されるので好きな色を指定して下さい。
それでは、ざっとパラメーター化してみましょう。
OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,0,0,OrdersComment,Magic,0,clrBlue);
数値を指定しただけでは「どの値がどの設定か」分かりづらかったと思いますが、パラメーターにすることでわかりやすくなりました。
(StopLossとTakeProfitをパラメーターにするためには価格を計算しないといけないので今回は0のままにしています)
パラメーター化した修正版のソースコードは以下のようになります。(OrderSendの変更とパラメーターを追加しています)
//+------------------------------------------------------------------+ //| ZeroCreatePart2.mq4 | //| | //| | //+------------------------------------------------------------------+ #property copyright "" #property link "" #property version "1.00" #property strict input int Magic = 123465; input double Lots = 0.1; input int Slippage = 2; input string OrdersComment = "ZeroCreate"; input int StartHour = 9; input int StopHour = 18; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { if(Hour() == StartHour && OrdersTotal() == 0) { OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,0,0,OrdersComment,Magic,0,clrBlue); } if(Hour() == StopHour && OrdersTotal() > 0) { for(int i=0; i<=OrdersTotal()-1; i++) { if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) == false) break; OrderClose(OrderTicket(),OrderLots(),Bid,2,clrBlue); } } } //+------------------------------------------------------------------+
OrderSend関数の詳細を知りたい方は以下のサイトでご確認ください。
「使い方はどうだったかな?」と確認する際にとても便利なサイトです。
まとめ
- パラメーターの定義方法
- 最適化のやり方
- OrderSend関数の使い方
OrderSend関数の説明を無理やり入れたのでボリュームが大きくなってしまいました。
「引数」が多いので初心者の方は「なんだこれ・・・!難しい!」と思われたかも知れませんが、暗記する必要は無いのでご安心ください。
(わかるようにパラメーターの名前をつけておけば後で見てもわかりますし、それでもわからないときはリファレンスを見ればOKです。)
もし意味がわからない箇所がありましたら、お気軽にコメントください。
※大変申し訳ございませんが、当記事に直接関係のないコメントはご遠慮頂ますようお願い致します。
次回は、今回はパラメーター化しなかった「ストップロス」と「テイクプロフィット」のパラメーター化と、クローズ時に使用しているforループ、それとOrderClose関数について解説する予定です。
以上、初心者向けEA講座「自動売買システムを作ろう!ゼロから始めるEA開発Part4 パラメーターと最適化」でした。
コメント