今回の内容
今回行う内容は、
- 【MQL4:バックテスト編①】アローカウントとオブジェクトの準備(カスタムインジケーターver)<バイナリーオプション>とは別の処理でカウントを取る
- 勝率の計算期間を日時指定で行う
上記の2点を説明していこうと思います。
サンプルコード
まずは全体のサンプルコードから
//+------------------------------------------------------------------+
//| TAKULOG_BLOG_BTsample2.mq4 |
//| Copyright 2019, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "TAKULOG"
#property version "1.00"
#property strict
#property indicator_chart_window//メインウィンドウに表示
#property indicator_buffers 2 //インジケータのバッファを2つ用意
#property indicator_color1 Red //1つ目のインジケータを赤色に設定
#property indicator_color2 Blue //2つ目のインジケータを青色に設定
#property indicator_width1 1 //1つ目のインジケータの太さを3に設定
#property indicator_width2 1 //2つ目のインジケータの太さを3に設定
//////////////////////// << 外部パラメーター >> /////////////////////////////////
extern string INFO = ">> 簡易勝率計算開始期間"; // 勝率計算開始期間
extern datetime DAY1 = D'2021.01.01.00:00'; // ★ 勝率計算開始日時
//バッファー用意///////////////////////////////////////////////
double ArrowUp[]; //上矢印用バッファー
double ArrowDown[]; //下矢印用バッファー
datetime Timeflag = 0;
int COUNT=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit() //初期化関数---主に初期条件やチャート更新時に決めておく内容を書く項目
{
//下矢印1
SetIndexBuffer(0,ArrowDown); //バッファを用意
SetIndexStyle(0,DRAW_ARROW); //矢印を出す
SetIndexArrow(0,238); //矢印の種類設定 調べると各矢印形等の番号が出る
SetIndexEmptyValue(0,0.0);
SetIndexLabel(0,"arrow_Down");//ラベル(名前)を決める
//上矢印1
SetIndexBuffer(1,ArrowUp); //バッファを用意
SetIndexStyle(1,DRAW_ARROW); //矢印を出す
SetIndexArrow(1,236); //矢印の種類設定 調べると各矢印形等の番号が出る
SetIndexEmptyValue(1,0.0);
SetIndexLabel(1,"arrow_Up"); //ラベル(名前)を決める
LABEL("COUNT",50,50,20,clrGold);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| 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[])
{
int limit = rates_total - prev_calculated;
int n = 2; //array out of range対処
if (limit > 1) {limit = rates_total - n - 1;}
// <<アロー用forループ開始>>///////////////////////////////////////////
for(int i=limit; i>=0; i--){//for開始
if(i+1 >= Bars-1){continue;}
////// 【RSI値取得】 ///////////////////////////////////////////
double RsiCL =iRSI(NULL,0,14,PRICE_CLOSE,i); //現行足RSI
// <<アロー条件定義>> ////////////////////////////////////////////
if(RsiCL>=70){ //条件①
ArrowUp[i] =0; //0に返す
ArrowDown[i]=High[i]; //下矢印を高値に表示
}
else if(RsiCL<=30){ //条件②
ArrowUp[i]=Low[i]; //上矢印を安値に表示
ArrowDown[i]=0; //0に返す
}
else{
ArrowDown[i]=0; //0に返す
ArrowUp[i] =0; //0に返す
}
}
// <<アロー用forループ終了>> ///////////////////////////////////
// >> 期間指定
int shiftA = iBarShift(Symbol(),Period(),DAY1,false);//
int LimA;
if(shiftA<limit){LimA=shiftA-prev_calculated;}
else {LimA=limit;}
// <<確定足forループ開始>>///////////////////////////////////////////
for(int i=LimA; i>=1; i --){ // 1本前足からのループ処理(確定足)
if(i+1 >= LimA){continue;} // バーがない時、スキップ
if(ArrowUp[i+1]||ArrowDown[i+1]){
COUNT++;
ObjectSetString(0,"COUNT",OBJPROP_TEXT,(string)COUNT);
}
}
// <<確定足forループ終了>>///////////////////////////////////////////
//--- return value of prev_calculated for next call
return(rates_total);
}
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>自作関数
// ------ << テキスト >>--------------------------------------------------------
void LABEL(string label,int posx,int posy,int FS,color fontcolor){
ObjectCreate(label,OBJ_LABEL,0,0,0); // ラベルを生成
ObjectSetString (0,label,OBJPROP_FONT,"メイリオ"); // ラベルのフォントを指定
ObjectSetInteger(0,label,OBJPROP_FONTSIZE,FS); // 文字のサイズ
ObjectSetInteger(0,label,OBJPROP_CORNER,0); // オブジェクトの表示コーナー
ObjectSetInteger(0,label,OBJPROP_XDISTANCE,posx); // オブジェクトのX(横方向)表示位置
ObjectSetInteger(0,label,OBJPROP_YDISTANCE,posy); // オブジェクトのY(縦方向)表示位置
ObjectSetInteger(0,label,OBJPROP_COLOR,fontcolor); // 文字色を設定する
ObjectSetInteger(0,label,OBJPROP_BACK,false); // 前景(false)または背景(true)に表示
ObjectSetInteger(0,label,OBJPROP_SELECTABLE,false);// オブジェクトの選択可否設定
ObjectSetInteger(0,label,OBJPROP_HIDDEN,true); // オブジェクトリスト表示設定
}
コンパイルしたもの
アローの表示条件やテキストに表示する内容に変更がない為、【バックテスト編①】の画像を流用しています。
今回変更したコード
今回は【バックテスト編①】で時間をフラグにしてティック処理を回避してカウントしていた方法を、確定足のforループにしてカウントを取る方法に変更しています。
//【バックテスト編①】のカウント処理
if(Timeflag!=Time[i]){
if(ArrowUp[i+1]!=0||ArrowDown[i+1]!=0){
COUNT++;
ObjectSetString(0,"COUNT",OBJPROP_TEXT,(string)COUNT);
}
Timeflag=Time[i];
}
}
//今回のカウント処理
// >> 期間指定
int shiftA = iBarShift(Symbol(),Period(),DAY1,false);//
int LimA;
if(shiftA<limit){LimA=shiftA-prev_calculated;}
else {LimA=limit;}
// <<確定足forループ開始>>///////////////////////////////////////////
for(int i=LimA; i>=1; i --){ // 1本前足からのループ処理(確定足)
if(i+1 >= LimA){continue;} // バーがない時、スキップ
if(ArrowUp[i+1]||ArrowDown[i+1]){
COUNT++;
ObjectSetString(0,"COUNT",OBJPROP_TEXT,(string)COUNT);
}
}
まとめ