跳至主要內容
台股研究 約 10 分鐘閱讀

yfinance 教學:用 Python 免費下載全球指數與股價,
8 大指數與還原股價實測

yfinance 教學完整指南:教你用 Python 免費下載台股、美股與全球指數的歷史股價。本文實測八大指數的可回溯年份,標普五百最遠可回溯至 1927 年;台積電還原股價 16 年漲 55.6 倍、原始股價只漲 33.7 倍。從安裝、代號規則、還原股價原理到限流陷阱,附完整程式碼與資料下載。

8 大指數 yfinance 全實測

pip install yfinance 加上十行 Python,就能免費下載台股、美股與全球指數的完整歷史股價。這件事從 2020 年到現在都成立,但工具細節已經換了好幾輪:舊版教學的網址會回 301、不帶 User-Agent 的爬蟲會被 429 擋下、auto_adjust 的預設值也變了。本文用 2026 年 6 月的 yfinance 1.4 把整條流程重新實測一遍:8 大指數最遠可回溯到 1927 年,台積電用原始收盤價計算會少算超過三分之一的報酬。每個數字都附可下載的程式碼與 CSV,你可以自己重跑驗證。

yfinance 教學實測:全球 8 大指數 2000 年至今累積走勢,那斯達克漲 5.1 倍居冠

8 大指數實測結果速覽

下表是用 yfinance 下載 8 大指數後算出的描述統計。窗口統一為 2000 年 1 月到 2026 年 6 月 10 日,純價格指數算術(期間報酬連乘),不含股息與任何交易成本:

指數 代號 可回溯起點 總報酬 年化報酬 年化波動 最大回撤
那斯達克綜合(美) ^IXIC 1971-02-05 +509.3% 7.08% 24.8% -77.9%
標普 500(美) ^GSPC 1927-12-30 +399.4% 6.27% 19.3% -56.8%
台灣加權 ^TWII 1997-07-02 +393.6% 6.23% 21.0% -66.2%
道瓊工業(美) ^DJI 1992-01-02 +339.5% 5.76% 18.3% -53.8%
DAX(德) ^GDAXI 1987-12-30 +258.4% 4.95% 22.4% -72.7%
日經 225(日) ^N225 1965-01-05 +237.7% 4.71% 23.3% -66.1%
富時 100(英) ^FTSE 1984-01-03 +53.8% 1.64% 17.9% -51.6%
恒生(港) ^HSI 1986-12-31 +40.5% 1.30% 23.5% -65.2%

資料截至 2026-06-10。三個觀察:台灣加權指數即使不含息(後面會解釋這個但書),年化 6.23% 也與標普 500 的 6.27% 幾乎並列;那斯達克報酬第一,代價是 -77.9% 的最大回撤與最高的波動;恒生與富時 100 在這 26 年只累積了不到 55% 的漲幅。

yfinance 是什麼?為什麼量化新手都從它開始

yfinance 是一個開源 Python 套件(GitHub 專案頁),它把 Yahoo Finance 的公開資料包裝成 pandas DataFrame:你給它一個代號,它還你一張開高低收的表格。對想入門量化交易程式交易的人來說,它解決的是第一個門檻:在寫任何策略之前,你得先有資料。

它的三個優點:免費、涵蓋全球市場(台股、美股、港股、指數、外匯、加密貨幣)、兩行程式就能上手。它的限制同樣明確:資料來自 Yahoo 的網頁介面而非官方 API,沒有服務品質保證,台股的除權息還原與下市股票也有缺口。這些限制對「分析全球指數」幾乎無感,對「台股個股回測」則是致命傷,本文最後一節會給出對應的解法。

環境準備:pip 安裝與 Google Colab 起手式

如果你不想在電腦安裝任何東西,打開 Google Colab 新增一個筆記本即可。Colab 上執行終端機指令要在前面加驚嘆號:

顯示程式碼
!pip install yfinance

在自己電腦的終端機(cmd、Terminal)則不需要驚嘆號,輸入 pip install yfinance 即可。安裝完成後,把套件載入並取個短名字:

顯示程式碼
import yfinance as yf

用 yfinance 爬全球股票股價:從一檔台積電開始

