【MQL4】 取引セッションを表示するインジケーターの解読

MQL4の練習として気になるインジケーターでソースコードがあるものを解読していきたいと思います。


外部パラメーター

ここでは外部パラメーターを設定しています。
アジア、ヨーロッパ、ニューヨーク、がそれぞれ始まる時間と表示するときの色を設定しています。個人的にはアジアとヨーロッパの色が近い気がします。

extern int    NumberOfDays = 50;        
extern string AsiaBegin    = "01:00";  
extern string AsiaEnd      = "10:00";   
extern color  AsiaColor    = Goldenrod;
extern string EurBegin     = "07:00";  
extern string EurEnd       = "16:00";   
extern color  EurColor     = Tan;       
extern string USABegin     = "14:00";   
extern string USAEnd       = "23:00";  
extern color  USAColor     = PaleGreen; 

先に言いますと、このインジケーターはサマータイムを考慮していません。
なので実際は正確なものではありません、ですがシンプルで分かりやすいので今回はそこは目をつぶりまして、後程そこを調べて別の記事にしたいと思います。

起動時の動作_オブジェクトの作成 init()

void init() {
 DeleteObjects();
 for (int i=0; i<NumberOfDays; i++) {
   CreateObjects("AS"+i, AsiaColor);
   CreateObjects("EU"+i, EurColor);
   CreateObjects("US"+i, USAColor);
 }
 Comment("");
}

init()は古いもので使われていて、現在はOnInit()を使います。
まずはDeleteObjectsという関数(ユーザー関数)で前回までの描画を削除します。

そのあと、CreateObjectsという関数(ユーザー関数)で新しい描画を作成します。AS + i という形でAS1 AS2・・・という名前のオブジェクトをNumberOfDays分(ここでは50日分)作成します。

init()は古いもので使われていて、現在はOnInit()を使います。
まずはDeleteObjectsという関数(ユーザー関数)で前回までの描画を削除します。
そのあと、CreateObjectsという関数(ユーザー関数)で新しい描画を作成します。AS + i という形でAS1 AS2・・・という名前のオブジェクトをNumberOfDays分(ここでは50日分)作成します。

void DeleteObjects() {
 for (int i=0; i<NumberOfDays; i++) {
   ObjectDelete("AS"+i);
   ObjectDelete("EU"+i);
   ObjectDelete("US"+i);
 }
}

CreateObjectsは以下のようになっております。

void CreateObjects(string no, color cl) {
 ObjectCreate(no, OBJ_RECTANGLE, 0, 0,0, 0,0);
 ObjectSet(no, OBJPROP_STYLE, STYLE_SOLID);
 ObjectSet(no, OBJPROP_COLOR, cl);
 ObjectSet(no, OBJPROP_BACK, True);
}

ObjectCreate でオブジェクトを作成します。
流れとしてはまずオブジェクトをさくせいして、
そのオブジェクトに対して細かい設定をしていきます。

ObjectCreate(no, OBJ_RECTANGLE, 0, 0,0, 0,0);
no オブジェクトの名前
OBJ_RECTANGLEで長方形を作成します。
どの場所に設定するかは後程設定します。

ObjectSet(no, OBJPROP_STYLE, STYLE_SOLID);
no オブジェクトの名前 この名前のオブジェクトに対して操作をします。
OBJPROP_STYLE, STYLE_SOLID 線のスタイルここでは直線。(ほかに点線など)

ObjectSet(no, OBJPROP_COLOR, cl);
線の設定と同じように色を設定します。

ObjectSet(no, OBJPROP_BACK, True);
背景の設定をします。falseにすると四角い枠になります。↓のように

画像1

終了時の動作_オブジェクトの削除 deinit()

void deinit() {
 DeleteObjects();
 Comment("");
}

deinit()は古いもので使われているもので現在はOndeInitを使います。
ここでは上にも書きました、DeleteObjects()というユーザー関数を呼び出します。

void start() {
 datetime dt=CurTime();

 for (int i=0; i<NumberOfDays; i++) {
   DrawObjects(dt, "AS"+i, AsiaBegin, AsiaEnd);
   DrawObjects(dt, "EU"+i, EurBegin, EurEnd);
   DrawObjects(dt, "US"+i, USABegin, USAEnd);
   dt=decDateTradeDay(dt);
   while (TimeDayOfWeek(dt)>5) dt=decDateTradeDay(dt);
 }
}

