新しい記事を書く事で広告が消せます。
新しい記事を書く事で広告が消せます。
[MetaTrader] カスタム出来高チェック
MetaTraderでカスタムインディケータを作成する際のサンプルプログラムになります。
MetaTraderが何ぞの物やという方はこちらからどうぞ。
またカスタムインディケータとは、移動平均線のようなテクニカル指標を、Meta Traderが読み込み可能なMeta Quotes Language (MQL)というプログラム言語にて記述を行うことで、Meta Traderのチャート上に表示を可能にするプログラムのことです。
MQLの標準関数についてはこちらからどうぞ。
さて本項にてご紹介するカスタム出来高チェッカー(なんと命名すれば良いか悩ましいですが…)ですが、これはMeta Traderより取得することができるVolume(≒出来高)から、レジスタンスラインとサポートラインを確認するためのカスタムインディケータになります。
ただしMeta Traderから得られるVolumeは、ティックカウントであり、正確な意味での出来高ではありません。
ティックカウントは、チャート上において、ローソク足(もしくはバー等)が確定するまでに、どれほどの価格変動があったかを表すものです。
簡単に言えば、過去のティックカウントに注目すれば、価格変動が大きい位置において強い反発があったことを意味しており、上昇時にはレジスタンスライン、そして下落時にはサポートラインとして機能した可能性が高いと言えます。
このインディケータでの活用方法をご紹介しますと、例えば、現在の4時間足チャートに、1日単位にて、15分足レベルでのVolumeが最大となる価格帯を表示できれば、レジスタンスラインもしくはサポートラインを確認しやすく、実際のトレードに活用しやすいかと思います。
実際に、このカスタムインディケータを使用した際のチャートを左下に、またその際の15分足チャートを右下に表示します。
下記にMQLにてカスタム出来高チェッカーのカスタムインディケータを作成した際のサンプルプログラムを示す。
//+------------------------------------------------------------------+
//| Jaku_Check_Volume.mq4 |
//| Jaku |
//| http://techsystrade.blog17.fc2.com/ |
//+------------------------------------------------------------------+
#property copyright "Jaku"
#property link "http://techsystrade.blog17.fc2.com/"
#property indicator_chart_window
#property indicator_buffers 8
#property indicator_color1 Yellow
#property indicator_color2 Yellow
#property indicator_color3 Yellow
#property indicator_color4 Yellow
#property indicator_color5 Yellow
#property indicator_color6 Yellow
#property indicator_color7 Yellow
#property indicator_color8 Yellow //main
#property indicator_style1 2
#property indicator_style2 2
#property indicator_style3 2
#property indicator_style4 2
#property indicator_style5 2
#property indicator_style6 2
#property indicator_style7 2
#property indicator_style8 0 //main
#property indicator_width1 1
#property indicator_width2 1
#property indicator_width3 1
#property indicator_width4 1
#property indicator_width5 1
#property indicator_width6 1
#property indicator_width7 1
#property indicator_width8 1 //main
//---- input parameters
extern int Search_TIMEFRAME = PERIOD_M15;
extern int Applied_TIMEFRAME = PERIOD_D1;
extern int Applied_PRICE = 7;
extern int line_shift = 20;
extern int display_day = 0;
//---- output parameters
double buf0[]; //0
double buf1[]; //1
double buf2[]; //2
double buf3[]; //3
double buf4[]; //4
double buf5[]; //5
double buf6[]; //6
double buf7[]; //0123456
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
SetIndexBuffer(0,buf0);
SetIndexBuffer(1,buf1);
SetIndexBuffer(2,buf2);
SetIndexBuffer(3,buf3);
SetIndexBuffer(4,buf4);
SetIndexBuffer(5,buf5);
SetIndexBuffer(6,buf6);
SetIndexBuffer(7,buf7);
SetIndexShift(0,line_shift);
SetIndexShift(1,line_shift);
SetIndexShift(2,line_shift);
SetIndexShift(3,line_shift);
SetIndexShift(4,line_shift);
SetIndexShift(5,line_shift);
SetIndexShift(6,line_shift);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
//----
int i, j, k, l, count, imax, shift, limit[200];
double price[200], temp_volume;
datetime some_time;
//----
Search_TIMEFRAME = CHECK_TIMEFRAME(Search_TIMEFRAME);
Applied_TIMEFRAME = CHECK_TIMEFRAME(Applied_TIMEFRAME);
if(Period()>Applied_TIMEFRAME) Applied_TIMEFRAME = Period();
if(display_day>7) display_day = 7;
imax = iBars(NULL,Search_TIMEFRAME);
shift = Applied_TIMEFRAME / Search_TIMEFRAME;
some_time = iTime(NULL,Applied_TIMEFRAME,0);
//----
limit[0] = 0;
limit[1] = iBarShift(NULL,Search_TIMEFRAME,some_time);
count = (imax-limit[1])/shift;
for(i=1;i<count;i++) limit[i+1] = limit[i] + shift;
//----
for(j=0;j<count;j++){
temp_volume = 0;
for(i=limit[j];i<limit[j+1];i++){
if(temp_volume < iVolume(NULL,Search_TIMEFRAME,i)){
temp_volume = iVolume(NULL,Search_TIMEFRAME,i);
switch(Applied_PRICE){
case 0: price[j] = iClose(NULL,Search_TIMEFRAME,i); break;
case 1: price[j] = iOpen (NULL,Search_TIMEFRAME,i); break;
case 2: price[j] = iHigh (NULL,Search_TIMEFRAME,i); break;
case 3: price[j] = iLow (NULL,Search_TIMEFRAME,i); break;
case 4: price[j] = (iHigh(NULL,Search_TIMEFRAME,i)+iLow(NULL,Search_TIMEFRAME,i))/2; break;
case 5: price[j] = (iHigh(NULL,Search_TIMEFRAME,i)+iLow(NULL,Search_TIMEFRAME,i)+ iClose(NULL,Search_TIMEFRAME,i))/3; break;
case 6: price[j] = (iHigh(NULL,Search_TIMEFRAME,i)+iLow(NULL,Search_TIMEFRAME,i)+2*iClose(NULL,Search_TIMEFRAME,i))/4; break;
case 7: if(iOpen(NULL,Search_TIMEFRAME,i)<iClose(NULL,Search_TIMEFRAME,i)) price[j] = iHigh(NULL,Search_TIMEFRAME,i);
else if(iOpen(NULL,Search_TIMEFRAME,i)>iClose(NULL,Search_TIMEFRAME,i)) price[j] = iLow(NULL,Search_TIMEFRAME,i);
else price[j] = iClose(NULL,Search_TIMEFRAME,i);
break;
default: price[j] = iClose(NULL,Search_TIMEFRAME,i);
}
}
}
}
//----
for(j=0;j<count;j++){
k = iBarShift(NULL,NULL,iTime(NULL,Search_TIMEFRAME,limit[j] ),true);
l = iBarShift(NULL,NULL,iTime(NULL,Search_TIMEFRAME,limit[j+1]),true);
for(i=k;i<l;i++) buf7[i] = price[j];
if(j<display_day){
switch(j){
case 0: for(i=0;i<k+line_shift;i++) buf0[i] = price[0]; break;
case 1: for(i=0;i<k+line_shift;i++) buf1[i] = price[1]; break;
case 2: for(i=0;i<k+line_shift;i++) buf2[i] = price[2]; break;
case 3: for(i=0;i<k+line_shift;i++) buf3[i] = price[3]; break;
case 4: for(i=0;i<k+line_shift;i++) buf4[i] = price[4]; break;
case 5: for(i=0;i<k+line_shift;i++) buf5[i] = price[5]; break;
case 6: for(i=0;i<k+line_shift;i++) buf6[i] = price[6]; break;
}
}
}
//-----
return(0);
}
//+------------------------------------------------------------------+
int CHECK_TIMEFRAME(int TIMEFRAME)
{
//-----
if ((TIMEFRAME>=PERIOD_M1 )&&(TIMEFRAME<PERIOD_M5 )) TIMEFRAME = PERIOD_M1;
else if((TIMEFRAME>=PERIOD_M5 )&&(TIMEFRAME<PERIOD_M15)) TIMEFRAME = PERIOD_M5;
else if((TIMEFRAME>=PERIOD_M15)&&(TIMEFRAME<PERIOD_M30)) TIMEFRAME = PERIOD_M15;
else if((TIMEFRAME>=PERIOD_M30)&&(TIMEFRAME<PERIOD_H1 )) TIMEFRAME = PERIOD_M30;
else if((TIMEFRAME>=PERIOD_H1 )&&(TIMEFRAME<PERIOD_H4 )) TIMEFRAME = PERIOD_H1;
else if((TIMEFRAME>=PERIOD_H4 )&&(TIMEFRAME<PERIOD_D1 )) TIMEFRAME = PERIOD_H4;
else if((TIMEFRAME>=PERIOD_D1 )&&(TIMEFRAME<PERIOD_W1 )) TIMEFRAME = PERIOD_D1;
else if((TIMEFRAME>=PERIOD_W1 )&&(TIMEFRAME<PERIOD_MN1)) TIMEFRAME = PERIOD_W1;
else if( TIMEFRAME>=PERIOD_MN1 ) TIMEFRAME = PERIOD_MN1;
else TIMEFRAME = PERIOD_M1;
//-----
return(TIMEFRAME);
}
//+------------------------------------------------------------------+
簡単に機能についてご紹介します。
このカスタムインディケータでは、現在のウィンドウ上に過去の価格帯を表示を行うため、この価格帯を入れるための配列と、おまけになりますが、最近の価格帯をシフトして表示するための配列7つのための設定を行っています。、
#property indicator_chart_window #property indicator_buffers 8 #property indicator_color1 Yellow #property indicator_color2 Yellow #property indicator_color3 Yellow #property indicator_color4 Yellow #property indicator_color5 Yellow #property indicator_color6 Yellow #property indicator_color7 Yellow #property indicator_color8 Yellow //main #property indicator_style1 2 #property indicator_style2 2 #property indicator_style3 2 #property indicator_style4 2 #property indicator_style5 2 #property indicator_style6 2 #property indicator_style7 2 #property indicator_style8 0 //main #property indicator_width1 1 #property indicator_width2 1 #property indicator_width3 1 #property indicator_width4 1 #property indicator_width5 1 #property indicator_width6 1 #property indicator_width7 1 #property indicator_width8 1 //main
次に入力パラメータの設定を行います。
このインディケータでは、どの足に注目してVolumeをチェックするかをSearch_TIMEFRAMEにて、計算範囲である指定期間をApplied_TIMEFRAMEにて、そしてVolumeが最大となる際に4本値のどれを選択するかをApplied_PRICEにて設定しています。
また上記にておまけとご説明しましたが、近々の価格帯を最大で7期分、シフトラインにて支援表示することが可能となっています。
そのため、シフトラインのシフト量をline_shiftにて、また何期分を表示するかline_shiftdisplay_dayにて設定を行います。
//---- input parameters extern int Search_TIMEFRAME = PERIOD_M15; extern int Applied_TIMEFRAME = PERIOD_D1; extern int Applied_PRICE = 7; extern int line_shift = 20; extern int display_day = 0;
出力パラメータの設定を行います。
上記で述べましたが、価格帯を入れる配列と、最大で7期分のシフトラインの表示を行うため、8つのバッファーを定義しています。
//---- output parameters double buf0[]; //0 double buf1[]; //1 double buf2[]; //2 double buf3[]; //3 double buf4[]; //4 double buf5[]; //5 double buf6[]; //6 double buf7[]; //0123456
メインプログラムについてご説明します。
メインプログラムのはじめにて、入力されたパラメータ(外部変数)のチェックを行っています。
Search_TIMEFRAME = CHECK_TIMEFRAME(Search_TIMEFRAME); Applied_TIMEFRAME = CHECK_TIMEFRAME(Applied_TIMEFRAME); if(Period()>Applied_TIMEFRAME) Applied_TIMEFRAME = Period(); if(display_day>7) display_day = 7;
上記にて、入力パラメータのSearch_TIMEFRAMEとApplied_TIMEFRAMEのチェックを行っているのですが、チェックには外部関数のCHECK_TIMEFRAMEを用いています。
この外部関数は、プログラムの一番下に記述されているのですが、こちらでは、間違った期間が入力された際に、入力された期間から最も近い、かつ小さな期間に訂正するようになっています。
//+------------------------------------------------------------------+
int CHECK_TIMEFRAME(int TIMEFRAME)
{
//-----
if ((TIMEFRAME>=PERIOD_M1 )&&(TIMEFRAME<PERIOD_M5 )) TIMEFRAME = PERIOD_M1;
else if((TIMEFRAME>=PERIOD_M5 )&&(TIMEFRAME<PERIOD_M15)) TIMEFRAME = PERIOD_M5;
else if((TIMEFRAME>=PERIOD_M15)&&(TIMEFRAME<PERIOD_M30)) TIMEFRAME = PERIOD_M15;
else if((TIMEFRAME>=PERIOD_M30)&&(TIMEFRAME<PERIOD_H1 )) TIMEFRAME = PERIOD_M30;
else if((TIMEFRAME>=PERIOD_H1 )&&(TIMEFRAME<PERIOD_H4 )) TIMEFRAME = PERIOD_H1;
else if((TIMEFRAME>=PERIOD_H4 )&&(TIMEFRAME<PERIOD_D1 )) TIMEFRAME = PERIOD_H4;
else if((TIMEFRAME>=PERIOD_D1 )&&(TIMEFRAME<PERIOD_W1 )) TIMEFRAME = PERIOD_D1;
else if((TIMEFRAME>=PERIOD_W1 )&&(TIMEFRAME<PERIOD_MN1)) TIMEFRAME = PERIOD_W1;
else if( TIMEFRAME>=PERIOD_MN1 ) TIMEFRAME = PERIOD_MN1;
else TIMEFRAME = PERIOD_M1;
//-----
return(TIMEFRAME);
}
//+------------------------------------------------------------------+
また下記にて、指定された時間足にあるバーの数
imax = iBars(NULL,Search_TIMEFRAME); shift = Applied_TIMEFRAME / Search_TIMEFRAME; some_time = iTime(NULL,Applied_TIMEFRAME,0);
次に、指定期間の始めと終わりのバーシフト数を算出し、
つまり、1期目がlimit[0]からlimit[1]の期間、2期目がlimit[1]からlimit[2]の期間であり、以下も同様となります。
しかしながら注意すべきこととして、指定期間ですべてのバーを区切ると、最初か最後にて、端数が出てくることになります。
そこで本プログラムでは、最初に期間に端数を持ってきており、それによって、任意の時間足チャート上で、ローソク足を分割評価することをなくしています。
limit[0] = 0; limit[1] = iBarShift(NULL,Search_TIMEFRAME,some_time); count = (imax-limit[1])/shift; for(i=1;i<count;i++) limit[i+1] = limit[i] + shift;
上記のlimit配列から、期間毎に最大のVolumeをチェックし、そしてその際の価格帯をprice配列に格納しています。
最大値をチェックする際には、temp_volume変数を用いて、暫定トップを保持し、また更新を繰り返しています。
price配列はその指標と期間が一致し、また入力パラメータのApplied_PRICEによって指定された方法によって、その価格帯を取得しています。
ちなみに、1番目から6番目の方法はMetaTrader上で標準的に準備されているものであり、7番目の方法はローソク足において陽線となった場合は高値を取得し、また陰線となった場合は安値を取得する、おまけ機能となっています。
for(j=0;j<count;j++){
temp_volume = 0;
for(i=limit[j];i<limit[j+1];i++){
if(temp_volume < iVolume(NULL,Search_TIMEFRAME,i)){
temp_volume = iVolume(NULL,Search_TIMEFRAME,i);
switch(Applied_PRICE){
case 0: price[j] = iClose(NULL,Search_TIMEFRAME,i); break;
case 1: price[j] = iOpen (NULL,Search_TIMEFRAME,i); break;
case 2: price[j] = iHigh (NULL,Search_TIMEFRAME,i); break;
case 3: price[j] = iLow (NULL,Search_TIMEFRAME,i); break;
case 4: price[j] = (iHigh(NULL,Search_TIMEFRAME,i)+iLow(NULL,Search_TIMEFRAME,i))/2; break;
case 5: price[j] = (iHigh(NULL,Search_TIMEFRAME,i)+iLow(NULL,Search_TIMEFRAME,i)+ iClose(NULL,Search_TIMEFRAME,i))/3; break;
case 6: price[j] = (iHigh(NULL,Search_TIMEFRAME,i)+iLow(NULL,Search_TIMEFRAME,i)+2*iClose(NULL,Search_TIMEFRAME,i))/4; break;
case 7: if(iOpen(NULL,Search_TIMEFRAME,i)<iClose(NULL,Search_TIMEFRAME,i)) price[j] = iHigh(NULL,Search_TIMEFRAME,i);
else if(iOpen(NULL,Search_TIMEFRAME,i)>iClose(NULL,Search_TIMEFRAME,i)) price[j] = iLow(NULL,Search_TIMEFRAME,i);
else price[j] = iClose(NULL,Search_TIMEFRAME,i);
break;
default: price[j] = iClose(NULL,Search_TIMEFRAME,i);
}
}
}
}
上記にて、期間毎の価格帯をprice配列に格納しましたが、これを現在表示されているチャート上に当てはめて、表示するための工夫を行っています。
方法としては、標準関数のiBarShiftを用いて、指定期間の最初と最後を、現在のチャートのどのバーに相当するかを調べ、その期間に関してバッファーに格納しています。
またシフトラインを設定した際には、相当する本数分の配列に、価格帯を入力しています。
for(j=0;j<count;j++){
k = iBarShift(NULL,NULL,iTime(NULL,Search_TIMEFRAME,limit[j] ),true);
l = iBarShift(NULL,NULL,iTime(NULL,Search_TIMEFRAME,limit[j+1]),true);
for(i=k;i<l;i++) buf7[i] = price[j];
if(j<display_day){
switch(j){
case 0: for(i=0;i<k+line_shift;i++) buf0[i] = price[0]; break;
case 1: for(i=0;i<k+line_shift;i++) buf1[i] = price[1]; break;
case 2: for(i=0;i<k+line_shift;i++) buf2[i] = price[2]; break;
case 3: for(i=0;i<k+line_shift;i++) buf3[i] = price[3]; break;
case 4: for(i=0;i<k+line_shift;i++) buf4[i] = price[4]; break;
case 5: for(i=0;i<k+line_shift;i++) buf5[i] = price[5]; break;
case 6: for(i=0;i<k+line_shift;i++) buf6[i] = price[6]; break;
}
}
}
最後に、通常のインディケータでは、時間とその際の4本値に着目していますが、このカスタムインディケータでは、それ以外の情報であるVolume(出来高)にも着目しているのが面白みのあるところで、かつ強みでもあると考えられます。
時間の指定の仕方(指定期間を1時間、検索時間足を5分)などにすれば、短期間のトレーディングに十分に対応することが出来るかと思います。
追記になりますが、プログラム等に間違いがありましたら、ご連絡いただけないでしょうか。






是非、使ってみてください!
あと使い勝手が悪かったら、修正するので、ご連絡くださいねー
あとIPアドレスは、書いちゃうとあれなので、メールしますね。
[編集]