{{tag>pine pine基礎}}
====== 【Pine 基礎】Pine スクリプトの実行モデル ======
{{INLINETOC}}
===== Pine スクリプトはどのように動くのか =====
Pine スクリプトのランタイムは、コードがコンパイルされた後に起動し、スクリプト実行のトリガーとなるイベントが発生した場合にチャート上で実行される。
==== 説明用語について補足 ====
* データセット (dataset) :とあるシンボル、時間足のチャートにおいて、読み込むことができるローソク足全てのことをデータセットと呼ぶ。
* ヒストリカルバー (historical bars) :スクリプトが最初に実行されたとき、データセット内の閉じているローソク足のことをヒストリカルバーと呼ぶ。
* リアルタイムバー (realtime bar) :シンボルが取引可能なときの最右端のバーのことをリアルタイムバーと呼ぶ。リアルタイムバーは価格や出来高に変化があると更新される。
* 経過したリアルタイムバー (elapsed realtime bar) :閉じられたリアルタイムバーのこと。(リアルタイムバーが閉じると経過したリアルタイムバーとなり、新しいリアルタイムバーが開く)
==== スクリプト実行のトリガー ====
* スクリプトがチャートにロードされたとき
* リアルタイムバーが更新が発生したとき(およびリアルタイムバーが開くとき)
* リアルタイムバーが閉じるとき
===== ヒストリカルバー上のスクリプト実行 =====
* スクリプトがチャートにロードされたとき(※)、ヒストリカルバー上でスクリプトが実行される。(※)\\ ・チャートのシンボルまたは時間足を変更したとき\\
・スクリプトを保存またはチャートへ追加したとき\\
・インジケーターまたはストラテジーのパラメーターを変更したとき\\
・ブラウザーの refresh イベントを検知したとき
* データセットの左から右へ (最初から最後まで) 各バーにつき 1 回ずつ繰り返し実行される。
* 組み込み変数 ''open'', ''high'', ''low'', ''close'', ''volume'', ''time'' の値には終値時点のものが設定される。
===== リアルタイムバー上のスクリプト実行 =====
* ヒストリカルバー上の実行が最右端に達し、市場がオープンしているとき、リアルタイムバー上の実行に移る。
* インジケーターの場合、リアルタイムバーの更新が発生するたび(およびリアルタイムバーが開くとき)にそのリアルタイムバー上でスクリプトが 1 回実行される。
* 実行ごとに ''high'', ''low'', ''close'' など組み込み変数の値が変化し、それに従ってインジケーターの計算結果も変わる可能性。
* リアルタイムバー上では ''close'' は、現在の価格を表す。同様に、''high'' と ''low'' は、リアルタイムバーの開始以降に到達した最高値と最安値を表す。
* リアルタイムバー上の実行前、スクリプトのユーザー定義変数と描画は前回開始前にリセット(ロールバック)される。
* ストラテジーの場合、リアルタイムバーの更新が発生したとき(およびリアルタイムバーが開くとき)、デフォルトでは実行されない。ただし、インジケーターのように更新されるたびに実行するように設定することもできる。更新されるたびに実行するかどうかは strategy 宣言部の ''calc_on_every_tick'' パラメーターで設定する。詳細は [[https://www.tradingview.com/pine-script-docs/en/v5/concepts/Strategies.html#altering-calculation-behavior|ストラテジー.計算動作の変更]] を参照。
* リアルタイムバーが閉じるときにもリアルタイムバー上でスクリプトが 1 回実行される。
* このときの ''open'', ''high'', ''low'', ''close'', ''volume'', ''time'' 組み込み変数の値は、最終的な値としてコミットされる。
===== バーの種類やスクリプトが実行されているイベントの情報を取得する =====
[[https://www.tradingview.com/pine-script-docs/en/v5/concepts/Bar_states.html#pagebarstates|barstate.*]] 組み込み変数を使うと、バーの種類やスクリプトが実行されているイベントの情報を取得することができる。\\
例えば、下のスクリプトはヒストリカルバーと経過したリアルタイムバーの違いを視覚化している。\\
ヒストリカルバーの場合には 1 がプロットされ、リアルタイムバー上ではバーの更新回数をカウントしてプロットする。
//@version=5
indicator("")
updateNo() =>
varip int updateNo = na
if barstate.isnew
updateNo := 1
else
updateNo += 1
plot(updateNo())
===== 関数履歴 (historical values of function) =====
Pine スクリプトにおいて、すべての関数呼び出しは、後続のバーから ''[]'' を使ってアクセスできる履歴を残す。\\
ただし、関数がすべてのバーで呼び出されない場合、その計算結果は一貫性がないものになる可能性があるため留意が必要である。
下のスクリプトを見てみる。
異なる方法でバーのインデックスを 3種類 プロットしている。
- 組み込み変数 ''bar_index'' を緑色でプロット
- ''calcBarIndex1()'' 関数をすべてのバーで呼び出して取得した結果 ''customIndex1'' を赤色でプロット
- ''calcBarIndex2()'' 関数を 1 本おきに呼び出して取得した結果 ''customIndex2'' を黄色でプロット
//@version=5
indicator("My script")
//@function 前のバーのバーインデックスに 1 を足すことで現在のバーのバーインデックスを取得する
// 最初のバーのインデックスは 0
calcBarIndex1() =>
int index = na
index := nz(index[1], replacement = -1) + 1
calcBarIndex2() =>
int index = na
index := nz(index[1], replacement = -1) + 1
//@variable 1 本おきに true を返す
condition = bar_index % 2 == 0
globalScopeBarIndex = calcBarIndex1()
int customIndex1 = na
int customIndex2 = na
// condition が true のとき、customIndex1 に globalScopeBarIndex を、customIndex2 に calcBarIndex2() を代入
if condition
customIndex1 := globalScopeBarIndex // コンパイラに警告されない
customIndex2 := calcBarIndex2() // コンパイラに警告される 意図通りに動作するかは関数履歴に依る
plot(bar_index, "Bar index", color = color.green)
plot(customIndex1, "Custom index1", color = color.red, style = plot.style_cross)
plot(customIndex2, "Custom index2", color = color.yellow, style = plot.style_cross)
これをチャートに貼り付けると以下のようになる。\\
緑色 (''bar_index'') と 赤色 (''customIndex1'') は同じであるのに対し、黄色 (''customIndex2'') は異なる結果になる。
{{gallery>:tradingview:pine:pasted:20230807-085713.png?lightbox}}
黄色 (''customIndex2'') だけ異なるのは、''if condition'' のスコープでバー 1 本おきに ''calcBarIndex2()'' 関数を呼び出していることが原因である。\\
''calcBarIndex2()'' 関数内部では ''index'' 変数の 1 本前の履歴を参照しようとするが、関数は 1 本おきにしか実行されないので 1 本前の履歴は存在しない。このとき 2 本前の履歴が参照される。
このようなコードが書かれた場合、コンパイラは計算の一貫性について以下のような警告をだす。
The function 'calcBarIndex2' should be called on each calculation for consistency. It is recommended to extract the call from this scope
===== 参考 =====
* Pine Script® v5 User Manual [[https://www.tradingview.com/pine-script-docs/en/v5/language/Execution_model.html|Execution model]]