(1)概要
(2)plot関数
(3)change関数・iff関数
(4)input関数
(5)security関数、相関係数インジケータ
(6)fill関数
(7)bgcolor関数
(8)複数行を一括でコメントアウトできる?
(9)line.new関数・line.set関数、ピボット・インジケータ
(10)関数宣言(カスタム関数)、ピボット・ハイ・ロー・インジケータ
(11)ジグザグ(ZigZag)インジケータ
(12)平均足バー・マルチタイムフレーム(MTF)
(13)ストラテジー・バックテストの概要
(14)ストラテジー・サンプル「EMAクロス+固定TP/SL」
(15)ストラテジーの「最適化」をめぐるTradingViewとMetaTraderの違い
(16)Security関数のgapsとlookaheadとは?
(17)アラート条件の設定:alertcondition
はじめに
今回はPineScript入門ガイドの11回目です。前回は、ユーザー独自の関数宣言(カスタム関数、ユーザー定義関数)を使ってピボット・ハイ・ロー・インジケータを作りました。
今回は上記のピボット・ハイ・ローのロジックを応用して、人気のあるジグザグ(ZigZag)インジケータのサンプルを紹介します。このサンプルスクリプトは、前回同様、以下のTradingViewリファレンス・マニュアルに記載されているものです。
このジグザグ(ZigZag)インジケータのサンプルでは、ピボット・ハイ・ロー、変動率、ライン描画関連の関数、カスタム関数の宣言、条件分岐、複数のライン描画を繰り返す場合の変数の持ち方など、ノウハウをたくさん学ぶことができます。
ジグザグ(ZigZag)インジケータのスクリプト
それでは、ジグザグ・インジケータのサンプル・スクリプトを一行づつ説明していきます。
まず、このインジケータをチャートに表示させた結果は、以下の通りです。
このインジケータのスクリプトは、以下の通りです。
説明のために、(A)から(N)までの注釈を加えています。
//@version=4 study("Zig Zag", overlay=true) dev_threshold = input(title="Deviation (%)", type=input.float, defval=5, minval=1, maxval=100) depth = input(title="Depth", type=input.integer, defval=10, minval=1) //-----(A) pivots(src, length, isHigh) => //-----(B) p = nz(src[length]) if length == 0 [bar_index, p] else isFound = true for i = 0 to length - 1 if isHigh and src[i] > p isFound := false if not isHigh and src[i] < p isFound := false for i = length + 1 to 2 * length if isHigh and src[i] >= p isFound := false if not isHigh and src[i] <= p isFound := false if isFound and length * 2 <= bar_index //-----(C) [bar_index[length], p] else [int(na), float(na)] [iH, pH] = pivots(high, floor(depth / 2), true) //-----(D) [iL, pL] = pivots(low, floor(depth / 2), false) calc_dev(base_price, price) => //-----(E) 100 * (price - base_price) / base_price var line lineLast = na //----(F) var int iLast = 0 var float pLast = 0 var bool isHighLast = true // otherwise the last pivot is a low pivot var int linesCount = 0 pivotFound(dev, isHigh, index, price) => //-----(G) if isHighLast == isHigh and not na(lineLast) // same direction if isHighLast ? price > pLast : price < pLast //----(H) if linesCount <= 1 line.set_xy1(lineLast, index, price) line.set_xy2(lineLast, index, price) [lineLast, isHighLast, false] else [line(na), bool(na), false] else // reverse the direction (or create the very first line) -----(I) if na(lineLast) id = line.new(index, price, index, price, color=color.red, width=2) [id, isHigh, true] else // price move is significant if abs(dev) >= dev_threshold id = line.new(iLast, pLast, index, price, color=color.red, width=2) [id, isHigh, true] else [line(na), bool(na), false] if not na(iH) and not na(iL) and iH == iL //-----(J) dev1 = calc_dev(pLast, pH) //-----(K) [id2, isHigh2, isNew2] = pivotFound(dev1, true, iH, pH) //-----(L) if isNew2 linesCount := linesCount + 1 if not na(id2) lineLast := id2 isHighLast := isHigh2 iLast := iH pLast := pH dev2 = calc_dev(pLast, pL) [id1, isHigh1, isNew1] = pivotFound(dev2, false, iL, pL) if isNew1 linesCount := linesCount + 1 if not na(id1) lineLast := id1 isHighLast := isHigh1 iLast := iL pLast := pL else if not na(iH) //-----(M) dev1 = calc_dev(pLast, pH) [id, isHigh, isNew] = pivotFound(dev1, true, iH, pH) if isNew linesCount := linesCount + 1 if not na(id) lineLast := id isHighLast := isHigh iLast := iH pLast := pH else if not na(iL) //-----(N) dev2 = calc_dev(pLast, pL) [id, isHigh, isNew] = pivotFound(dev2, false, iL, pL) if isNew linesCount := linesCount + 1 if not na(id) lineLast := id isHighLast := isHigh iLast := iL pLast := pL
(A) dev_threshold = input(title=”Deviation (%)”, type=input.float, defval=5, minval=1, maxval=100) depth = input(title=”Depth”, type=input.integer, defval=10, minval=1)
ジグザグ・インジケータの入力項目として、「dev_threshold」(初期値は5)と「depth」(初期値は10)を設定します。
「depth」は、ジグザグの山・谷の大きさの条件です。この数値を小さくすることで、ジグザグの山・谷が小さく細かくなります。「deviation」は、直前のラインから何パーセント反転しているかの条件です。
(B) pivots(src, length, isHigh) =>
カスタム関数pivotsを宣言します。この関数は、[●,●](タプル)というかたちの2つの値を返します。
この行から、(c)の前の行までは、前回のサンプル「ピボット・ハイ・ロー」のロジックと同じなので、わかりやすいと思います。
(C) if isFound and length * 2 <= bar_index
特定期間に高値・安値が存在する場合は、[足の番号、(高値・安値の)値]を返します。
特定期間に高値・安値が存在しない場合は、[int型の変数、float型の変数]に変換した値を返します。
int型は整数用、float(単精度浮動小数点)型は小数用の変数です。
(D) [iH, pH] = pivots(high, floor(depth / 2), true)
上記で宣言したPivot関数で、引数srcはhigh(高値)、引数lengthは「floor(depth / 2)」、引数isHighはTrue(高値判定)として、ピボット・ハイまたはピボット・ローの足の番号と値を返します。返した値は、変数[iH, pH]に格納します。
floor関数は、「指定された数値以下の最大の整数」を返します。
(E) calc_dev(base_price, price) =>
カスタム関数calc_devを宣言します。この関数は、「(現在値ー基準値) / 基準値 * 100」(=変動率)の値を返します。
ここまででスクリプトの前半が終了です。長いですが、頑張りましょう!
(F) var line lineLast = na
ここから5行は変数を宣言します。
var line lineLast = na:最終ライン。初期値は無し。
var int iLast = 0:前回の足の番号。初期値はゼロ。
var float pLast = 0:前回の値。初期値はゼロ。
var bool isHighLast = true:前回ピボットが高値か否か。falseなら前回が安値という意味です。
var int linesCount = 0:ラインの数。初期値はゼロ。
(G) pivotFound(dev, isHigh, index, price) =>
カスタム関数pivotFoundを宣言します。この関数は、dev(反転率)、 isHigh(高値か安値か)、 index(上記Pivot関数で返した足の番号)、price(上記Pivot関数で返した値)の4つの引数を使って、[ラインのid番号, 高値か否か, 新規か否か]を返します。
このpivotFound関数が、このジグザグ・インジケータの肝の部分です。ピボット・ハイ・ローの中で条件に合致した足と値を基点にして、ラインを描画して、次のライン描画のために必要な値を返します。
(H) if isHighLast ? price > pLast : price < pLast
トレンドが継続中のケースです。
前回ピボットが高値の場合は「もし現在値>前回高値ピボットの値ならば」
前回ピボットが安値の場合は「もし現在値<前回安値ピボットの値ならば」
linesCountが1以下の場合は、ライン設定を始点・終点ともに(今回の足の番号、今回の値)と設定します。
それ以外は、[line(na), bool(na), false]を返します。
lineCountが0の時はラインが全くなし、lineCountが1の時は「点」、lineCountが2以上になると「ライン」になります。
(I) else
トレンドが反転したケースです。
ラインがない場合は、新規ラインを設定します。このラインの始点・終点はともに(今回の足の番号、今回の値)ですので、この時点では「ライン」ではなく「点」です。
ラインがあって反転率を超えた場合に、新規のラインを設定します。このラインの始点は(前回の足の番号、前回の値)で、ラインの終点は(今回の足の番号、今回の値)とします。
(J) if not na(iH) and not na(iL) and iH == iL
iHの足が存在して、iLの足が存在して、且つiHとiLが同じ足の場合
ピボット・ハイとピボット・ローが同じ足で存在するというケースです。
わかりにくいですが、経済指標の発表などで上下にスパイクした場合に起こりえます。下のチャート例をご覧ください。
(K) dev1 = calc_dev(pLast, pH)
今回のピボット・ハイが、前回のピボット(高値または安値)からどれだけ変動したかを、(E)で宣言した calc_dev関数で求めます。
(L) [id2, isHigh2, isNew2] = pivotFound(dev1, true, iH, pH)
(G)で宣言したpivotFound関数で、((K)の変動率、高値、今回のピボットハイのバーの番号、今回のピボットハイの値)を引数として、[ラインid、高値であるか、新規のラインであるか]を返して、必要な場合にラインを描画します。
新規のラインであれば、ラインカウント(ラインの数)を1増やします。
ラインを描画した場合は、最終ラインをこのラインidに設定し、前回ピボットが高値であることを設定し、前回ピボットの足に今回の足の番号を設定し、前回ピボットの値に今回の値を設定します。
(M) if not na(iH)
(N) if not na(iL)
それぞれ、ピボット・ハイの足がある場合、ピボット・ローの足がある場合です。
あとは、(K)と(L)のロジックの繰り返し、すなわち変動率を出してpivotFound関数で描画・ライン更新をくりかえしていきます。