先從最簡單的單檔下載開始。抓台積電上市以來的全部日線:

顯示程式碼
df = yf.Ticker("2330.TW").history(period="max")
df

period="max" 代表拿取該檔股票在 Yahoo Finance 上的全部歷史。實測台積電可以回溯到 2000 年 1 月 4 日,原始收盤價從 69.65 元一路走到 2026 年 6 月的 2,255 元,共 6,572 個交易日。

股票代號命名規則:台股加 .TW、上櫃加 .TWO

只要在 Yahoo Finance 搜尋得到的代號,yfinance 都抓得到。命名規則整理如下:

市場 代號寫法 範例
台股上市 數字代號 + .TW 2330.TW 台積電、2317.TW 鴻海
台股上櫃 數字代號 + .TWO 5483.TWO 中美晶
美股 英文代號 AAPL 蘋果、TSLA 特斯拉、MSFT 微軟
全球指數 ^ 開頭 ^TWII 台灣加權、^GSPC 標普 500
港股 4 位數字 + .HK 0700.HK 騰訊
加密貨幣 幣別-計價幣 BTC-USD 比特幣

一個常見的新手錯誤是把上櫃股票寫成 .TW 結尾,抓回來會是空表格;上櫃要用 .TWO

回傳的 DataFrame 欄位怎麼讀

history() 回傳的是 pandas DataFrame,你可以把它想像成一張可程式化操作的 Excel 表。欄位包含 Open、High、Low、Close(開高低收)、Volume(成交量)、Dividends(每股配息)與 Stock Splits(股票分割)。有兩個新版行為值得知道:索引是帶時區的 DatetimeIndex(台股是 Asia/Taipei),跨市場合併資料前建議先用 tz_localize(None) 拿掉時區;另外 history()auto_adjust 參數預設是 True,也就是你拿到的 Close 已經是還原股價。這個預設值是好事,但你得知道它在做什麼。

還原股價:auto_adjust 在做什麼

股票除權息那天,股價會跳空下跌,但持有人沒有虧損,因為現金股利進了你的口袋。如果用原始收盤價計算報酬,每次配息都會被誤認為下跌。還原股價(adjusted close)的作法是把歷史價格按比例往下調整,讓除權息前後的報酬可以直接相連。數學定義是:

Ptadj=Pt×s>t(1DsPs)P^{adj}_t = P_t \times \prod_{s>t}\left(1-\frac{D_s}{P_{s^-}}\right)

其中 PtP_ttt 日原始收盤價,DsD_sss 日每股配息,PsP_{s^-} 是除息前一日收盤價:在 tt 日之後每發生一次配息,tt 日以前的歷史價格就乘上一個小於 1 的調整因子。

用一個簡化示例說明(示意數字,非真實個股):某公司股價 100 元,配發 5 元現金股利,除息日參考價變成 95 元。若隔天收在 96 元,原始價格序列顯示 100 到 96,看起來跌了 4%;還原價格會把除息前的 100 元調整為 100×(15/100)=95100\times(1-5/100)=95 元,序列變成 95 到 96,正確反映出含息報酬 +1.05%。

差距有多大?用台積電實測,2010 年初到 2026 年 6 月:

台積電 2330.TW 原始收盤價與 auto_adjust 還原收盤價對照,還原後漲 55.6 倍

原始收盤價漲 33.7 倍,還原收盤價漲 55.6 倍,對應年化報酬分別是 24.10% 與 27.85%。差距來自這段期間的 37 次配息、累計每股 136 元。如果你拿原始價格做 16 年的回測,光台積電一檔就會少算超過三分之一的累積報酬。指數沒有配息問題(價格指數本身就不含股息),但個股一定要用還原價。

把下載打包成 crawl_price() 函式

要抓很多檔標的時,不需要每檔都複製貼上一段程式。用 def 把下載動作包成函式:

顯示程式碼
import yfinance as yf
 
def crawl_price(stock_id):
    df = yf.Ticker(stock_id).history(period="max")
    return df

第一行 def crawl_price(stock_id): 宣告一個可呼叫的程式區塊,內縮的程式碼屬於這個函式。stock_id 是參數:傳入不同代號,就能抓不同標的。例如抓鴻海並畫出收盤價走勢:

