勝率計算付きのインジケーター
日本でもBinary Option(バイナリーオプション)が流行っていますが、
勝率計算機付きというシステムが多く出回っています。
プログラミング初心者だと勝率計算というだけで難しいと思いがちですが、
実は超簡単にBinary Option(バイナリーオプション)のシステムを勝率計算させることが可能です。
Binary Option(バイナリーオプション)はエントリーの次のローソク足が確定した際に
そのレートよりも上にあるか下にあるかで勝ち負けが決まるシンプルなルールになっています。
このルールに従って勝率計算機を作っていきます。
今回は過去に使用したRSIのロジックを活用して作っていきたいと思います。
メタエディタ(MetaEditor)を立ち上げる
メタエディタ(MetaEditor)を立ち上げましょう。操作は以下に記載しています。
今回は名前を「Win-Rate」で作成します。
プロパティを記述する
プロパティを記述しましょう。まず今回用意するバッファは4つです。
そして矢印を青色と赤色の2つを用意して、マルバツ判定は黄色にします。それぞれ幅を2に設定します。
#property indicator_chart_window #property indicator_buffers 4//バッファ4つ #property indicator_color1 clrBlue//青色 #property indicator_color2 clrRed //赤色 #property indicator_color3 clrYellow//黄色 #property indicator_color4 clrYellow//黄色 #property indicator_width1 2//幅2 #property indicator_width2 2//幅2 #property indicator_width3 2 //幅2 #property indicator_width4 2//幅2
バッファを定義する
バッファを定義しましょう。
上矢印を『arrup[]』にして下矢印を『arrDown[]』にします。
また、マルを『maru[]』としてバツを『batu[]』にします。
double arrUp[], arrDown[];//上矢印と下矢印 double maru[],batu[];//マルとバツ
パラメーターを記述する
パラメーターを記述しましょう。
今回はRSIを活用したインジケーターですので、RSIの期間を決めることができる『RSI_Period』と
RSIの上限を『upfilter』でRSIの下限を『downfilter』に設定します。
input int RSI_Period = 14;//RSIの期間 input int upfilter = 70;//フィルター上限 input int downfilter = 30;//フィルター下限
グローバル変数を記述する
グローバル変数を記述しましょう。『totalCnt』でトレードの回数を格納します。
また、それぞれのトレードの勝ち負けの回数を『winCnt』と『loseCnt』にします。
Binary Option(バイナリーオプション)は基本的に終値で終了するので、
終値を判定するために『endPrise』を作ります。エントリーの次の足を判定制御用として『isJudge』にします。
勝利判定を『upEntryFlag』にして敗北判定を『downEntryFlag』にします。
int totalCnt = 0;//トレード回数 int winCnt = 0;//合計勝利回数 int loseCnt = 0;//合計敗北回数 double endPrise = 0;//終値の格納 bool isJudge = false;//次足判定制御用 bool upEntryFlag = false;//勝利判定フラグ bool downEntryFlag = false;//敗北判定フラグ
OnInit()関数を記述する
OnInit()関数を記述しましょう。それぞれのインデックスにバッファを紐付けさせていきます。
今回はすべて矢印なので矢印設定を行い、それぞれの表示形式を設定すれば完了です。
SetIndexBuffer(0, arrUp);//インデックス0にarrupを紐付け SetIndexBuffer(1, arrDown);//インデックス1にarrDownを紐付け SetIndexBuffer(2, maru);//インデックス2にmaruを紐付け SetIndexBuffer(3, batu);//インデックス3にbatuを紐付け SetIndexStyle(0, DRAW_ARROW, STYLE_SOLID);//インデックス0に矢印設定 SetIndexStyle(1, DRAW_ARROW, STYLE_SOLID);//インデックス1に矢印設定 SetIndexStyle(2, DRAW_ARROW, STYLE_SOLID);//インデックス2に矢印設定 SetIndexStyle(3, DRAW_ARROW, STYLE_SOLID);//インデックス3に矢印設定 SetIndexArrow(0, 233);//インデックス0に上矢印 SetIndexArrow(1, 234);//インデックス1に下矢印 SetIndexArrow(2, 161);//インデックス2にマル SetIndexArrow(3, 251);//インデックス3にバツ
OnDeinit()関数を記述する
OnDeinit()関数を記述しましょう。
インジケーターをチャートから削除した場合に勝率計算も消えるように
オブジェクトを全て削除できるように『ObjectsDeleteAll()』を設定しておきましょう。
ObjectsDeleteAll();//オブジェクトを全て削除
OnCalculate()関数を記述する
OnCalculate()関数を記述しましょう。
double dRsiNow,dRsiPast;//RSI変数 int limit = Bars-IndicatorCounted(); //チャート更新時の勝率計算バグを防ぐ処理 if(limit == Bars - 1) { totalCnt = 0; winCnt = 0; loseCnt = 0; } for(int i=0; i < limit; i++) { dRsiNow = iRSI(NULL,0,RSI_Period,PRICE_CLOSE,i);//現在の足のRSI dRsiPast = iRSI(NULL,0,RSI_Period,PRICE_CLOSE,i+1);//1つ前の足のRSI arrUp[i] = EMPTY_VALUE;//バッファの値が空 arrDown[i] = EMPTY_VALUE;//バッファの値が空 if(dRsiPast <= downfilter && dRsiNow >downfilter)//1つ前のRSIが30以下で現在のRSIが30を超えている { arrUp[i] = Low[i];//シグナルを安値にセットする upEntryFlag = true;//エントリー確定時フラグを立てる endPrise = iClose(NULL,0,i);//エントリー確定時の終値を格納 } else if(dRsiPast >= upfilter && dRsiNow <upfilter)//1つ前のRSIが70以上で現在のRSIが70下回る { arrDown[i] = High[i];//シグナルを高値にセットする downEntryFlag = true;//エントリー確定時フラグを立てる endPrise = iClose(NULL,0,i);//エントリー確定時の終値を格納 } //勝敗判定 if(upEntryFlag) { //isJudgeがfalseの場合、一回処理を飛ばす(次足で判定サインを出したい為) if(isJudge) { //前足の終値よりも次足の終値の方が大きかった場合 if(endPrise < iClose(NULL,0,i-2)) { maru[i-2] = iLow(NULL,0,i-2)-10*Point;//丸印を安値の1pips下に出す upEntryFlag = false; winCnt++; } else { batu[i-2] = iLow(NULL,0,i-2)-10*Point;//バツ印を安値の1pips下に出す。 upEntryFlag = false; loseCnt++; } isJudge = false; } else { isJudge = true; } } if(downEntryFlag) { //isJudgeがfalseの場合、一回処理を飛ばす(次足で判定サインを出したい為) if(isJudge) { //前足の終値よりも次足の終値の方が小さかった場合 if(endPrise > iClose(NULL,0,i-2)) { //丸印を高値の1pips上に出す。(1*Point=0.1pips) maru[i-2] = iHigh(NULL,0,i-2)+10*Point; downEntryFlag = false; winCnt++; } else { //バツ印を高値の1pips上に出す。(1*Point=0.1pips) batu[i-2] = iHigh(NULL,0,i-2)+10*Point; downEntryFlag = false; loseCnt++; } isJudge = false; } else { isJudge = true; } } } WinRate();//勝率計算の関数 //--- return value of prev_calculated for next call return(rates_total); }
WinRate()関数を記述する
WinRate()関数を記述しましょう。WinRate()関数では勝率計算を行っていきます。
まず、ObjectCreateで勝利計算のオブジェクトを作成していきます。
ObjectCreate("obj_judgeMonitor",OBJ_LABEL,0,0,0);//勝率計算のオブジェクト作成
次にサイズ設定ですが、左上にXサイズ10でYサイズ20で設置します。
ObjectSet("obj_judgeMonitor",OBJPROP_CORNER,CORNER_LEFT_UPPER);//左上に表示 ObjectSet("obj_judgeMonitor",OBJPROP_XDISTANCE,10);//X軸サイズ10 ObjectSet("obj_judgeMonitor",OBJPROP_YDISTANCE,20);//Y軸サイズ20
ここから勝率計算を行っていきます。
まず、totalCntにwinCntとloseCntの合計を代入します。
totalCnt = winCnt + loseCnt;//トータル
そして、勝利/トレード合計*100で勝率を計算していきます。
double rate = MathRound((double)winCnt / totalCnt * 100);//100%の割合を計算
そして、最後に表示させて完了です。
ObjectSetText("obj_judgeMonitor", "判定:"+(string)totalCnt+" 勝ち:"+(string)winCnt+" 勝率:"+(string)rate+"%", 11, "メイリオ", clrWhite);//勝率の表示
//勝率オブジェクト作成 ObjectCreate("obj_judgeMonitor",OBJ_LABEL,0,0,0);//勝率計算のオブジェクト作成 ObjectSet("obj_judgeMonitor",OBJPROP_CORNER,CORNER_LEFT_UPPER);//左上に表示 ObjectSet("obj_judgeMonitor",OBJPROP_XDISTANCE,10);//X軸サイズ10 ObjectSet("obj_judgeMonitor",OBJPROP_YDISTANCE,20);//Y軸サイズ20 //勝率計算 totalCnt = winCnt + loseCnt;//トータル double rate = MathRound((double)winCnt / totalCnt * 100);//100%の割合を計算 ObjectSetText("obj_judgeMonitor", "判定:"+(string)totalCnt+" 勝ち:"+(string)winCnt+" 勝率:"+(string)rate+"%", 11, "メイリオ", clrWhite);//勝率の表示
コンパイルする
コンパイルしましょう。しっかりとロジック通りに動いていれば完成です。
ソースコード全体
//+------------------------------------------------------------------+ //| Win-rate.mq4 | //| Copyright 2020, FX-EA System Project Creator | //| https://creator.fx-ea-system-project.com/ | //+------------------------------------------------------------------+ #property copyright "Copyright 2020, FX-EA System Project Creator" #property link "https://creator.fx-ea-system-project.com/" #property version "1.00" #property strict /*プロパティ*/ #property indicator_chart_window #property indicator_buffers 4//バッファ4つ #property indicator_color1 clrBlue//青色 #property indicator_color2 clrRed //赤色 #property indicator_color3 clrYellow//黄色 #property indicator_color4 clrYellow//黄色 #property indicator_width1 2//幅2 #property indicator_width2 2//幅2 #property indicator_width3 2 //幅2 #property indicator_width4 2//幅2 /*バッファ*/ double arrUp[], arrDown[];//上矢印と下矢印 double maru[],batu[];//マルとバツ /*パラメーター*/ input int RSI_Period = 14;//RSIの期間 input int upfilter = 70;//フィルター上限 input int downfilter = 30;//フィルター下限 /*グローバル変数*/ int totalCnt = 0;//トレード回数 int winCnt = 0;//合計勝利回数 int loseCnt = 0;//合計敗北回数 double endPrise = 0;//終値の格納 bool isJudge = false;//次足判定制御用 bool upEntryFlag = false;//勝利判定フラグ bool downEntryFlag = false;//敗北判定フラグ //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0, arrUp);//インデックス0にarrupを紐付け SetIndexBuffer(1, arrDown);//インデックス1にarrDownを紐付け SetIndexBuffer(2, maru);//インデックス2にmaruを紐付け SetIndexBuffer(3, batu);//インデックス3にbatuを紐付け SetIndexStyle(0, DRAW_ARROW, STYLE_SOLID);//インデックス0に矢印設定 SetIndexStyle(1, DRAW_ARROW, STYLE_SOLID);//インデックス1に矢印設定 SetIndexStyle(2, DRAW_ARROW, STYLE_SOLID);//インデックス2に矢印設定 SetIndexStyle(3, DRAW_ARROW, STYLE_SOLID);//インデックス3に矢印設定 SetIndexArrow(0, 233);//インデックス0に上矢印 SetIndexArrow(1, 234);//インデックス1に下矢印 SetIndexArrow(2, 161);//インデックス2にマル SetIndexArrow(3, 251);//インデックス3にバツ //--- return(INIT_SUCCEEDED); } void OnDeinit(const int reason) { ObjectsDeleteAll();//オブジェクトを全て削除 } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { //--- double dRsiNow,dRsiPast;//RSI変数 int limit = Bars-IndicatorCounted(); //チャート更新時の勝率計算バグを防ぐ処理 if(limit == Bars - 1) { totalCnt = 0; winCnt = 0; loseCnt = 0; } for(int i=0; i < limit; i++) { dRsiNow = iRSI(NULL,0,RSI_Period,PRICE_CLOSE,i);//現在の足のRSI dRsiPast = iRSI(NULL,0,RSI_Period,PRICE_CLOSE,i+1);//1つ前の足のRSI arrUp[i] = EMPTY_VALUE;//バッファの値が空 arrDown[i] = EMPTY_VALUE;//バッファの値が空 if(dRsiPast <= downfilter && dRsiNow >downfilter)//1つ前のRSIが30以下で現在のRSIが30を超えている { arrUp[i] = Low[i];//シグナルを安値にセットする upEntryFlag = true;//エントリー確定時フラグを立てる endPrise = iClose(NULL,0,i);//エントリー確定時の終値を格納 } else if(dRsiPast >= upfilter && dRsiNow <upfilter)//1つ前のRSIが70以上で現在のRSIが70下回る { arrDown[i] = High[i];//シグナルを高値にセットする downEntryFlag = true;//エントリー確定時フラグを立てる endPrise = iClose(NULL,0,i);//エントリー確定時の終値を格納 } //勝敗判定 if(upEntryFlag) { //isJudgeがfalseの場合、一回処理を飛ばす(次足で判定サインを出したい為) if(isJudge) { //前足の終値よりも次足の終値の方が大きかった場合 if(endPrise < iClose(NULL,0,i-2)) { maru[i-2] = iLow(NULL,0,i-2)-10*Point;//丸印を安値の1pips下に出す upEntryFlag = false; winCnt++; } else { batu[i-2] = iLow(NULL,0,i-2)-10*Point;//バツ印を安値の1pips下に出す。 upEntryFlag = false; loseCnt++; } isJudge = false; } else { isJudge = true; } } if(downEntryFlag) { //isJudgeがfalseの場合、一回処理を飛ばす(次足で判定サインを出したい為) if(isJudge) { //前足の終値よりも次足の終値の方が小さかった場合 if(endPrise > iClose(NULL,0,i-2)) { //丸印を高値の1pips上に出す。(1*Point=0.1pips) maru[i-2] = iHigh(NULL,0,i-2)+10*Point; downEntryFlag = false; winCnt++; } else { //バツ印を高値の1pips上に出す。(1*Point=0.1pips) batu[i-2] = iHigh(NULL,0,i-2)+10*Point; downEntryFlag = false; loseCnt++; } isJudge = false; } else { isJudge = true; } } } WinRate();//勝率計算の関数 //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| 勝率計算関数 | //+------------------------------------------------------------------+ void WinRate() { //勝率オブジェクト作成 ObjectCreate("obj_judgeMonitor",OBJ_LABEL,0,0,0);//勝率計算のオブジェクト作成 ObjectSet("obj_judgeMonitor",OBJPROP_CORNER,CORNER_LEFT_UPPER);//左上に表示 ObjectSet("obj_judgeMonitor",OBJPROP_XDISTANCE,10);//X軸サイズ10 ObjectSet("obj_judgeMonitor",OBJPROP_YDISTANCE,20);//Y軸サイズ20 //勝率計算 totalCnt = winCnt + loseCnt;//トータル double rate = MathRound((double)winCnt / totalCnt * 100);//100%の割合を計算 ObjectSetText("obj_judgeMonitor", "判定:"+(string)totalCnt+" 勝ち:"+(string)winCnt+" 勝率:"+(string)rate+"%", 11, "メイリオ", clrWhite);//勝率の表示 }
まとめ
今回のソースコードを改良することで、異なるシステムを勝率計算させることが可能になります。
コメント