進階課程 · Lesson 5
第一版的任務是確認研究管線,不是追求高 Sharpe。建議用少量規則:
商品:單一流動性資產
頻率:日線
訊號:收盤高於 20 日 SMA
決策:日 t 收盤後
成交:日 t+1 開盤(簡化範例若無 open,使用 position shift)
出場:訊號反轉
部位:0% 或 100%,不加槓桿
成本:每次 position change 扣固定 bps
先驗證對齊,再加入 stop、分批、short、volatility sizing。
若 signal_t 使用 close_t,則不能乘上同一期由 close_(t-1) 到 close_t 的報酬。最小寫法:
signal = close > close.rolling(20).mean()
position = signal.shift(1).fillna(False).astype(float)
asset_return = close.pct_change().fillna(0.0)
gross_return = position * asset_return
這仍是一個 close-to-close approximation(近似)。若規格要求 next-open execution,就必須有 open data 並分開 overnight 與 intraday return。
turnover = position.diff().abs().fillna(position.abs())
net_return = gross_return - turnover * cost_rate
從 0 到 1 是一次買進;1 到 0 是一次賣出;從 -1 到 1 則是 2 單位 turnover。cost_rate 必須說清楚是單邊還是 round-trip。
至少建立:
如果策略只在多頭市場工作,可能只是降低或增加 beta。可進一步估計 market exposure、up/down capture 與 regime performance。
不要只輸出 summary。至少保存:
timestamp, raw_signal, position, entry/exit flag,
fill price, quantity, fee, slippage, gross pnl, net pnl,
equity, drawdown, parameter version, data version
任何一筆異常績效都應能追到原始 bar 與計算步驟。
執行 python .\code\simple_backtest.py。範例用合成資料,不下載市場資料,因此結果可重現。請依序修改:
window=20 改為 10;cost_bps=5 改為 50;shift(1),觀察不當時間對齊如何改變結果。第三步只用來理解 bias,不得保留為正式版本。
你應能從任一 equity 點反查:當日使用哪個訊號、前一日持有什麼部位、扣了多少成本,以及為何該報酬屬於策略。