本文へスキップ

TradingView のトレードが、バックテスターより 1 件多い理由

読了 約5分

多い 1 件は一覧の最後のトレードです。データが尽きた時点でまだ保有中だったポジションを、TradingView は最終バーの終値で決済したトレードとして計上します。この行の正体、統計が変わる理由、PineForge での計上のしかたを解説します。

同じ戦略なのに、TradingView に表示されるトレードが、手元のバックテスターより 1 件多いことがあります。多いのは一覧の最後のトレードです。エグジットのシグナルは Open か空欄で、エグジット価格は最終バーの終値そのままです。

どちらのツールも壊れてはいません。この行は、データが尽きた時点でまだ保有中のポジションを TradingView が報告するときの形です。この行を含めないバックテスターは、トレード数でも純利益でも、それらをもとにしたあらゆる統計でも、TradingView と食い違うことになります。

TradingView の計上のしかた

バックテストは最後のバーで止まりますが、そこで戦略のポジションをフラットにするものは何もありません。TradingView のレポートは、保有中のポジションを切り捨てません。期間の最後のバーにそのバーの終値でエグジットした、決済済みのトレードとして計上し、ほかのトレードと同じように数えます。PineForge はこのルールを再現しており、エンジンのヘッダーにその説明があります。

公開コーパスから一例を挙げます。stats-eventrades-zero-pnl-count-01 は、UTC 0 時のバーで 1 単位を買い(約定は次のバーの始値)、そのエントリー価格に置いた指値で売る戦略です。最後のロングは、その価格まで戻りませんでした。TradingView のトレード一覧は次のとおりです(時刻は Asia/Taipei のタイムゾーン表記なので、08:00 が UTC 0 時にあたります)。

Trade number,Type,Date and time,Signal,Price USDT,...,Net PnL USDT,...
140,Exit long,2026-05-01 08:00,,2261.44,...,-2525.12,...
140,Entry long,2025-08-25 08:15,even-trade entry,4786.56,...,-2525.12,...

エグジット行を見てください。シグナルはなく、価格は最終バーの終値そのものです。この戦略は売っていません。−2,525.12 は 8 か月保有したポジションの含み損にすぎないのに、実現した損失のような顔をしてトレード一覧にも純利益にも入っています。

この行の表記は 2 通りあります。TradingView 自身がトレード一覧を CSV にエクスポートすると、Signal 列に Open と書かれます(この戦略の以前のエクスポートがそうでした)。TradingView のディープバックテストのレポートでは Signal 列が空欄で、いまのコーパスのファイルでも大半は上のように空欄になっています(グレーダー)。

たった 1 行が効いてくる理由

トレード頻度の低い戦略や短い期間では、保有中のポジションが結果の大半を占めることもあります。日足チャートでは、それが期間内の唯一のトレードであることも珍しくありません。PineForge がこの行を計上していなかった頃は、こうした戦略についてトレードは 1 件もないと報告していました。TradingView は 1 件と報告していたにもかかわらずです。トレード数、勝率、純利益、1 トレードあたりの平均損益と、トレード一覧から計算する数字はすべて、この行と一緒に動きます。

PineForge の計上のしかた

エンジンは以前、決済済みのトレードしかエクスポートしていませんでした。いまは、TradingView が計上するのと同じ行を計上します。最後のバーを過ぎても保有中のロット 1 つにつき 1 行で、日時はそのバー、価格はそのバーの終値をティック単位に丸めたものです。手数料はかかりますが、スリッページはかかりません。この行は「注文ではなく、値洗い」だからです(エンジンガイド)。この戦略のエンジン側のトレード一覧では、最後の列でこの行に印を付けています。

Trade #,Type,Date and time,Price,Qty,Net PnL,...,Engine range-end
140,Exit long,2026-05-01 00:00,2261.440000,1,-2525.120000,...,open

バーも価格も損失も TradingView と同じで、open がこれは値洗いだと示しています。スクリプト自身がこの行を目にすることはありません。実行中はポジションがまだ保有中なので、Pine の strategy.closedtrades はこれを数えません。この変数と一致させたいときはこの行を除外するよう、エンジンのドキュメントに書かれています(Pine とネイティブの対応表)。

価格を決めるのは、データの終わる位置

値洗いはバックテスターの最後のバーで計上されるので、そのバーは TradingView の最後のバーと一致していなければなりません。TradingView の期間は、終了日の UTC 0 時ちょうど、またはそれより前に始まる最後のバーで終わります(ハーネス)。コーパスの価格ファイルはその先、5 月 4 日まで続いています。ファイルをまるごと渡すと、エンジンはトレード 140 をその日の最後のバーで 2,365.09 として計上してしまいます。TradingView の 2,261.44 より約 4.6% 高い値です(同じファイル)。そこでハーネスは、実行前にデータを TradingView の最後のバーで切っています。

エンジンのグレーダーは、この 2 行もほかのトレードと同じようにペアにし、エグジット価格と P&L もほかのトレードと同じように評価します。TradingView 側の行が Open と書かれているときに限り、このペアを値洗い同士として扱います。ペアとして照合してトレード数に数え、エントリーはチェックしますが、エグジットと P&L は評価から外し、P&L の一致はセント単位で報告します(グレーダー)。

29 本の戦略で、トレードが 1 件増えた

コーパスのトレード一覧を現行のエンジンで生成し直したところ、312 本中 29 本の戦略でトレード数が変わりました。そのうち 26 本では、新たに加わったトレードの 1 件がこの行です。残る 3 本で決済済みのトレードが 1 件増えたのは、TradingView 側の一覧がその日の終わりまでのトレードを含むように更新されていたためです。

stats-eventrades-zero-pnl-count-01 の古い一覧も、グレーダーの最上位の評価を受けていました。グレーダーは、両方の一覧がカバーする期間の両端でトレードを切り落とします。始まりや終わりに 1 件余分なトレードがあるだけで戦略が不合格にならないようにするためです。今回は、この切り落としが欠けていた 1 件を隠していました。古いレポートは、TradingView の一覧には 140 件あったのに、両側 139 件ずつで評価していました。新しいレポートでは 140 件対 140 件で評価しています。

コーパスの 312 本のうち 131 本、つまり 4 割強の戦略で、PineForge のトレード一覧は保有中のポジションで終わっています(コーパスの README)。

押さえておきたいこと

  • TradingView のほうがバックテスターよりトレードが 1 件多く、その 1 件が最後のトレードなら、終わりの時点で保有中のポジションがないか確認してください。これは TradingView の通常の挙動です。
  • TradingView の純利益と勝率には、このポジションが最後の終値で含まれています。実現した結果だけを見たいなら、エグジットのシグナルが Open か空欄の最後のトレードを外してください。PineForge の一覧では、open と印の付いた行がそれにあたります。
  • 2 つのバックテストを比べる前に、両方を同じバーで止めてください。TradingView の終了日の UTC 0 時までに始まる最後のバーです。

2026-10-02 に、同日リリースの PineForge エンジンと codegen 1.0.1 で計測しました。

次に読むなら