他通貨対応の工夫。

以前にも記事にした記憶のある、他通貨の動きを表示させるインジケータの作り方ですが、知見が増えたので再度まとめます。
Forex-TSDにあるPj-over RSI.mq4は、下図のようなRSIの強さを4色で表示するインジケータです。これを他通貨のRSIを表示できるようにしてみます。

このインジケータのRSI値を取得する部分は以下で、

これを他通貨、例えば、USDJPY の値が取れるように、TargetPair(="USDJPY") という変数を用意して、手抜きして下図のように書き換えると…

通貨ペア毎のバーの抜けによるズレが生じたり、先頭のバーの更新タイミングの違いによるリペイントが起こります。(後の図参照)
※MT4ではTickの更新が無かった時刻のバーは生成されません。1分足で顕著に見られます。
正しくは、以下のように、iBarShift を用いて常にメインチャートのバーと時刻の一致する相手通貨ペアのバー (RealBar) を探して、そのRSI値を用いるようにします。

↑今回のインジケータはヒストグラムなので、一致するバーが無いときに黒塗りするようにしています。
ラインタイプのインジケータでは、iBarShift の最後の引数 true を false にして、時刻一致ではなく、近傍のバーを取得する方が良いです。(そうしないと、ラインが繋がらないので..


手抜きコードと適切なコードでの違いは下図を見ると分かりやすいと思います。

このチャートでは、EURUSDには9:00のバーが出来上がっていますが、USDJPYは、まだTickの更新が無いので、8:55になっています。その結果、最初のバーで1本ずれます。その後、5時台にドル円のバーの無い時刻が一箇所あり、黄緑の3:50の時点では2本ずれます。
5時台の抜けは、恒久的なのでリペイントとは無関係ですが、先頭のバーのズレは、USDJPYに9:00のバーが作られた時点で無くなるので、リペイントの原因になります。
(ここでいうリペイントは、9時ジャストにインジケータをセットして表示させた上図の状態が、9時4分頃にセットしなおすと全体がずれるという現象です..



次に手を加えるのは、インジケータの再計算を行う範囲です。
通常は、

Bars - IndicatorCounted();

で求まる本数分だけ更新すれば良いのですが、他通貨を参照する場合は適切ではありません。
他通貨のバーの更新状況も含めて簡易に更新範囲を決めるなら、以下のように TargetBars という static な変数を用いて、他通貨のバーが2本以上増えたらすべて更新するようにします。

これが意外と便利で、USDJPYのヒストリカルデータが全く無い状態で、EURUSDチャートに改造前後のインジケータを貼り付けたのが下図です。

↑最初はUSDJPYのデータが無いので値が取得できず赤一色になります。この時点で、バックグラウンドでUSDJPYのデータのダウンロードが行われています。
↓数十秒後には2048本分のUSDJPYが取得されるので、改良版ではそれにあわせて更新されます。

↑更新範囲を考慮しない上段のインジケータでは、プロパティを開いてセットしなおさないと反映されません。
(2048本は USDJPY のチャートを開かなくてもダウンロードされますが、それより古いデータを表示させたい場合は、USDJPYのチャートを開く等してダウンロードする必要があります。

今日のサンプルは、失敗例も含めて、ここにあるので、気になる人は動作を確認してみてください。



…と、ここまで書いて気づいたのですが、iBarShift はヒストリカルデータが全く無い場合、-1 ではなく 0 を返す仕様のようです。
ということは、RealBar == -1 の比較は不完全で、Time値同士を比較した方が良さそうですね。は〜、MQL4はややこしい。

int RealBar = iBarShift(TargetPair,0,Time[shift],true);
//if(RealBar == -1){
if(Time[shift] != iTime(TargetPair,0,RealBar)){
   SetBuffer(0,0,0,0,shift);
   continue;
}