エントリー判定関数とは?
EA(自動売買プログラム)を作成するにあたり、エントリー条件がそのプログラムの根幹になっていることは多いです。
問題は、そのエントリー条件をどのように記述していくか?
という事です。
もちろん「もし~の条件になったら買う、売る」という記述をするのですが、
メインプログラムといえるOnTick関数内にそれらすべてを記述していくと、コード自体が長く猥雑なものになりがちですし、開発を進めていく中で、プログラムが想定しているような挙動にならないときに、
コードのどの部分が間違っているのか把握できない、という事が往々にしてあります。
そこで、上記のような問題を解決するために、エントリー判定は関数を別に作って、そっちでやってもらおう!
という訳です。
関数を作ることによって、メインプログラム内の記述もスリム化できますし、
プログラムの挙動に問題が発生した時に、どの部分の記述に問題があったのか、切り分けが容易になります。
エントリー判定関数導入のロードマップ
以下の手順でコードを記述していきます
- 標準ライブラリのトレードファイルをインクルードし、CTradeクラスのインスタンスを宣言
- OnTick関数内にエントリーシグナルを受け取る変数を宣言
- OnTick関数内にその他取引に必要な値を取得し、発注命令を記述
- グローバル領域に判定関数を定義
標準ライブラリのトレードファイルをインクルードし、CTradeクラスのインスタンスを宣言
発注回路をOnTick関数内に簡単に組み込むために、Trade.mqhをインクルードして、CTradeクラスのインスタンスを生成します。
#include <Trade\Trade.mqh>
//標準ライブラリーのトレードファイルを使えるようにする
CTrade trade;
// CTradeクラスのインスタンスを宣言
OnTick()内にエントリーシグナルを受け取る変数を宣言
後ほど、グローバル領域に定義を書いていくエントリー判定関数CheckEntry()は文字列を
戻り値として返す想定なので、string型の変数entrySignalを用意します。
//エントリーシグナルを格納する変数を宣言
string entrySignal=CheckEntry();
OnTick()内にその他取引に必要な値を取得し、発注命令を記述
変数entrySignalが受け取る売買シグナルがbuyで、ノーポジなら買い注文を、
変数entrySignalが受け取る売買シグナルがsellで、ノーポジなら売り注文を、
という発注回路にしました。
相場状況の変化に伴うエントリー条件判定を関数に担わせ、「ノーポジなら」という口座状況の判定はOnTick関数内で行うよう、条件判定を分割させた形になるでしょうか?
今回のような単純な条件であれば、特に問題が生じることもないでしょうが、
エントリー条件が複雑になっていくと、このような配慮が必要になってくることもあるかと思います。
//現在値の取得と正規化
double Ask=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
double Bid=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
if(entrySignal=="buy" && PositionsTotal()==0)
{
//買い注文
trade.Buy(0.01,NULL,Ask,0,Ask+100*_Point);
}//if(entrySignal=="buy" && PositionsTotal()==0)
if(entrySignal=="sell" && PositionsTotal()==0)
{
//売り注文
trade.Sell(0.01,NULL,Bid,0,Bid-100*_Point);
}//if(entrySignal=="sell" && PositionsTotal()==0)
}//void OnTick()
グローバル領域に判定関数を定義
エントリー条件はMACDをベースにしました。
MACDのメインラインが0を上回っているときは文字列”sell”を、
MACDのメインラインが0を下回っているときは文字列“buy”を、戻り値として返す、という単純な判定です。
//エントリ-チェック関数の定義
string CheckEntry()
{
//シグナル用の文字列変数を宣言
string signal="";
//価格を格納する配列を宣言
double priceArray[];
//MACDのハンドルを取得
int macdHandle=iMACD(_Symbol,_Period,12,26,9,PRICE_CLOSE);
//配列を時系列にセット
ArraySetAsSeries(priceArray,true);
//MACDのメインライン値を取得し、配列に格納
CopyBuffer(macdHandle,0,0,3,priceArray);
//現在足のMACD値を変数に格納
double macdValue=priceArray[0];
//MACDの0ラインを基準として売買シグナルを発出
if(macdValue>0)signal="sell";
if(macdValue<0)signal="buy";
Comment("シグナル: ",signal);
//戻り値としてsignalを返す
return signal;
}//string CheckEntry()
全体のプログラムコード
全体のプログラムコードは以下のようになります。
#include <Trade\Trade.mqh>
//標準ライブラリーのトレードファイルを使えるようにする
CTrade trade;
// CTradeクラスのインスタンスを宣言
void OnTick()
{
//エントリーシグナルを格納する変数を宣言
string entrySignal=CheckEntry();
//現在値の取得と正規化
double Ask=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
double Bid=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
if(entrySignal=="buy" && PositionsTotal()==0)
{
//買い注文
trade.Buy(0.01,NULL,Ask,0,Ask+100*_Point);
}//if(entrySignal=="buy" && PositionsTotal()==0)
if(entrySignal=="sell" && PositionsTotal()==0)
{
//売り注文
trade.Sell(0.01,NULL,Bid,0,Bid-100*_Point);
}//if(entrySignal=="sell" && PositionsTotal()==0)
}//void OnTick()
//+------------------------------------------------------------------+
//エントリ-チェック関数の定義
string CheckEntry()
{
//シグナル用の文字列変数を宣言
string signal="";
//価格を格納する配列を宣言
double priceArray[];
//MACDのハンドルを取得
int macdHandle=iMACD(_Symbol,_Period,12,26,9,PRICE_CLOSE);
//配列を時系列にセット
ArraySetAsSeries(priceArray,true);
//MACDのメインライン値を取得し、配列に格納
CopyBuffer(macdHandle,0,0,3,priceArray);
//現在足のMACD値を変数に格納
double macdValue=priceArray[0];
//MACDの0ラインを基準として売買シグナルを発出
if(macdValue>0)signal="sell";
if(macdValue<0)signal="buy";
Comment("シグナル: ",signal);
//戻り値としてsignalを返す
return signal;
}//string CheckEntry()
プログラムの挙動は以下のようになります。
最後までお読みいただきありがとうございました!
※当サイトでは、プログラミング経験ゼロの方でも、プログラミングの基礎から学べる
をメインコンテンツとして展開しています。
第0回から、順を追って勉強していけばプログラミングの経験がなくてもMQL5を使って、MT5用のEAが作れるように書いています。最初は難しいと感じるかもしれませんが、繰り返し勉強していく事で自然とスキルが身についていくはずです。興味ある方は是非ご覧ください。
コメント