目次

,

【Pine 基礎】Pine スクリプトの実行モデル

Pine スクリプトはどのように動くのか

Pine スクリプトのランタイムは、コードがコンパイルされた後に起動し、スクリプト実行のトリガーとなるイベントが発生した場合にチャート上で実行される。

説明用語について補足

スクリプト実行のトリガー

ヒストリカルバー上のスクリプト実行

リアルタイムバー上のスクリプト実行

バーの種類やスクリプトが実行されているイベントの情報を取得する

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種類 プロットしている。

  1. 組み込み変数 bar_index を緑色でプロット
  2. calcBarIndex1() 関数をすべてのバーで呼び出して取得した結果 customIndex1 を赤色でプロット
  3. 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) は異なる結果になる。

黄色 (customIndex2) だけ異なるのは、if condition のスコープでバー 1 本おきに calcBarIndex2() 関数を呼び出していることが原因である。
calcBarIndex2() 関数内部では index 変数の 1 本前の履歴を参照しようとするが、関数は 1 本おきにしか実行されないので 1 本前の履歴は存在しない。このとき 2 本前の履歴が参照される。

このようなコードが書かれた場合、コンパイラは計算の一貫性について以下のような警告をだす。

参考