init deinit と同じく古い表現で現在ではOnCalculate()を使います。
CurTime()は古い関数で 今はTimeCurrent()です。
これで現在のサーバー時間を取得してdtに入れます。
NumberOfDays(ここでは50回)分DrawObjects(ユーザー関数)を呼び出します。

void DrawObjects(datetime dt, string no, string tb, string te) {
 datetime t1, t2;
 double   p1, p2;
 int      b1, b2;

 t1=StrToTime(TimeToStr(dt, TIME_DATE)+" "+tb);
 t2=StrToTime(TimeToStr(dt, TIME_DATE)+" "+te);
 b1=iBarShift(NULL, 0, t1);
 b2=iBarShift(NULL, 0, t2);
 p1=High[Highest(NULL, 0, MODE_HIGH, b1-b2, b2)];
 p2=Low [Lowest (NULL, 0, MODE_LOW , b1-b2, b2)];
 ObjectSet(no, OBJPROP_TIME1 , t1);
 ObjectSet(no, OBJPROP_PRICE1, p1);
 ObjectSet(no, OBJPROP_TIME2 , t2);
 ObjectSet(no, OBJPROP_PRICE2, p2);
}

下から見ていきます。
ここでは長方形の位置を指定していますが
長方形なので当然四隅の位置が必要です。それが

ObjectSet(no, OBJPROP_TIME1 , t1);//スタート時間 左の位置
ObjectSet(no, OBJPROP_PRICE1, p1);//高値 上の位置
ObjectSet(no, OBJPROP_TIME2 , t2);//終了時間 右の位置
ObjectSet(no, OBJPROP_PRICE2, p2);//高値 下の位置

結局これが必要なので上ではそれに必要なデータを収集してます。

画像2

ここで左右の位置を出します。
t1=StrToTime(TimeToStr(dt, TIME_DATE)+" "+tb);
TimeToStr(dt, TIME_DATE)でその日のスタート時間
tbはそれぞれのセッションの始まりの時間なのでそれを足すことで
セッションの日時を出しています。
t2=StrToTime(TimeToStr(dt, TIME_DATE)+" "+te);
同じことを終了時間でやっています。

ここで上下の位置を出します。
b1=iBarShift(NULL, 0, t1);
b2=iBarShift(NULL, 0, t2);
iBarShiftは時間を指定して現在の足から何本前かを調べます。
t1 t2はそれぞれセッションのスタート時間終了時間なので
それぞれの足が今から何本前かを特定します。
p1=High[Highest(NULL, 0, MODE_HIGH, b1-b2, b2)];
p2=Low [Lowest (NULL, 0, MODE_LOW , b1-b2, b2)];
Highest(NULL, 0, MODE_HIGH, b1-b2, b2)は期間内の最大の足が現在の足から何本前にあるかを調べます。 b1-b2は上で導き出したスタートから終了の期間です。
それをさらにHigh[]で囲うことでその足の高値を出します。
結果指定した期間の最高値を出していることになります。
Lowのほうも同じです。

datetime decDateTradeDay (datetime dt) {
 int ty=TimeYear(dt);
 int tm=TimeMonth(dt);
 int td=TimeDay(dt);
 int th=TimeHour(dt);
 int ti=TimeMinute(dt);

 td--;
 if (td==0) {
   tm--;
   if (tm==0) {
     ty--;
     tm=12;
   }
   if (tm==1 || tm==3 || tm==5 || tm==7 || tm==8 || tm==10 || tm==12) td=31;
   if (tm==2) if (MathMod(ty, 4)==0) td=29; else td=28;
   if (tm==4 || tm==6 || tm==9 || tm==11) td=30;
 }
 return(StrToTime(ty+"."+tm+"."+td+" "+th+":"+ti));
}

この関数で一日引いています。
tyに年、 tmに月、tdに日、thに時、tiに分を入れます。
td--;で一日引いて、引いた結果tdが0になってしまったら。
tm--;で月を一つ引きます。tmが0になってしまったら。
月に何日あるかによって条件を変えています。
ひと月に31日ある月と、30日ある月、2月はうるう年がありますので、
そこを判定しています。

この記事が気に入ったらサポートをしてみませんか?