想數均線交叉幾次?用 backtrader 餵證交所日資料,一秒列出日期
📌 數據僅限本工具現階段參考用。本文只示範工具怎麼安裝、設定、執行,不是投資建議,也不推薦任何股票。
重點摘要
- pip install -e . 約 15 秒裝好 backtrader;要畫圖還得另外 pip install -r requirements.txt(約 14 秒)。
- 餵入證交所 2330 日資料 83 列(2026-07-01 至 2026-11-02),跑 5 日線/20 日線交叉約 1 秒,列出 4 個交叉日,交易次數 2、最大回落 1.88%。
- 直接畫圖依序遇到缺 plotly、缺 dash、TKAgg 需要視窗三個錯誤;補裝 requirements、改用 Agg 並以 figs[0][0].savefig 才存出圖。
- c.plot 的 savefig=True 參數在本次實測沒有產生圖檔。
- 結論: 算均線交叉與列日期很快,畫圖要先備好相依套件與無視窗環境設定。
- 適合: 想用 Python 在台股日資料上自己驗證均線交叉、願意照步驟設定環境的人
- 不適合: 不想碰命令列、需要多檔同時回測或即時資料的人(本次未測)
| 實測項目 | 結果 |
|---|---|
| 資料列數 | 83 |
| 安裝時間 | 約15秒(畫圖相依另約14秒) |
| 交叉日數 | 4 |
| 交易次數 | 2 |
| 最大回落 | 1.88% |
| 回測耗時 | 約1秒 |
| 畫圖錯誤 | 3 個(plotly、dash、TKAgg) |
想驗證一句老話:「五日線穿過二十日線」在最近幾個月到底發生過幾次?用試算表拉公式,拉到一半日期就對不上。這篇用 Python 回測框架 backtrader,餵入證交所公開的日資料,讓它把交叉日一次列出來,也順便畫圖。
測試設備:Mac mini M4 Pro(12 核、64GB)。受測版本:cloudQuant/backtrader(GPL-3.0)master,版本 1.9.76.123,Python 3.12。本文示範資料是證交所公開資料,代號 2330 只是示範輸入,資料日期到 2026-11-02。
下載
git clone https://github.com/cloudQuant/backtrader
cd backtrader
pip install -e . # 實測約 15 秒
pip install -r requirements.txt # 畫圖需要,約 14 秒
pip install requests
重點:只做 pip install -e . 不會裝到畫圖用的 plotly、dash,下面的常見問題會說明。
設定
資料來源是證交所的個股日成交資訊(STOCK_DAY),一次一個月。下面的腳本抓 2026 年 7 月到 11 月,存成 2330.csv(日期、開高低收、成交量),共 83 列,從 2026-07-01 到 2026-11-02。
import requests, csv, time
rows=[]
for ym in ['20260701','20260801','20260901','20261001','20261101']:
j=requests.get('https://www.twse.com.tw/exchangeReport/STOCK_DAY',
params={'response':'json','date':ym,'stockNo':'2330'},timeout=30).json()
for r in j.get('data',[]):
y,m,d=r[0].split('/'); n=lambda s: float(s.replace(',',''))
rows.append((f'{int(y)+1911}-{m}-{d}',n(r[3]),n(r[4]),n(r[5]),n(r[6]),int(n(r[1]))))
time.sleep(3) # 請求間隔,避免被擋
with open('2330.csv','w',newline='') as f:
w=csv.writer(f); w.writerow(['date','open','high','low','close','volume']); w.writerows(rows)
跑起來
import matplotlib
matplotlib.use('Agg')
matplotlib.use=lambda *a,**k:None # backtrader 會強制改成 TKAgg,這行擋掉
import backtrader as bt
class Cross(bt.Strategy):
def __init__(self):
self.cx=bt.indicators.CrossOver(bt.indicators.SMA(self.data.close,period=5),
bt.indicators.SMA(self.data.close,period=20))
def next(self):
d=self.data.datetime.date(0)
if self.cx>0: print(d,'5日線向上穿過20日線'); self.buy()
elif self.cx<0 and self.position: print(d,'5日線向下穿過20日線'); self.close()
c=bt.Cerebro()
c.adddata(bt.feeds.GenericCSVData(dataname='2330.csv',dtformat='%Y-%m-%d',datetime=0,open=1,high=2,low=3,close=4,volume=5,openinterest=-1,headers=True))
c.addstrategy(Cross)
c.addanalyzer(bt.analyzers.TradeAnalyzer,_name='t')
c.addanalyzer(bt.analyzers.DrawDown,_name='dd')
r=c.run()[0]
print('交易次數',r.analyzers.t.get_analysis().total.closed,'最大回落%',round(r.analyzers.dd.get_analysis().max.drawdown,2))
figs=c.plot(style='line',iplot=False,backend='matplotlib')
figs[0][0].set_size_inches(10,6); figs[0][0].savefig('bt2330.png',dpi=110)
實測輸出(跑完約 1 秒):

| 項目 | 結果 |
|---|---|
| 資料列數 | 83(2026-07-01 至 2026-11-02) |
| 交叉日 | 08-06 向上、09-16 向下、09-21 向上、10-16 向下 |
| 交易次數 | 2 |
| 最大回落 | 1.88% |
圖檔長這樣(收盤線、5 日與 20 日均線、成交量、下方是交叉指標):

以上是工具現階段算出的欄位與日期,只示範用法,不解讀好壞。
常見問題
ModuleNotFoundError: No module named 'plotly':只裝pip install -e .就畫圖會遇到。改裝pip install -r requirements.txt。- 補裝後又出現
No module named 'dash':同一份 requirements.txt 會一起裝。 ImportError: Cannot load backend 'TKAgg' which requires the 'tk' interactive framework:沒有視窗的環境(伺服器、容器)會遇到,backtrader 載入畫圖模組時會強制指定 TKAgg。上面腳本用matplotlib.use('Agg')加覆寫matplotlib.use,並在c.plot指定backend='matplotlib'。c.plot(savefig=True, figfilename=...)沒產生檔案:我實測這樣沒存出圖,改用figs[0][0].savefig(...)才成功。- 這次沒測:多檔同時回測、參數掃描、其他資料來源與即時資料。
專案連結:https://github.com/cloudQuant/backtrader 授權:GPL-3.0