多出來的是最後一筆:資料結束時仍未平倉的部位,TradingView 會以最後一根 K 線的收盤價,把它記成一筆已平倉交易。本文說明這一列是什麼、為什麼會牽動你的統計數字,以及 PineForge 怎麼記錄它。
同一支策略,TradingView 上的交易就是比你的回測工具多一筆。多出來的是清單裡的最後一筆:它的出場訊號寫著 Open,或乾脆空白,出場價就只是最後一根 K 線的收盤價。
兩個工具都沒壞。這一列是 TradingView 回報「資料結束時仍未平倉的部位」的方式;回測工具如果漏掉它,交易筆數、淨利,以及所有以這兩者為基礎的統計數字,都會和 TradingView 對不上。
TradingView 記下了什麼
回測在最後一根 K 線就停了,但那裡並沒有任何機制會讓策略平倉、回到空手。TradingView 的報告不會丟掉這個未平倉部位,而是把它記成一筆已平倉交易:出場在區間的最後一根 K 線,出場價就是那根 K 線的收盤價,並且和其他交易一樣計入統計。PineForge 模擬了這條規則,引擎標頭檔裡有說明。
開放語料庫裡就有一個例子。stats-eventrades-zero-pnl-count-01 會在 UTC 午夜那根 K 線買進一單位,以下一根 K 線的開盤價成交,再用一張掛在進場價的限價單賣出。它的最後一筆多單,價格再也沒有回到那個價位。以下是 TradingView 的交易清單(時間採用 Asia/Taipei 時區,所以 08:00 就是 UTC 午夜):
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,...
看出場那一列:沒有訊號,價格就是最後一根 K 線的收盤價。這支策略其實從來沒有賣出。這筆 −2,525.12 是一個抱了八個月的部位的帳面虧損,卻好像已經實現了一樣,躺在交易清單裡,也算進了淨利。
這一列有兩種寫法。TradingView 自己匯出的交易清單 CSV,會在 Signal 欄寫上 Open(這支策略較早的匯出檔就是這樣);TradingView 的深度回測報告則把這一欄留白,語料庫現在多數檔案也一樣,就像上面那樣(評分程式)。
區區一列,為什麼重要
對交易頻率低的策略,或是很短的區間來說,這個未平倉部位可能就占了結果的大半。在日線圖上,它常常是區間內唯一的一筆交易:PineForge 開始記錄這一列之前,這類策略在 PineForge 上一筆交易都沒有,TradingView 卻有一筆。所有從交易清單算出來的數字都會跟著變:交易筆數、勝率、淨利、平均每筆交易。
PineForge 怎麼記
引擎以前只匯出已平倉的交易。現在它會記下 TradingView 記下的那一列:最後一根 K 線之後仍未平倉的部位,每一筆各記一列,日期是那根 K 線,價格是它的收盤價(依 tick 取整),計入手續費但不計滑價,因為這一列「是一筆估值,不是一張訂單」(引擎指南)。這支策略在引擎這邊的交易清單,會在最後一欄標出這一列:
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
K 線、價格、虧損都和 TradingView 相同,再以 open 表明它只是估值。腳本本身永遠看不到這一列:在回測執行過程中,部位仍然未平倉,所以 Pine 的 strategy.closedtrades 不會把它算進去;引擎文件也說明,想和這個變數的值一致,就要把這一列濾掉(Pine 與原生 API 對照表)。
資料停在哪裡,價格就定在哪裡
這筆估值記在回測工具的最後一根 K 線上,所以那根 K 線必須就是 TradingView 的最後一根。TradingView 的區間,終點是開盤時間不晚於結束日 UTC 午夜的最後一根 K 線(執行腳本)。語料庫的價格檔則還往後多了一段,一直到 5 月 4 日。如果把整個檔案餵給引擎,它會把第 140 筆交易記在那天的最後一根 K 線上,價格 2,365.09,比 TradingView 的 2,261.44 高出約 4.6%(同一個檔案)。所以執行腳本會在回測開始前,先把資料截在 TradingView 的最後一根 K 線。
接著,引擎的評分程式會像對待其他交易一樣,把這兩列配成一對,也照樣評它們的出場價和 P&L。只有當 TradingView 把這一列寫成 Open 時,評分程式才會把這一對當成「估值對估值」:照樣配對、照樣計數,進場也照樣檢查,但出場價和 P&L 不列入評分,兩邊 P&L 的吻合程度則另外回報,精確到分(評分程式)。
29 支策略,多了一筆交易
我們用目前的引擎重新產生語料庫的交易清單時,312 支策略中有 29 支的交易筆數變了。其中 26 支新增的交易裡,有一筆就是這一列。另外三支多出一筆已平倉交易,則是因為 TradingView 那邊的清單已更新到當天結束。
stats-eventrades-zero-pnl-count-01 的舊清單,當初照樣拿到評分程式的最高等級。評分程式會修剪兩份清單共同涵蓋區間兩端的交易,這樣開頭或結尾多出一筆,才不會讓整支策略不及格。但在這裡,修剪反而藏住了少掉的那一筆:舊報告兩邊各評了 139 筆,TradingView 的清單卻有 140 筆;新報告則是 140 筆對 140 筆。
語料庫的 312 支策略中,有 131 支的 PineForge 交易清單是以一個仍未平倉的部位作結,超過四成(語料庫 README)。
這對你代表什麼
- 如果 TradingView 比你的回測工具多一筆交易,而且多的是最後一筆,先找找看結尾是不是有仍未平倉的部位。這是 TradingView 的正常行為。
- TradingView 的淨利和勝率,都把這個部位以最後收盤價算了進去。如果只想看已實現的結果,最後一筆交易的出場訊號若是
Open或空白,就把它拿掉;在 PineForge 的清單裡,就是標了open的那一筆。 - 比較兩份回測之前,先讓兩邊停在同一根 K 線:也就是開盤時間不晚於 TradingView 結束日 UTC 午夜的最後一根。
2026-10-02 以當天發行的 PineForge 引擎與 codegen 1.0.1 實測。
下一步
- 讀懂 engine_trades.csv 格式:上面引用的這個檔案逐欄說明,外加一個 pandas 載入器。
- 瀏覽畫廊:每支語料庫策略的交易清單,都和 TradingView 的並排呈現。
- 我們如何衡量對齊:目前的結果與資料來源。