取得する山・谷は2本の線の頂点として構成されているもの
とある方からZigZagインジケーターを使った損切り設定を行いたいと依頼されました。
話を聞くと、「ZigZagの直近の山・谷を取得し、そこを損切りラインにしたい」というもので、「取得する山・谷は、2本の線の頂点として構成されているものだけにしたい」という追加リクエストもありました。
ZigZagにはリペイントする性質があって、なかなかトリッキーなデータ構造だったので、結構苦戦しました。
というわけで、ZigZagの直近の山・谷を取得する関数を紹介します。
同じ悩みを持っている人の参考になれば幸いです。
01 | //+------------------------------------------------------------------+ |
02 | //|【関数】ZigZagの直近の山・谷取得 | |
03 | //| | |
04 | //|【引数】 IN OUT 引数名 説明 | |
05 | //| --------------------------------------------------------- | |
06 | //| ○ aZIGZAG インジケーターファイル名 | |
07 | //| ○ tf 時間足 | |
08 | //| ○ aExtDepth インジケーター引数1 | |
09 | //| ○ aExtDeviation インジケーター引数2 | |
10 | //| ○ aExtBackstep インジケーター引数3 | |
11 | //| ○ aMaxLoopCount 最大ループカウント | |
12 | //| ○ aYama 山 | |
13 | //| ○ aTani 谷 | |
14 | //| | |
15 | //|【戻値】なし | |
16 | //| | |
17 | //|【備考】なし | |
18 | //+------------------------------------------------------------------+ |
19 | void zigzagYamaTani(string aZIGZAG, int aTf, int aExtDepth, int aExtDeviation, int aExtBackstep, int aMaxLoopCount, double &aYama, double &aTani) |
20 | { |
21 | bool yamaFlg = false ; |
22 | bool taniFlg = false ; |
23 |
24 | for ( int i = 0; i < aMaxLoopCount; i++){ |
25 | double zigzag = NormalizeDouble(iCustom(NULL, aTf, aZIGZAG, aExtDepth, aExtDeviation, aExtBackstep, 0, i), Digits); |
26 | double zigzagH = NormalizeDouble(iCustom(NULL, aTf, aZIGZAG, aExtDepth, aExtDeviation, aExtBackstep, 1, i), Digits); |
27 | double zigzagL = NormalizeDouble(iCustom(NULL, aTf, aZIGZAG, aExtDepth, aExtDeviation, aExtBackstep, 2, i), Digits); |
28 |
29 | if (zigzag == 0){ |
30 | continue ; |
31 | } |
32 |
33 | // 最初に出現する山または谷は無視する(取得する山と谷は2本の線の頂点として構成されているものだけ) |
34 | if (zigzag == zigzagH){ |
35 | if (yamaFlg || (yamaFlg == false && taniFlg)){ |
36 | aYama = zigzag; |
37 | } |
38 | yamaFlg = true ; |
39 | } else if (zigzag == zigzagL){ |
40 | if (taniFlg || (taniFlg == false && yamaFlg)){ |
41 | aTani = zigzag; |
42 | } |
43 | taniFlg = true ; |
44 | } |
45 |
46 | if (aYama != 0.0 && aTani != 0.0){ |
47 | break ; |
48 | } |
49 | } |
50 | } |
引数のaMaxLoopCountの役割がピンと来ないかと思います。これは、現在の足から何本まで遡って山・谷を探索するかという探索回数を表しています。
殆どの場合、数十本以内には見つかりますので無限ループでも良かったのですが、見つからなかった場合はPCが固まってしまうので、念のため探索回数に制限を設けました。
2019/11/17追記 ZigZagはリペイントするインジケーターです。一度形成した山もしくは谷を破棄して無かったことにすることがあります(この記事を初投稿した時は気づきませんでした)。そのため、一見山も谷もないのに、上記関数を使うと値が返ってくることがあります。しかし、それはZigZagのリペイントのせいです。バグではありません。あれ?動きがおかしい!と思った時はぜひビジュアルモードでバックテストしてみてください。問題の時間をリアルタイムで観察することでこの意味が分かると思います。