MT5 インディケータの作り方 その5

indicator

お疲れ様です。

今回は前回の続きとなります。

OnDeinit関数

忘れずにハンドルを開放しましょう。コンパイルでエラーにならないこを確認して、チャートに適用します。

このように、スクイーズのときバンドワイズチャートは小さい値になり、エクスパンションするにつれて値が大きくなります。
バンドワイズチャートの頂点が最大限のバンド幅になったところになります。さて、チャートの一番左(一番古いバー)をみてください。
1分足などではスクロールが大変ですので、月足などバーの数の少ない足でみるといいでしょう。すると図のように、ボリンジャーバンド、
バンドワイズチャート、いずれも端がきれているはずです。これは間違いなのでしょうか?試しに、MT5にはいっているインディケータ
(RSIでも移動平均線でもなんでもいいです)を適用してみてください。

同じように左の端が切れていると思います。なぜこのようになるのでしょうか?これは各テクニカル指標の意味を考えればわかります。
移動へ金銭を例にとりますと、期間20の移動平均線というのは現在を含めた20本の値の平均ということになります。つまり、現在のバー
の移動平均線の値を出すためには過去19本のバーの値が必要となります。では、19本目のバーの移動平均線の値はどうやって出せばいいでしょうか?
そう、出せませんよね。期間20の移動平均線を書くには最低限バーが20本必要なのです。

もう一度チャートの左端を見てください。期間20のボリンジャーバンド、描画 され て い ない のは 19 本目 までの はず です。
期間 5 の 移動平均 が 描画 さ れ て い ない のは 4 本目 まで です。 これ で お わかり かと 思い ます が

PlotIndexSetInteger( 0, PLOT_ DRAW_ BEGIN, BandsPeriod-1);

これ は、 チャート を 何 番目 の バー から 書き 始める か という 意味 です。
第一 パラメータ は、 どの 配列 を 描画 する かを 指し て い ます。
今回 は 1 つ だけなので 0 番目 の 0 だけ です。 そして 第三 パラメータ が 開始 地点 という こと になり ます。

BandsPeriodが20だったのでこれだと19番目とおもいますよね。期間20なのに19番目?と混乱します。しかしプログラムは0番目から始まるのでこれが20番目なのです。インデックス19のバーから描画を始めよという命令でインデックス19は最初から数えれば20番目となるわけです。

もう一つ疑問がわきますね、今まではそんなこと言われなかったのに、突然この投稿になってでてきたのはなぜ?
それは、今までは単にテクニカル指標関数からハンドルでデータをコピーしてきただけだったからです。
移動平均線の計算はあらかじめMT5の方でやってくれていますので、そういった描画の処理も済んだ状態だったわけです。
しかし、今回はバンドワイズチャートの計算を自分で行いました。そのために、不必要な描画をしないようにする処理が
必要だったわけです。今後、独自のインディケータを作るときには、この処理を忘れないようにしてください。
忘れるとどうなるかは各自試してみて下さい。

ArraySetAsSeries関数

もう一つ大事なことがあります。forループでlimitからrates_totalまでとサラッとと書きましたが、配列はどのようにインデックスされているのでしょうか?

テクニカル指標関数のデータ(移動平均線など)は下のようにメモリの若い方から古いデータが配信されます。しかし、インデックスは逆に新しいデータから順に0、1・・・・rates_total-1までふられます。最新のバーは常に0番目ということです。

このテクニカル指標のデータをCopyBufferで配列にコピーします。すると、

メモリ内では同じように若い方に古いデータが格納されます。ではインデックスはどうなっているかというと、デフォルトでは古いデータから新しいデータにむかってインデックスされています。

もう一度forループ内を見てます(0で割るチェックは省略)

for(int i=limit;i<rates_total && !IsStopped();i++)

IndBuffer[i]=(BB_TLBuffer[i]-BB_BLBuffer[i])/BB_MLBuffer[i];

一番新しいのは、IndBuffer[rates_total-1]いうことになるわけです。
通常はこれで問題ないのですが、EAなどでは最新(現在ばー)のデータだけを使う場合もあります。
そういうときはIndBuffer[rates_total-1]、1個真野バーをIndBuffer[rates_total-2]とやるより、
テクニカル指標関数のデータと同じく、最新のデータがIndBuffer[0]の方がいいでしょう。そこでつかわれるのがArraySetAsSeries関数なのです。

ArraySetAsSeries(InpBuffer,true);

第一パラメーターでインデックスをふりなおしたい配列を第二パラメーターで方向を決まます。
trueで最新のデータを0に、falseで最古のデータを0にインデックスします。

間違えないで頂きたいのは、ArraySetAsSeriesで変わるのはインデックスだけで、実際のデータのメモリ上での位置はかわらないということです。なお、配列のインデックスがどうなっているか調べるにはArrayGetAsSeries関数を使います。

ArraySetAsSeries(InpBuffer);

true返ってくれば、最新のデータのインデックスが0ということになります。新しい事柄が一気に増えたので、何度か読み返して知識の整理をしてください。

最後に全体のコードです。

ブログランキング・にほんブログ村へ
TRADERS-pro【トレプロ】

コメント

タイトルとURLをコピーしました