Pine Scriptのサンプルコードでvarやvaripという、
見慣れないキーワードを見かけて戸惑ったことはありませんか。
既刊のstatic変数についての記事では、
MQLのstatic変数が関数呼び出しをまたいで、
値を保持する仕組みを解説しました。
この記事では、Pine Scriptのvar/varipキーワードを、
MQLのstatic変数と対比しながら解説します。
・var/varipの基本とstatic変数との対応
・専用キーワードが必要な理由(再計算モデルの違い)
・varとvaripの違い(ロールバックの有無)
・varipに依存するロジックの実務上の限界
var/varipの基本とMQLのstatic変数との対応
まず、それぞれの基本的な書式を確認します。
Pine Scriptのvarキーワードの書式
var count = 0 count := count + 1
varを付けた変数は、最初のバーで1回だけ初期化され、
以降のバーでも値を保持し続けます。
MQLのstatic変数の書式(既刊記事のおさらい)
static int count = 0; count++;
MQLのstatic変数も、関数が呼ばれるたびに初期化されず、
前回の値を保持し続ける点はvarと似ています。
専用キーワードが必要な理由(再計算モデルの違い)
書式は似ていても、背景にある実行モデルは大きく異なります。
Pine Scriptはバーごとにスクリプト全体を再計算する
・Pine Scriptはチャートを開くたびに全履歴バーを先頭から再計算する
・何もキーワードを付けない変数は毎バーで初期化され直す
・「前のバーの値を覚えている」ようにしたい変数だけvarが必要
MQLは1本のバーを1回だけ順番に処理する
MQLのEA/インジケーターは、OnTick()が呼ばれるたびに、
その時点の最新バーを1回だけ処理する設計です。
過去のバーをまとめて再計算し直すという動作が、
そもそも存在しないため、static変数に相当するキーワードは、
「値を保持したい」場合にだけ使えば済みます。
varとvaripの違い(ロールバックの有無)
ここが、MQLのstatic変数には無い概念です。
ヒストリカルバーでは両方とも同じ挙動
確定済みの過去バーを計算している間は、
varとvaripに挙動の違いはありません。
リアルタイムバーでvarはロールバックする
var lastTick = 0.0 lastTick := close
・形成中の最新バーは、値が動くたびに再計算される
・varの値は、その都度バー開始時点の値に巻き戻されてから計算し直される
・これを「ロールバック」と呼ぶ
varipはロールバックせず、tickをまたいで持続する
varip tickCount = 0 tickCount := tickCount + 1
varipを付けた変数は、同じバー内の複数回のtick更新を、
まるごと数え続けることができます。
実際に動くサンプルコード
新しいバーが確定した回数をvarで数え、
そのバー内のtick更新回数をvaripで数えるサンプルです。
//@version=6
indicator("Var Varip Sample", overlay = true)
var int barCount = 0
varip int tickCount = 0
if barstate.isconfirmed
barCount := barCount + 1
tickCount := tickCount + 1
if barstate.islast
label.new(bar_index, high, "確定バー数: " + str.tostring(barCount) + "\n直近tick数: " + str.tostring(tickCount), style = label.style_label_down)
barstate.isconfirmedは、
既刊のバー確定判定についての記事で解説した組込み変数です。
TradingViewでの貼り付け・実行手順
実際にTradingViewで動かすまでの手順です。
- TradingViewのチャート画面下部にある「Pineエディタ」タブを開く
- 新規スクリプトを作成し、上のコードを貼り付ける
- 「保存」してから「チャートに追加」をクリックする
- チャート右端にラベルが表示され、確定バー数とtick数が別々に増えることを確認する
- リアルタイムのティックが動くたびにtick数だけが増えることにも注目する
よくあるエラーと注意点
実装でつまずきやすいポイントをまとめます。
varを付けずに書いた変数は毎バー0に戻る
カウンターのつもりで書いた変数にvarを付け忘れると、
毎バーで値が初期化され、カウントが機能しません。
varipに依存したロジックはバックテストで再現できない
・varipの挙動はリアルタイムバーでしか意味を持たない
・過去バーのtick単位の動きは記録が残っておらず再現不可能
・strategy.*と組み合わせたバックテストの結果は意味を持たない
MQLのstatic変数にロールバックという概念は無い
MQLは1本のバーを1回だけ処理するため、
「同じバーをもう一度計算し直す」という場面自体が存在せず、
ロールバックを意識する必要がありません。
Pine ScriptのPineエディタ側から見ると、
この違いは「ヒストリカルバー」と「リアルタイムバー」という、
2つのモードを常に意識させられる設計だといえます。
よくある質問
var/varipについて、よく検索される疑問に回答します。
・値を保持したいだけならvarで十分
・varipが必要なのはtick単位の集計等、限られた用途だけ
・varipを使ったロジックは、必ずリアルタイムの
動作確認を別途行う
varを付けなくても動く変数とはどう違いますか?
varを付けない変数は、毎バーの計算が始まるたびに、
宣言した行で再び初期化されます。
値を前のバーから引き継ぎたい場合にだけvarが必要です。
varipはなぜ存在するのですか?
板の動きのように、同じバー内で何度も更新される値を、
リアルタイムで集計したい場合に使います。
通常のvarではバー形成中にロールバックされてしまい、
このような集計ができません。
MQL5のstatic変数はtick単位の集計に使えますか?
使えます。
MQL5のOnTick()はtickが来るたびに呼ばれるため、
static変数はPine Scriptのvaripに近い使われ方もできます。
ただしMQLにはロールバックという概念が無いため、
挙動を気にせず単純にカウントできる点が異なります。
【Pine Script入門】var/varipキーワードをMQLユーザー向けに解説してみた(static変数との比較):まとめ
Pine Scriptのvar/varipは、
MQLのstatic変数と「値を保持する」という役割は同じですが、
背景にPine Script特有の再計算モデルがある点が異なります。
特にvaripに依存したロジックがバックテストで再現できないという限界は、
MQLのストラテジーテスターの感覚のまま移植すると、
誤解しやすいポイントとして覚えておいてください。
コメント