顯示程式碼
df = crawl_price("2317.TW")
df["Close"].plot()

之後抓美股、指數都是同一行的事:crawl_price("AAPL")crawl_price("^GSPC")

全球指數清單還能爬嗎?2026 年實測 Yahoo 頁面

2020 年的舊教學會教你用 requestspd.read_html 爬 Yahoo 的全球指數清單頁。這條路線在 2026 年 6 月實測的結果是:

測試情境 結果
舊網址 finance.yahoo.com/world-indices/ 回 301,轉址到 /markets/world-indices/
新網址、不帶 User-Agent 回 429(Too Many Requests),拿不到內容
新網址、帶瀏覽器 User-Agent 回 200,解析出 1 張表、42 個指數

也就是說流程還活著,但要改兩個地方:網址換新、請求要帶 User-Agent。可運作的版本如下:

顯示程式碼
import io
 
import pandas as pd
import requests
 
url = "https://finance.yahoo.com/markets/world-indices/"
headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
                  "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36"
}
 
response = requests.get(url, headers=headers)
tables = pd.read_html(io.StringIO(response.text))
world_index = tables[0]

requests.get 取回網頁原始碼,io.StringIO 把文字包裝成檔案物件,pd.read_html 解析網頁中的表格成 a list of DataFrame,第一張就是含 Symbol 與 Name 的指數清單。實測抓到 42 列,開頭依序是 ^GSPC^DJI^IXIC

要提醒的是:這種網頁爬蟲對頁面改版很脆弱,Yahoo 任何一次改版都可能讓 read_html 解析失敗。如果你的目標是固定追蹤幾個主要指數,維護一份靜態代號清單(如下一節的寫法)比每次重爬更穩定。想練習更多爬蟲技巧,可以參考台股每日爬蟲教學三大法人爬蟲實作

一次下載全球 8 大指數:yf.download 批次寫法

抓多檔標的時,比起用迴圈一檔一檔呼叫 crawl_price,新版 yfinance 更建議用 yf.download 一次傳入清單,它會自動平行下載:

顯示程式碼
import yfinance as yf
 
indices = ["^GSPC", "^IXIC", "^DJI", "^TWII",
           "^N225", "^GDAXI", "^FTSE", "^HSI"]
 
raw = yf.download(indices, period="max", auto_adjust=False)
close = raw["Close"]          # 欄位是 MultiIndex,取 Close 得到寬表
close = close.tz_localize(None)

回傳的欄位是兩層的 MultiIndex(價格種類 × 代號),取 ["Close"] 之後就是「一欄一個指數」的寬表,後續分析都基於它。想看逐檔迴圈與 dictionary 的批次寫法,全球指數歷史數據下載教學有完整實作。

各指數能回溯多遠?這是很少有人實際測過的問題,實測結果:

yfinance 全球指數可回溯起始年實測,標普 500 自 1927 年起共 24,727 個交易日

標普 500 可以回溯到 1927 年 12 月 30 日,將近一百年、24,727 個交易日;日經 225 從 1965 年起有 15,101 個交易日;台灣加權指數從 1997 年 7 月 2 日開始,共 7,091 個交易日。注意道瓊工業在 Yahoo 上只能回溯到 1992 年,雖然這個指數本身已有百年以上歷史:資料源的覆蓋範圍與指數的存在時間是兩回事,動手抓之前別想當然。

拿到價格後,要把起始值不同的指數放在同一張圖比較,先做正規化,讓每個指數都從 100 出發:

It=100×PtP0I_t = 100 \times \frac{P_t}{P_0}

文章開頭那張累積走勢圖就是這樣畫出來的:2000 年起算,那斯達克收在 609(漲 5.1 倍)居冠,恒生收在 140(漲 0.4 倍)墊底。

8 大指數的風險與報酬:拿到資料後能做什麼

有了乾淨的日收盤價,就能計算風險報酬指標。年化報酬與年化波動的定義:

