2009年1月の記事一覧

カスタムインディケータをEAにする方法3


下記の前回の記事と前々回の記事・・・

の続きです!

まずは、ファイルダウンロード
BBands_Stops_EA.zip(mq4ファイルのダウンロード)

  1. EAの全体構成を決める
  2. EAのパラメータを作る
  3. 条件分けをする

といった感じにやっていきましょう!

1.EAの全体構成を決める

まず、ドテンを実現するためにはシグナルでクローズするというコードが必要ですね。
ドテンするかしないかの選択ができるように、そのパラメータもつくりましょう。

ドテンする場合で、シグナルが出た瞬間の取引の場合、コストが大きくなってしまいますので、

「1度エントリしたら次の足まで待って、シグナルがダマシだった場合は
クローズして次のシグナルまで待つ」

といった取引をするようにしましょうか。

2.EAのパラメータを作る

EAを使うときに、選択できるようにするものをパラメータ化していきましょう!

エントリの時のパラメータとして

extern double Lots = 0.1;
extern int StopLoss = 0;
extern int TakeProfit = 0;
extern int Slippage = 1;

ロット数、ストップ値、リミット値、スリッページ

インディケータの使い方として

extern int SignShift = 1;
extern bool ClosebySign = true;

何本前の足のシグナルか、シグナルでクローズするか


EAのマジックナンバーもパラメータにしましょうか^^;

extern int MagicNumber = 883102;

EAでエントリしたときのコメントをパラメータにしたいときは、

string EA_Comment = "EA";

の前にexternをつけてください。


また、他のインディケータを使うときに改造しやすいように

//Other Set
string IndicatorName ="BBands_Stops_mtf";
int IndicatorUpIndex = 2;
int IndicatorDnIndex = 3;
int NoSignValue = -1;

として、インディケータ名、シグナルのインデックス、シグナルが出ていないときの値
変数に代えときましょうか。

シグナル部分は

double upsign=iCustom(NULL,TimeFrame,IndicatorName,0,Length,Deviation,
IndicatorUpIndex,SignShift);
double dnsign=iCustom(NULL,TimeFrame,IndicatorName,0,Length,Deviation,
IndicatorDnIndex,SignShift);

int sign;
if(upsign!=NoSignValue) sign=1;
if(dnsign!=NoSignValue) sign=-1;

といった形になるかと思います。

3.条件分けをする

条件分けは、

  • ポジションがあるかないか
  • シグナルがどういう状態か
  • エントリした足から足が新たにできているか

などなど・・・大まかな条件から、枝分かれするイメージで作っていきましょう。

まず、ポジションがあるか無いかを調べるために、

int pos=-1;
for(int i=OrdersTotal()-1;i>=0;i--)
{
OrderSelect(i,SELECT_BY_POS); if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber) pos=i;
}

として、
ポジションが無かったら変数posは-1
ポジションがあれば、posはそのポジションのインデックスの値

とします。

そして、

if(pos>=0)
{
}
のカッコ内にポジションがあるときに実行してもらうコード

if(pos<0)
{
}
のカッコ内にポジションが無いときに実行してもらうコード

を書いていきましょう。

まず、ポジションが無いときに実行してもらうコードを書いていきましょうか。

//MM
double lots=Lots;

として、後でマネーマネジメントの機能追加をしやすいように書いておきましょう^^

