完整流程
實盤覆盤
本頁內容5
回測報表看的是理論部位,實盤覆盤看的是你真的成交了什麼。TradeReview 用實際成交價、手續費、交易稅、除權息與入出金,重建每天的持股、現金與淨值,算出排除入出金影響的報酬率(時間加權報酬),並產生和回測同一套的 FinLab 報表。
做完這一頁,你會有:每天的持股與淨值、時間加權報酬、一份 FinLab 報表,以及實際部位和策略目標的差異表。
開始前你需要:
- 一個用
finlab.online連上的券商帳戶,設定方式見實盤下單。券商不在支援清單,或想用匯出的成交檔,看本頁最後一節「用自己的成交紀錄」。 - 決定從哪一天開始覆盤。券商 API 查不到那麼早的資料時,覆盤只能從查得到的那天開始。
從券商帳戶覆盤
連上券商帳戶
以永豐為例,其他台股券商的支援程度見下方的表:
from finlab.online.sinopac_account import SinopacAccount
acc = SinopacAccount()以嘉信為例:
from finlab.online.schwab_account import SchwabAccount
acc = SchwabAccount()建立覆盤
from finlab.portfolio import TradeReview
review = TradeReview.from_account(acc, start="2026-01-01")from_account 會依序做四件事:
- 依券商 API 抓
start到今天的成交(各券商的差異見下方的表)。 - 由券商目前庫存倒推起始日的庫存(扣回期間成交、除回配股與分割),最後再把重建出的期末庫存和券商庫存對帳,不一致的代號會寫進
review.limitations。 - 套用除權息。台股自動套用 FinLab 公告的除權息:現金股利在除息交易日入帳,配股與 ETF 分割在除權交易日(分割為恢復買賣日)調整股數。嘉信與幣安用券商紀錄裡的股利。
- 以未還原收盤價每日估值。
先看資料限制
review.limitations # 這次覆盤的資料限制,務必看過對帳不一致的代號、被略過的融券與借券成交,都會列在這裡。先看過,再相信後面的數字。
看績效與明細
review.summary() # 起訖淨值、外部淨投入、股利、費稅、損益、時間加權報酬
review.daily # 每日現金、持股市值、淨值、流入流出、報酬率、累計損益
review.holdings # 每日收盤持股股數
review.trades # FIFO 配對的每段實際交易(含股利),未出清的部位 exit_date 為空
review.report.display() # FinLab 報表:淨值曲線、績效指標、MAE/MFE、交易明細和策略目標比對
compare 用「目標日收盤時」的實際部位和目標比,不會用到之後的成交。目標可以是股數,也可以是權重:
import pandas as pd
target = pd.DataFrame({"2330": [2000], "2454": [1000]}, index=["2026-03-02"])
review.compare(target) # date, stock_id, target, actual, diff(股數)
weights = pd.DataFrame({"2330": [0.6], "2454": [0.4]}, index=["2026-03-02"])
review.compare(weights, kind="weight") # 也可以比權重import pandas as pd
target = pd.DataFrame({"AAPL": [20], "MSFT": [10]}, index=["2026-03-02"])
review.compare(target) # date, stock_id, target, actual, diff(股數)
weights = pd.DataFrame({"AAPL": [0.6], "MSFT": [0.4]}, index=["2026-03-02"])
review.compare(weights, kind="weight") # 也可以比權重報酬怎麼算:帳戶模式與持股模式
覆盤會依券商查得到哪些資料,選一種口徑算淨值:
| 口徑 | 什麼時候用 | 淨值 | 外部資金流 |
|---|---|---|---|
| 帳戶模式 | 券商 API 有完整入出金(嘉信、幣安),或你給了 initial_cash 與 cash_events | 現金+持股市值 | 入金、出金 |
| 持股模式 | 台股券商(交割戶是銀行帳戶,API 查不到入出金) | 持股市值 | 買進金額視為開盤前投入;賣出淨額與股利視為收盤後取出 |
日報酬 r = (當日淨值 + 當日流出) / (前日淨值 + 當日流入) - 1,串接成累積報酬。報表的年化報酬、夏普、回撤都以此計算,不受入出金影響。帳戶模式下 pnl 是「淨值變化減去外部淨投入」。
台股券商查不到入出金,所以預設只覆盤持股。要算含現金的帳戶淨值,自己給起始現金與入出金:
import pandas as pd
review = TradeReview.from_account(
acc,
start="2026-01-01",
initial_cash=500_000,
cash_events=pd.DataFrame(
{
"time": ["2026-03-02"],
"amount": [100_000],
"type": ["deposit"],
}
),
)各券商支援程度
| 券商 | 成交來源 | 手續費/交易稅 | 已平倉部位 | 股利 | 入出金 | 預設口徑 |
|---|---|---|---|---|---|---|
| 永豐 | 已實現損益+明細、未實現部位明細 | 買進取自明細;賣出由已實現損益反推(合併記在 fee) | 可還原買進腿 | FinLab 自動 | 無 | 持股模式 |
| 口袋 | 已實現損益、未實現部位明細 | 無 | SDK 有明細查詢時同永豐;沒有時期間內賣出的股票視為起始日已持有 | FinLab 自動 | 無 | 持股模式 |
| 富邦 | filled_history(每次 30 天,需 fubon_neo 2.1.1 以上) | API 無逐筆費稅,依 fee_ratio 與法定稅率估算 | 可 | FinLab 自動 | 無 | 持股模式 |
| 台新(原元富) | 對帳單 account_statment | 逐筆實際值 | 可 | FinLab 自動 | 無 | 持股模式 |
| 玉山(富果) | get_transactions_by_date(每次 180 天) | 逐筆實際值 | 可 | FinLab 自動 | 無 | 持股模式 |
| 嘉信 | 交易紀錄 get_transactions | 淨額與成交金額的差 | 可 | 券商紀錄 | 券商紀錄 | 帳戶模式 |
| 幣安 | myTrades(逐幣別) | 以報價幣或該幣支付的手續費;以 BNB 支付的未計入 | 只查目前持有與 symbols= 指定的幣別 | 報價幣配發 | 報價幣入出金 | 帳戶模式 |
所有券商共同的限制:
- 只覆盤現股與融資的多單;融券、借券成交會略過並列在
limitations。融資利息不計。 - 台股成交大多只有日期;同一天先處理買進再處理賣出,每日收盤估值不受影響。
- 減資、面額變更沒有完整的每股退還現金與換股比例資料,不自動處理;遇到時把事件放進
corporate_actions(欄位stock_id, date, cash, ratio)。配股以「元/股 ÷ 面額」換算,零股以無條件捨去計算。 - 券商 API 查不到時間範圍外的資料時,覆盤只能從查得到的那天開始。
用自己的成交紀錄
券商不在上表,或要用匯出的成交檔時,把檔案整理成標準欄位,直接建立 TradeReview。quantity 是股數,fee、tax 是該筆實際金額,沒有這兩欄時以 0 計。
台股可以用 tw_corporate_actions(stock_ids, start, end),從 FinLab 公告的除權息產生 corporate_actions 表:
import pandas as pd
from finlab.markets.tw import TWMarket
from finlab.portfolio import TradeReview
from finlab.portfolio.trade_review import tw_corporate_actions
fills = pd.DataFrame(
{
"time": ["2026-01-05 09:01", "2026-01-07 10:00"],
"stock_id": ["1101", "1101"],
"action": ["buy", "sell"],
"quantity": [5000, 5000], # 股數,不是張數
"price": [35.2, 36.0],
"fee": [250, 256], # 該筆實際金額
"tax": [0, 540],
}
)
market = TWMarket()
review = TradeReview(
fills,
market.get_price("close", adj=False),
start="2026-01-05",
initial_holdings={"2330": 1000},
corporate_actions=tw_corporate_actions(
["1101", "2330"], "2026-01-05", "2026-12-31"
),
market=market,
)美股的股利與分割自己寫進 corporate_actions:cash 是除息日每股配發的現金,ratio 是股數倍數(2.0 代表一股拆成兩股)。
import pandas as pd
from finlab.markets.us import USMarket
from finlab.portfolio import TradeReview
fills = pd.DataFrame(
{
"time": ["2026-01-05 09:45", "2026-01-07 10:00"],
"stock_id": ["MSFT", "MSFT"],
"action": ["buy", "sell"],
"quantity": [50, 50], # 股數
"price": [480.0, 486.5],
"fee": [0, 0], # 該筆實際金額;沒有 fee、tax 欄位時以 0 計
}
)
market = USMarket()
review = TradeReview(
fills,
market.get_price("close", adj=False),
start="2026-01-05",
initial_holdings={"AAPL": 100},
# 示意用的股利:除息日每股現金;ratio 2.0 代表一股拆成兩股
corporate_actions=pd.DataFrame(
{"stock_id": ["AAPL"], "date": ["2026-02-09"], "cash": [0.25], "ratio": [1.0]}
),
market=market,
)建好之後,review 的用法和從券商帳戶建立的完全一樣。
下一步
- 實盤下單 設定券商帳戶,從回測結果算出部位並下單。
- 從研究到實盤 從策略構想、回測、驗證到上線的完整流程。
- 多策略組合 把多個策略合成一個帳戶來管理與下單。
- finlab.portfolio API
TradeReview與組合相關類別的完整參數。
這一頁有幫到你嗎?