CAGR=(PTP0)1/n1σann=σdaily252\text{CAGR} = \left(\frac{P_T}{P_0}\right)^{1/n} - 1 \qquad \sigma_{ann} = \sigma_{daily}\sqrt{252}

其中 nn 是經過的年數,252 是一年的交易日數。簡單示例(示意數字):指數 10 年從 100 漲到 200,CAGR 是 21/101=7.18%2^{1/10}-1=7.18\%,而非 100% 除以 10 年的 10%;日報酬標準差 1.2% 的指數,年化波動約 1.2%×25219%1.2\%\times\sqrt{252}\approx 19\%。用這兩個座標把 8 大指數畫成一張風險報酬地圖:

全球 8 大指數風險報酬地圖,x 軸年化波動 y 軸年化報酬,那斯達克報酬與波動皆最高

右上角的那斯達克用最高的波動(24.8%)換最高的報酬(7.08%);左側的道瓊與富時 100 波動最低(18.3% 與 17.9%),但報酬差距極大(5.76% 對 1.64%);恒生則落在最差的象限,波動 23.5% 排第二高、年化報酬卻只有 1.30%。高波動不保證高報酬,這張圖是最具體的證據。

報酬之外,回撤是另一個維度:

全球 8 大指數最大回撤比較,那斯達克 -78% 最深,富時 100 -52% 最淺

8 個指數在 2000 年以來的最大回撤全部超過 -50%:那斯達克 -77.9%(網路泡沫)、DAX -72.7%、台灣加權 -66.2%。這對資產配置的含義是:單押任何一個市場,都要有資產腰斬以上的心理準備。

為什麼值得花力氣抓「全球」而非只抓台股?Solnik (1974) 用各國股市的實證資料說明,跨國分散能把投資組合風險降到單一國家組合難以達到的水準,這是國際分散化研究的起點。不過分散效果不能只看平時:Longin & Solnik (2001) 用極值理論證明,全球股市在大跌時的相關性顯著高於平時,最需要分散保護的時刻保護最弱,所以評估分散效果需要涵蓋多次崩盤的長歷史資料,這正是 period="max" 的價值。另外,拿指數資料計算相關係數時有一個量測陷阱:Forbes & Rigobon (2002) 指出高波動期間的相關係數會被波動度本身機械性地推高,未經調整就下「危機傳染」的結論會高估連動。想實際算台股與哪國指數最連動,台股相關性分析用本文下載的資料做了完整實作。

資料口徑與限制

本文沒有任何策略績效宣稱,所有數字是描述統計,口徑如下。表格涵蓋量化研究慣例上應交代的項目,不適用者照實標明:

項目 本文處理方式
資料來源與截止 yfinance 1.4.1,資料截止釘在 2026-06-10,腳本可重現
股息 指數為價格指數,不含股息;台灣加權「報酬指數」yfinance 抓不到
交易成本與滑價 未計入(本文無交易模擬,純指數算術);實際投資指數需透過 ETF,含手續費、稅與追蹤誤差
統計窗口 2000-01 至 2026-06 共同窗口;起點選在 8 大指數皆有資料之後
流動性 指數本身無流動性問題;對應 ETF 的流動性與容量本文未評估
生存者偏誤 指數成分股的汰換由指數公司處理,指數值不受影響;但用 yfinance 抓「個股」做回測時,下市股票資料缺失會造成生存者偏誤,見下節
前視偏差 僅使用日收盤價,無財報公布日對齊問題;Yahoo 偶有歷史資料修訂,重跑結果可能微幅變動
樣本內外 不適用(無策略參數可過擬合);描述統計對窗口選擇敏感,更換起點數字會變

yfinance 的三個台股痛點與 finlab 替代方案

把 yfinance 用在全球指數,體驗接近完美;把它用在台股個股研究,有三個實測會遇到的痛點:

  1. 限流:Yahoo 對高頻請求回 429,大量下載全上市櫃近兩千檔個股既慢又容易斷。
  2. 還原品質:台股的現金股利、股票股利、減資、面額變更情境多,yfinance 的還原計算偶有誤差,且無人保證修復時程。
  3. 下市股票:已下市的股票抓不到歷史資料。做選股回測時,樣本只剩活下來的公司,績效會被系統性高估,這就是生存者偏誤,也是回測最常見的隱形錯誤之一,與過擬合並列回測兩大陷阱。