if(bar!=iBars(NULL,TimeFrame))
{

として、エントリした足(TimeFrameで指定したチャートのバー番号)では、実行しないようにします。
ここで出てくる bar は、エントリしたときのバー番号を記憶してもらう整数変数ですので、
パラメータの下あたりに、

int bar;

として、記憶用整数変数 bar を宣言しておきましょう!

そして、

if(sign==1)
{
if(TakeProfit>0) double tp=Ask+TakeProfit*Point;
else tp=0;
if(StopLoss>0) double sl=Ask-StopLoss*Point;
else sl=0;
int ticket=OrderSend(Symbol(),OP_BUY,lots,Ask,Slippage,sl,tp,EA_Comment,MagicNumber, 0,Blue); if(ticket>0) bar=iBars(NULL,TimeFrame); }

として、sign が1のときに実行してもらう内容を書いてあげましょう。

内容は、
もし、TakeProfitが0より大きい場合、小数変数tpは買値+TakeProfitピプス。
そうでない場合、tpは0。
もし、StopLossが0より大きい場合、小数変数slは買値-StopLossピプス。
そうでない場合、slは0。
指定した内容で買い注文をし、整数変数ticketに注文番号を代入。
もし、ticketが0より大きい場合、 bar にTimeFrameで指定したチャートのバー番号を代入。

という感じです。

ここで、TakeProfitやStopLossが0の場合、ストップやリミットを設定しないで注文をするといったことが出来るようになりました。
最近では、ストップやリミットが小さいとエントリを受け付けないブローカーが増えてきましたので、
MarketInfo(Symbol(),MODE_STOPLEVEL)と
MarketInfo(Symbol(),MODE_SPREAD)
ブローカーのストップ・リミット制限と
スプレッド
を使って条件わけをするとよいかと思います。
今回は省略します^^;

signが-1のときも同様に書いてあげましょう。
ここでの注意は、変数 tp,sl,ticket はすでに宣言してありますので、
変数宣言の必要がありません。

これでポジションなしの時のコードが完成しました!

次に、ポジションがあるときに実行してもらうコードを書いていきましょう!

OrderSelect(pos,SELECT_BY_POS);

として、ポジションの情報を取得できるようにポジションの選択をしておきます。

if(ClosebySign==true && bar!=iBars(NULL,TimeFrame))
{

として、ClosebySignがtrueでバー番号がエントリした足のバー番号ではないときだけ、実行してもらうようにします。

この条件は、ポジションの分岐とあわせて、

if(pos>=0 && ClosebySign==true && bar!=iBars(NULL,TimeFrame))
{
といった感じにもできますが、後から改造しやすいように分けてあります。

次に

if( (OrderType()==OP_BUY && sign==-1) || (OrderType()==OP_SELL && sign==1) )
{
OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage,Yellow); pos=-1; }

として、買いポジションでsignが-1、または、売りポジションでsignが1のときクローズ
posに-1を代入とします。

ここで、posに-1を代入してあげると、下に書いたポジション無しの場合のコードも実行してくれるといった感じです。

そして、最後に大きな課題
「1度エントリしたら次の足まで待って、シグナルがダマシだった場合はクローズして、次のシグナルまで待つ」
を書きましょう。

if(SignShift==0 && bar==iBars(NULL,TimeFrame)-1)
{
double upsign1=iCustom(NULL,TimeFrame,IndicatorName,0,Length,Deviation,
IndicatorUpIndex,1);
double dnsign1=iCustom(NULL,TimeFrame,IndicatorName,0,Length,Deviation,
IndicatorDnIndex,1);

if( (OrderType()==OP_BUY && upsign1==NoSignValue) || (OrderType()==
OP_SELL && dnsign1==NoSignValue) )
{
OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage,Yellow);
return(0); } }

とします。

SignShiftが0で、前の足でエントリしたときにのみ実行してもらうコードです。
また、iCustom関数で1つ前の足のシグナルをしらべます。
(signを決定するブースで記憶変数を使って調べる方法もありますが、今回はiCustom関数を使ってみましょう)

結局シグナルが出ていなかった場合、クローズする

という条件のコードを書いてあげましょう。

これで、一旦クローズしておいて、次のシグナルを待つという形になりました。

今回は、これで完成です。

あとは、ストップ・リミットが0でシグナルでもクローズしないとなるといつまででもポジションをもっていることになりますので、お好みでその条件も加えると良いかと思います。

でわ、今回はこのへんでm(..)m

カスタムインジケータをEAにする方法の関連記事

2009年1月 3日|コメント (88)

カテゴリー:EAの作成方法