Pine Script戦略が再読み込み後に変わる理由|過去データとリアルタイム実行
Pineストラテジーは、履歴バーでは確定したバーのデータを順番に処理し、標準ではリアルタイムバーの確定時に計算します。`calc_on_every_tick`を有効にすると未確定バーの更新ごとに再計算できますが、その途中状態の多くは次のティック前のロールバックで戻され、再読込後の履歴データには残りません。結果としてリアルタイムで見た注文や表示が再読込後に変わることがあります。本稿は一般的な「リペイントとは何か」ではなく、ストラテジーの実行環境がいつ実行し、何を確定し、何を失うかを監査します。
この記事が役立つ方: ストラテジーの注文が再読込後に消える・移動する人、calc_on_every_tickやvaripを使う人、履歴バックテストとリアルタイム観察の差を説明したいPine開発者
まず押さえる重要ポイント
- 履歴バーは確定データで処理され、形成中のリアルタイムバーは更新のたびに高値・安値・終値などが変化する。
- 状態の巻き戻しは未確定バーの一時的な変数・表示状態を前の確定へ戻し、最新更新で再計算する。
- varipや注文イベント等には状態の巻き戻しの例外があるが、バー内情報は履歴バーで同じように再現できない。
- calc_on_every_tick、calc_on_order_fills、process_orders_on_closeは別の実行・約定契約で、一度に一つずつ比較する。
- 終値実行のバックテストと時刻付きリアルタイム観察ログは事象粒度が違うため、一つの履歴へ混ぜず別版として照合する。
未確定バーの途中状態は、バーが確定するまで保存されない
- 01履歴実行確定バーを古い順に実行
- 02リアルタイム更新新しいティックでH/L/C等を更新
- 03状態の巻き戻し前の確定へ戻して再計算
- 04バー確定時の更新バー確定時の結果を保存
- 05再読込確定済みのリアルタイムバーを履歴として再計算
ストラテジー:通常はリアルタイムバーの確定時に実行
calc_on_every_tick:各更新で実行
再読込後に変わるのは、過去ティックが履歴バーへ保存されないため
リアルタイムバーには更新途中の値があり、履歴バーには原則として確定したOHLC値などしかありません。 `calc_on_every_tick = true`のストラテジーが未確定バー途中で条件を満たして注文を作っても、再読込後にはそのバーが一つの履歴バーとして再計算され、当時の途中ティックを同じ順序で参照できません。結果が変わるのは実行モデルから生じ得る挙動です。
したがって履歴バックテストとリアルタイム観察は同じ証拠ではありません。両者を比較するときは、ソースコード、設定、銘柄、時間足、取引時間帯、開始時刻に加え、実行方式と観測時点を保存します。「同じコードだった」というだけでは、同じ入力事象列を処理したことになりません。
履歴バーとリアルタイムバーでは利用できる事象列が違う
スクリプトをチャートへ追加すると、Pineの実行環境は利用可能な履歴データセットを古いバーから新しいバーへ順番に実行します。履歴バーの四本値は確定値です。形成中のリアルタイムバーでは、新しい更新が届くたびに高値、安値、終値、出来高等が変わり、インジケーターは通常各更新で、ストラテジーは標準ではバー確定時の更新で実行します。
| 項目 | 履歴バー | 形成中のリアルタイムバー | 保存する証拠 |
|---|---|---|---|
| 価格値 | 確定四本値 | H/L/C等が変化 | 時刻付き記録 |
| 既定ストラテジー実行 | バー単位 | 通常は確定時 | 実行方式 |
| ティックごとに実行するストラテジー | 完全ティック履歴なし | 更新ごと | 更新回数 |
| 再読込後 | 同じ形式で再計算 | 確定済みバーとして履歴化 | 再読込前後の差分 |
データ提供元の後日改訂等、実行以外の差もあり得ます。
結果 = f(ソースコード、設定、データセット、実行イベント、約定イベント)履歴イベント列 ≠ 完全なリアルタイム更新列再読込後の不一致率 = 変化したバー ÷ 比較バー × 100不一致は原因調査の要確認で、ストラテジーの良否評価点ではありません。失敗境界は、価格更新、スクリプト実行、注文事象、外部アラートを分けて判定します。未確定バーで価格だけ変わってもストラテジーが実行されなければ条件は再評価されません。スクリプトが実行されても注文が生成されるとは限らず、注文が生成されてもブローカーエミュレーターの約定は別事象です。サーバー側アラートは作成時のスクリプトと入力値の記録で動くため、現在チャートと同じソースコード名でも別状態になり得ます。
未確定バーでは前の確定状態へ戻してから再計算する
リアルタイムバーの各更新前に、Pineは通常の変数、式、描画等を最後に確定された状態へ戻します。これが状態の巻き戻しです。次に最新の価格データで同じバーを再計算し、暫定出力を置き換えます。バー確定時の更新が終わると必要な値が時系列へ確定され、次バーから履歴参照で利用できます。
`var`はバーをまたぐ状態を保持しますが、未確定バー内の状態の巻き戻しを自動で回避するものではありません。`varip`はバー内更新の間で値を保持できますが、その途中更新は履歴データセットに残らないため、再読込後に同じ件数やロジックを再現できない可能性があります。便利さとバックテスト不能部分を同時に文書化します。
| 欄 | 各実行で保存する値 | 再読込後の照合 |
|---|---|---|
| バー識別情報 | ティッカーID・時間足・バー時刻・バー番号 | 同じ市場バーを指すか |
| バー状態 | barstate.isnew/isrealtime/isconfirmed/islast | 履歴化で何が変わったか |
| 実行時状態 | 更新番号・var・varip・条件値 | 確定値と途中値を分離できるか |
| 注文状態 | 注文ID・生成時刻・約定時刻・建玉 | マーカー移動の原因を説明できるか |
| 設定 | 三つの再計算・約定設定 | 同じ実行仕様か |
| 観察 | 採取時刻・バー確定前後・再読込実施時刻 | 比較確認点が一致するか |
一つの行を一回の実行として保存します。バー単位へ早く集約すると、同じバー内の途中条件と約定後再計算が消えます。
確定証拠にはバー確定時の更新直後のソースコードのハッシュ値、バー時刻、条件、建玉、注文ID、累積損益を一組で封印し、未確定バー途中の記録と同じ列へ上書きしません。翌日の再読込後は封印値を基準に差分を取り、varip由来の途中件数、約定後再計算、提供元の改訂を別の理由コードへ分類します。原因を特定できない差は「0」ではなく未解決として残し、成績の良いバーだけ一致したことにしません。
三つの設定を一括して有効にしない
`calc_on_every_tick`はリアルタイム更新ごとの実行、`calc_on_order_fills`は注文約定後の再計算、`process_orders_on_close`は確定ティック周辺の注文処理へ影響します。それぞれ目的が違い、組み合わせると一バー内の実行と注文順序が増えます。基準版では既定値を記録し、一つずつ変更します。
| 設定 | 変える事象 | 主な危険 | 監査方法 |
|---|---|---|---|
| calc_on_every_tick | リアルタイム価格更新 | 再読込後にティック途中の条件が消失 | 終値実行版と比較 |
| calc_on_order_fills | 模擬約定後 | 同一バーで追加注文 | 約定ログと実行回数 |
| process_orders_on_close | バー確定周辺 | 実ブローカーでの時刻との乖離 | 作成時刻/約定時刻を分離 |
正確な現行挙動は、宣言文とストラテジーに関する公式資料を確認してください。
注文約定は状態の巻き戻し対象の通常変数と同じ扱いではありません。ブローカーエミュレーターの注文イベントが一バー内に残り、追加実行を生む場合があります。TV12の約定経路と組にし、コードの計算と注文処理を別列にします。
組み合わせの失敗例は、ティックごとの実行で一時条件が成立して注文を作り、同じバーの約定後再計算で追加注文を作る検証例です。さらにバー確定時の注文処理を変えると、作成と約定が同じバーへ集まり、履歴上は整って見えることがあります。三設定を一つずつ有効化し、実行回数、注文ID、建玉変化が最初に増えた版を特定します。
バー内更新を数えつつ、注文条件は確定バーへ限定する
下のPine v6の例は`calc_on_every_tick = true`でリアルタイム更新ごとに実行し、`varip`で未確定バー内の更新数を数えます。一方、架空のEMA交差による注文は`barstate.isconfirmed`へ限定します。これは実行観察用で、20期間や交差を推奨せず、バー内更新回数を履歴バックテストへ利用しません。
//@version=6
strategy(
"Execution audit demo",
overlay = true,
calc_on_every_tick = true,
calc_on_order_fills = false,
process_orders_on_close = false
)
varip int intrabarUpdates = 0
if barstate.isnew
intrabarUpdates := 1
else
intrabarUpdates += 1
float baseline = ta.ema(close, 20)
bool confirmedLong = ta.crossover(close, baseline) and barstate.isconfirmed
bool confirmedExit = ta.crossunder(close, baseline) and barstate.isconfirmed
if confirmedLong
strategy.entry("L", strategy.long)
if confirmedExit
strategy.close("L")
plot(baseline, "EMA", color.orange)
plotchar(
barstate.isrealtime ? intrabarUpdates : na,
"Realtime update count",
"",
location.top
)ティック頻度はデータ配信と市場状況で変わり、取引出来高や時間の代理にはなりません。
まず`calc_on_every_tick = false`の基準版を保存し、次に`true`版を観察します。確定した注文が一致しても更新回数や暫定表示は一致しない可能性があります。逆に注文条件から`barstate.isconfirmed`を外せば、バー内交差が再読込後に消え、履歴成績とリアルタイムで観察した注文が大きく離れる場合があります。
比較は同じ市場の取引時間中に行います。A版は終値実行のみ、B版はティックごとの実行ですが、シグナル式、銘柄、期間、注文設定は固定します。B版の更新ログはリアルタイム観察証拠として別保存し、A版の履歴バーへ後から埋めません。バー確定直後と翌日再読込後の両方で注文IDを照合し、途中でだけ存在した条件を「履歴上も成立した」と書き換えないことが重要です。
バー単位の更新前/確定時/再読込後の差分を作る
| 確認点 | 保存する状態 | 主な分類 |
|---|---|---|
| 基準版 | ティックごとの実行・約定後再計算・終値処理 | 実行設定 |
| バー開始時の更新 | 時刻・条件・更新回数・注文ID | 変動中の価格/varip |
| バー確定時の更新 | 表示・建玉・注文・アラートの状態 | 確定/約定 |
| 再読込後 | 同じバーの値・マーカー・取引ID | 状態の巻き戻し/参照先データ/改訂 |
同じバーIDを横一列にし、観測できなかった状態を0ではなく欠落として残します。
不一致が出たバーだけを削除せず、全比較バーを同じ分母へ残します。特に利益取引だけマーカーが残り、損失側のバー内注文が消えるなら重大な選択バイアスです。TV05のアラート実行例は作成時記録も持つため、チャート再読込差とサーバー側アラートとの差を混同しません。
- 終値実行の基準版を凍結
ソースコードのハッシュ値、三設定、開始バー、取引時間帯を記録し、ストラテジーテスターを出力します。
- リアルタイム観測期間を事前登録
開始前に対象バー数と採取項目を決め、利益バーだけを選びません。
- 全実行を採取
更新、条件、注文、約定、建玉を時刻付きで一行ずつ保存します。
- バー確定時点を封印
バー確定時の更新直後の状態を保存し、後の再読込後の記録で上書きしません。
- 再読込差を分類
状態の巻き戻し、varip、参照先データ、約定、提供元の改訂、アラート記録へ分けます。
再現率を上げるために不一致行を削除してはいけません。リアルタイム観察ログとバックテストCSVは同じ版系列へ関連付けますが、事象粒度が違うため別表に保ちます。比較できない列は欠落とし、0や`false`へ置換しません。二回目のリアルタイム観察窓でも同じ分類手順を使い、原因分類が再現できない版は公開基準版へ昇格させません。
安定した基準版とリアルタイム観察を別版で分析する
終値実行の基準版のストラテジーテスターのCSV/XLSXを、バー内のリアルタイム観察ログとは別ファイルで保持します。基準版はバックテスト分析ラボへ読み込み、損益指標、ドローダウン、ストレステスト、未使用期間を実行設定別に照合します。再現可能な設定版が複数そろい、差分を保存して追跡したい時点が有料機能への自然な移行点です。
無料インジケーターで未確定バーと確定済みバーの違いを観察できますが、インジケーターはストラテジーテスターの取引出力ではありません。インジケーター挙動を理解した後、注文・約定・実行を持つストラテジーへ変える場合は新しい検証仕様を作ります。
再読込差とバー内実行を分けて数える
比較したバー、再読込後に変わったバー、観測したリアルタイム更新、約定後の追加再計算を入力し、再現性要確認を集計します。
再現率=max(A−B,0)÷A、不一致=B、バー内イベント数=C+D。更新と約定再計算は重複し得て、実行の完全な一意件数やストラテジー品質評価点ではありません。
よくある質問
calc_on_every_tickをONにすると履歴バックテストもティック単位になりますか?
なりません。履歴データはリアルタイムの完全なティック列を持たず、未確定バーで観測したバー内条件は再読込後に再現できない場合があります。
varとvaripの違いは何ですか?
`var`はバーをまたぐ初期化を制御しますが通常状態の巻き戻しを受けます。`varip`は未確定バー内の更新間で持続できますが、その状態は履歴バーで再現できない可能性があります。
barstate.isconfirmedなら全差分がなくなりますか?
なくなりません。チャートバーのバー内条件を抑える助けですが、上位時間足参照、約定、提供元の改訂、取引時間帯差等は別に監査します。
バックテストCSVとリアルタイム観察ログを一つに結合してよいですか?
そのまま結合しないでください。終値実行の履歴とリアルタイム更新ログは事象粒度が違います。同じ版IDで関連付けつつ、母集団と列定義を分けて比較します。
根拠資料と確認先
- TradingView Pine Script | Execution model履歴/リアルタイム実行、状態の巻き戻し、確定、再読込に関する公式資料
- TradingView Pine Script | Bar statesbarstate名前空間とストラテジー実行時の公式挙動
- TradingView Pine Script | Repainting履歴/リアルタイム差、varip、calc_on_every_tickの注意点
- TradingView Pine Script | Declaration statementscalc_on_every_tick、calc_on_order_fills、process_orders_on_closeの公式リファレンス
- TradingView | Strategy alert and chart-order mismatches再計算設定によるリアルタイム/履歴差の公式サポート資料
編集・発行: SG Group · 編集方針: TradingView公式ヘルプとPine Script公式文書を優先し、金融市場・商品に関する説明は取引所、監督当局、一次資料で補完しています。機能、データ、料金、接続条件は変わるため、実際の利用前に公式画面とリンク先の最新情報を確認してください。
重要事項: 本記事はTradingViewの画面、チャート、アラート、スクリーナー、ペーパートレード、Pine Script等の一般的な学習情報です。投資助言、売買シグナル、特定商品・データ提供者・ブローカーの推奨、将来価格や利益の保証ではありません。機能、料金、データ、取引所区分、通知、注文連携、Pine Scriptの仕様はプラン・地域・接続先・時点で異なり変更されることがあります。実際の資金を使う前に、TradingView公式資料、データ提供元、接続先事業者の最新条件を確認し、架空データまたはペーパートレードで手順を検証してください。