台股研究可以改用 finlab 套件,資料由台灣團隊維護,含下市股票與處理過除權息、減資的還原股價:

顯示程式碼
# pip install finlab
import finlab
from finlab import data
 
finlab.login()   # 會自動開啟瀏覽器引導登入
 
# 全上市櫃還原股價,一張寬表,含下市股票
adj = data.get("etl:adj_close")
adj["2330"].plot()

兩個工具的分工很清楚:海外指數與美股用 yfinance,台股個股的選股與回測用 finlab。資料到手後的下一步是寫策略,可以從 finlab 平台新手指南策略參數最佳化教學接著走。

常見問題 FAQ

yfinance 是免費的嗎?有官方支援嗎?

套件本身開源免費。但它抓的是 Yahoo Finance 網頁資料,並非 Yahoo 官方發布的 API,沒有服務等級保證:欄位、頻率限制、頁面結構都可能在無預告下變動。拿來研究與學習很好,正式交易系統要評估資料源風險。

台股上櫃股票的代號怎麼寫?

上市加 .TW(台積電 2330.TW),上櫃加 .TWO(中美晶 5483.TWO)。寫錯結尾會回傳空資料,這是台股使用者最常見的卡關點。

出現 429 Too Many Requests 怎麼辦?

降低請求頻率(加 time.sleep)、改用 yf.download 批次一次抓、或在自家網路與雲端主機間換 IP。本文實測裸 requests 爬 Yahoo 頁面必帶瀏覽器 User-Agent,否則直接被擋。

auto_adjust 應該開還是關?

做報酬計算與回測一律用還原價(auto_adjust=True,新版預設)。需要看「當時實際成交價位」(例如對照歷史新聞、計算股價門檻)才用原始價。台積電的實測顯示兩者 16 年差距達 21.9 倍的累積漲幅。

yfinance 可以抓分鐘線嗎?

可以,interval="1m",但 Yahoo 只提供最近 7 天的 1 分鐘線、最近 60 天的其他分鐘級資料。長歷史的分鐘線研究需要付費資料源。

台灣加權「報酬指數」抓得到嗎?

抓不到。^TWII 是不含股息的價格指數,台灣證交所另編的「發行量加權股價報酬指數」在 Yahoo Finance 上沒有代號。台股長期報酬研究若忽略股息,以台股 3% 至 4% 的常見殖利率水準,會明顯低估報酬,這時用 finlab 的還原股價資料計算個股或 0050 的含息報酬更合適。

已下市的股票抓得到嗎?對回測有什麼影響?

大多抓不到。回測樣本若只含目前還活著的股票,等於事先剔除了所有失敗者,績效會被高估,正式名稱是生存者偏誤。嚴謹的台股回測必須用含下市股票的資料庫。

yfinance 和 finlab 套件怎麼分工?

yfinance 強在全球覆蓋與零成本,適合指數、美股與快速驗證想法;finlab 強在台股資料品質(還原股價、下市股票、財報與籌碼資料)與內建回測引擎。兩者並用,各取所長。

延伸閱讀

下載資源

檔案 說明
strategy.py 本文完整可重現腳本:下載 8 大指數、台積電還原價對照、清單頁爬取實測與全部圖表
global_indices_close.csv 8 大指數 2000 年起日收盤價(資料截至 2026-06-10)

投資警語:本文僅供教學參考,不構成投資建議。過去績效不代表未來表現,投資有風險。 文中所有指數統計為不含股息的價格指數算術,未計入交易成本、滑價與稅負,且對統計窗口的選擇敏感,不代表任何可投資商品的實際報酬。

最後更新:2026-06|資料區間:2000-01 ~ 2026-06(指數統計窗口,資料截至 2026-06-10)|作者:FinLab 量化研究團隊(經量化研究員審閱)。文中數據由 yfinance 1.4.1 實跑產出,腳本見下載資源。

FinLab AI

想建立自己的策略?

用自然語言描述你的選股想法,AI 自動驗證、回測、給你答案

免費開始

更多總經與市場研究

查看全部