Data Engineering · 2026-04-24 · 11 min read
台股歷史股價 API 設計:K 線、除權息、調整後收盤價與回測資料
歷史股價資料是台股量化交易、回測、技術分析、因子研究與 AI agent 股票分析的基礎。真正可用於 production workflow 的歷史股價 API,不只是回傳 open、high、low、close、volume,而是要清楚處理交易日曆、除權息、調整後價格、停牌、下市資料與資料偏誤。
TL;DR
如果你要用台股歷史股價 API 做回測,最少需要 OHLCV、交易日曆、成交量、成交金額、除權息資料與清楚的 adjusted price 設計。只用未調整的收盤價做長期回測,可能會因為配股、配息、減資或其他 corporate actions 造成績效失真。
好的歷史資料 API 應該讓使用者清楚知道:價格是否調整、成交量單位是什麼、資料時間區間如何查詢、下市股票是否保留,以及 response schema 是否能穩定接進 Python、backtester、database 或 AI agent workflow。
為什麼歷史股價 API 對台股量化交易重要?
台股量化研究通常不是從模型開始,而是從資料開始。策略訊號、回測績效、風險指標和 AI agent 的分析結果,都依賴歷史資料是否乾淨、完整且可重複取得。
如果歷史資料 API 不穩定,後續會出現幾種常見問題:
- 同一檔股票不同時間查詢結果不一致
- 欄位名稱或型別在不同 endpoint 中不一致
- 日期格式混用
- 成交量單位不清楚
- 沒有處理除權息
- 下市股票消失,造成 survivorship bias
- 停牌、無成交或缺值沒有標示
- 沒有交易日曆,導致回測日期對齊錯誤
如果你剛開始了解台股 API 的資料類型,可以先看 台股 API 完整指南。
如果你已經要用 Python 抓資料,可以參考 Python 抓台股資料教學。
如果你想把歷史資料進一步接到策略回測與風險控管,可以再看 台股量化交易入門。
如果你要把 OHLCV 進一步轉成均線、RSI、MACD 或布林通道等指標,可再看 台股技術分析 API。
OHLCV 是什麼?
OHLCV 是歷史股價最基本的資料格式,代表:
| 欄位 | 英文 | 說明 |
|---|---|---|
| O | open | 開盤價 |
| H | high | 最高價 |
| L | low | 最低價 |
| C | close | 收盤價 |
| V | volume | 成交量 |
對大多數回測、技術分析和因子研究來說,OHLCV 是最低限度資料。但台股 API 只提供 OHLCV 還不夠,還需要至少補上:
- symbol
- market
- date
- turnover
- currency
- adjusted flag
- data source
- timezone
基本 OHLCV schema
{
"date": "2026-04-23",
"symbol": "2330",
"market": "twse",
"open": 812,
"high": 825,
"low": 808,
"close": 821,
"volume": 35124000,
"turnover": 28754100000,
"currency": "TWD"
}這個 schema 看起來簡單,但最重要的是一致性。不同 endpoint 不應該混用 `stock_id`、`symbol`、`ticker`;成交量也不應該有時是股數、有時是張數,卻沒有清楚說明。
日 K、週 K、月 K 怎麼設計?
台股歷史股價 API 常見查詢粒度包括日 K、週 K 和月 K。這些資料可以由 API 直接提供,也可以由 client 端根據日 K 聚合。
| K 線類型 | 適合情境 | 開發注意事項 |
|---|---|---|
| 日 K | 回測、每日策略、因子研究 | 最常用,應優先保證資料完整與穩定 |
| 週 K | 中期趨勢、週期性報表 | 需要明確定義一週起訖與遇到假日的處理方式 |
| 月 K | 長期分析、資產配置、低頻策略 | 需要明確定義月末交易日與聚合規則 |
如果由 API 直接提供週 K 或月 K,應清楚說明聚合規則。通常:
- open 取期間第一個交易日開盤價
- high 取期間最高價
- low 取期間最低價
- close 取期間最後一個交易日收盤價
- volume 取期間成交量加總
- turnover 取期間成交金額加總
K 線查詢 endpoint 示意
GET /v1/tw/stocks/{symbol}/ohlcv?interval=1d&from=2025-01-01&to=2025-12-31
GET /v1/tw/stocks/{symbol}/ohlcv?interval=1w&from=2025-01-01&to=2025-12-31
GET /v1/tw/stocks/{symbol}/ohlcv?interval=1mo&from=2020-01-01&to=2025-12-31上方 endpoint 是示意。實際路徑請以 TW Market Data docs 為準。
除權息與調整後收盤價
台股長期回測不能忽略除權息。當公司配發現金股利、股票股利、減資或發生其他 corporate actions 時,未調整價格和調整後價格會產生差異。
如果使用未調整價格做長期策略研究,可能會把除權息造成的價格變化誤判成市場價格下跌,進而影響:
- 報酬率計算
- 技術指標
- 動能策略
- 最大回撤
- 長期績效
- AI agent 對價格走勢的解讀
未調整價格與調整後價格
| 價格類型 | 說明 | 適合用途 |
|---|---|---|
| unadjusted price | 原始交易價格,不針對除權息或 corporate actions 調整 | 還原實際市場成交價格、短期行情展示 |
| adjusted price | 根據 corporate actions 調整後的價格序列 | 長期績效、報酬率、回測、技術指標 |
| adjusted close | 通常指調整後收盤價 | 報酬率計算、策略研究、長期圖表 |
一個好的台股歷史股價 API 不一定要強迫所有使用者只用 adjusted price,但應該清楚提供參數讓使用者選擇。
調整參數設計示意
GET /v1/tw/stocks/2330/ohlcv?from=2020-01-01&to=2025-12-31&adjusted=false
GET /v1/tw/stocks/2330/ohlcv?from=2020-01-01&to=2025-12-31&adjusted=trueResponse meta 應標示 adjusted 狀態
{
"data": [
{
"date": "2026-04-23",
"symbol": "2330",
"open": 812,
"high": 825,
"low": 808,
"close": 821,
"volume": 35124000,
"turnover": 28754100000
}
],
"meta": {
"adjusted": false,
"timezone": "Asia/Taipei",
"currency": "TWD"
}
}重點不是欄位名稱一定要叫 `adjusted`,而是 API 必須明確告訴使用者現在拿到的是原始價格還是調整後價格。
歷史資料 API response schema
歷史資料 API 的 response schema 應該同時支援人類閱讀和程式消費。建議至少包含 `data` 和 `meta` 兩層。
{
"data": [
{
"date": "2026-04-23",
"symbol": "2330",
"market": "twse",
"open": 812,
"high": 825,
"low": 808,
"close": 821,
"volume": 35124000,
"turnover": 28754100000,
"currency": "TWD"
}
],
"meta": {
"source": "tw-market-data",
"interval": "1d",
"adjusted": false,
"from": "2026-04-01",
"to": "2026-04-23",
"timezone": "Asia/Taipei"
}
}欄位表
| Field | Type | Description |
|---|---|---|
| date | string | 交易日期,建議使用 ISO 8601 |
| symbol | string | 股票代號,例如 2330 |
| market | string | 市場別,例如 twse、tpex |
| open | number | 開盤價 |
| high | number | 最高價 |
| low | number | 最低價 |
| close | number | 收盤價 |
| volume | number | 成交量,需清楚定義單位 |
| turnover | number | 成交金額 |
| currency | string | 幣別,例如 TWD |
| interval | string | K 線粒度,例如 1d、1w、1mo |
| adjusted | boolean | 是否為調整後價格 |
對 developer 來說,`meta` 很重要。它可以讓 backtester 或 data pipeline 知道這批資料的查詢條件、時間區間、價格調整狀態與資料時區。
回測資料常見偏誤
歷史股價資料最危險的地方,是它看起來很完整,但實際上可能已經帶有偏誤。這些偏誤會讓回測結果看起來比真實情況更好。
Survivorship bias
如果資料庫只保留目前還存在的股票,而移除下市、下櫃或停止交易的公司,回測結果就會偏向成功存活的公司。這會高估策略績效。
Look-ahead bias
如果策略在回測中使用了當時尚未公開的資料,例如未來財報、未來指數成分股或尚未公告的 corporate actions,就會產生 look-ahead bias。
Corporate actions
除權息、減資、股票分割與其他 corporate actions 會影響價格序列。若未正確處理,技術指標和報酬率計算都會失真。
Trading calendar mismatch
如果沒有使用正確交易日曆,可能會把非交易日誤當成缺值,或讓多檔股票在不同日期對齊錯誤。
Missing data
缺值不一定代表資料錯誤,也可能代表停牌、無成交、資料尚未更新或該商品在那天不存在。API 應該讓使用者能區分這些狀況。
Bias checklist
| 偏誤 | 風險 | API 應提供的協助 |
|---|---|---|
| survivorship bias | 回測只看到存活股票 | 保留 inactive / delisted symbols |
| look-ahead bias | 使用未來資料 | 提供公告日、有效日與資料版本 |
| corporate actions | 報酬率與技術指標失真 | 提供 adjusted price 或 corporate action endpoint |
| calendar mismatch | 多商品日期對齊錯誤 | 提供交易日曆 endpoint |
| missing data | 錯把停牌或無成交當成資料錯誤 | 標示缺值原因或提供交易狀態 |
如何查詢一段時間的歷史資料?
台股歷史股價 API 應該支援清楚的時間區間查詢。最常見的方式是使用 `from` 和 `to` 參數。
GET /v1/tw/stocks/2330/ohlcv?from=2025-01-01&to=2025-12-31對大量資料來說,還需要考慮 pagination、batch query 和 rate limit。
批次查詢設計示意
POST /v1/tw/stocks/ohlcv/batch
{
"symbols": ["2330", "2317", "2454"],
"from": "2025-01-01",
"to": "2025-12-31",
"interval": "1d",
"adjusted": true
}批次查詢對 quant workflow 很重要,因為策略通常需要一次處理一整個股票 universe,而不是只查一檔股票。
上方 endpoint 是示意。實際路徑請以 TW Market Data docs 為準。
如何把歷史股價 API 接到 Python?
以下示範如何用 Python 抓取一檔股票的歷史 OHLCV,並轉成 pandas DataFrame。
import os
import requests
import pandas as pd
API_KEY = os.getenv("TW_MARKET_DATA_API_KEY")
BASE_URL = "https://api.example.com"
headers = {
"Authorization": f"Bearer {API_KEY}"
}
params = {
"from": "2025-01-01",
"to": "2025-12-31",
"interval": "1d",
"adjusted": "true"
}
response = requests.get(
f"{BASE_URL}/v1/tw/stocks/2330/ohlcv",
headers=headers,
params=params,
timeout=20
)
response.raise_for_status()
payload = response.json()
df = pd.DataFrame(payload["data"])
df["date"] = pd.to_datetime(df["date"])
df = df.sort_values("date").reset_index(drop=True)
print(df.head())上方 endpoint 是示意。實際路徑請以 TW Market Data docs 為準。
檢查價格是否為調整後資料
meta = payload.get("meta", {})
if not meta.get("adjusted"):
print("Warning: data is not adjusted. Long-term backtest may be affected by corporate actions.")如何把歷史資料接進回測系統?
歷史股價 API 回傳的 DataFrame 可以直接接進 backtester。最低限度需要 date、symbol、close 和 volume。
df["return"] = df["close"].pct_change()
df["ma20"] = df["close"].rolling(20).mean()
df["ma60"] = df["close"].rolling(60).mean()
df["signal"] = (df["ma20"] > df["ma60"]).astype(int)
df["strategy_return"] = df["signal"].shift(1) * df["return"]
equity_curve = (1 + df["strategy_return"].fillna(0)).cumprod()
print(equity_curve.tail())這只是資料處理示意,不是投資策略建議。正式回測還需要:
- 交易成本
- 滑價
- position sizing
- 風險限制
- 停損或部位調整規則
- out-of-sample test
- walk-forward validation
- portfolio-level analysis
AI agent 如何使用歷史股價資料?
AI agent 不應該靠模型內部知識猜測股價,也不應該直接把未驗證的自然語言當成市場資料。正確做法是讓 agent 透過 tool calling 查詢台股歷史資料。
Agent tool schema 示意
{
"name": "get_historical_ohlcv",
"description": "Get historical OHLCV data for a Taiwan stock.",
"parameters": {
"symbol": "2330",
"from": "2025-01-01",
"to": "2025-12-31",
"interval": "1d",
"adjusted": true
}
}Agent response schema 示意
{
"symbol": "2330",
"data_used": [
"historical_ohlcv"
],
"price_adjusted": true,
"summary": "The stock showed positive momentum over the selected period, but further risk checks are required.",
"risk_flags": [
"requires_volume_liquidity_check",
"strategy_not_backtested"
],
"not_investment_advice": true
}這種 schema 能讓 AI agent 清楚知道自己用了哪些資料、資料是否調整過,以及哪些風險還需要檢查。對 production workflow 來說,這比單純產生一段自然語言分析更可靠。
建議的 endpoint 設計
以下是歷史股價相關 endpoint 的設計示意。
GET /v1/tw/stocks/{symbol}/ohlcv
GET /v1/tw/stocks/{symbol}/ohlcv?interval=1d
GET /v1/tw/stocks/{symbol}/ohlcv?interval=1w
GET /v1/tw/stocks/{symbol}/ohlcv?interval=1mo
GET /v1/tw/stocks/{symbol}/ohlcv?adjusted=true
GET /v1/tw/stocks/{symbol}/corporate-actions
GET /v1/tw/calendar/trading-days實際 endpoint 命名不一定要完全相同。重點是查詢參數清楚、response schema 穩定、價格調整狀態明確,並且能支援回測和資料管線。
上方 endpoint 是示意。實際路徑請以 TW Market Data docs 為準。
FAQ
台股歷史股價 API 可以取得哪些資料?
通常至少會包含 OHLCV,也就是開盤價、最高價、最低價、收盤價與成交量。更完整的 API 還會包含成交金額、市場別、幣別、交易日曆、除權息資料與調整後價格。
OHLCV 和 K 線是一樣的嗎?
OHLCV 是 K 線資料的核心欄位。日 K、週 K、月 K 通常都是用 open、high、low、close、volume 組成,只是資料聚合的時間區間不同。
回測一定要用調整後收盤價嗎?
長期回測通常應該使用調整後價格,避免除權息或 corporate actions 造成報酬率失真。但如果研究的是實際成交價格或短期盤中行為,也可能需要使用未調整價格。重點是 API 必須清楚標示價格是否已調整。
台股歷史股價 API 需要交易日曆嗎?
需要。交易日曆可以幫助回測系統區分交易日、非交易日、休市日與特殊情況,避免日期對齊錯誤。
歷史股價資料可以直接拿來做量化交易嗎?
歷史股價資料是量化研究的基礎,但不能直接等同於可交易策略。正式策略還需要交易成本、滑價、風險控管、out-of-sample 測試與完整的回測流程。
AI agent 可以用歷史股價 API 分析股票嗎?
可以。AI agent 可以透過 tool calling 查詢歷史 OHLCV、技術指標或風險指標,再產生結構化摘要。但 agent 不應該直接猜測資料,也不應該把分析結果當成投資建議。
下一步
如果你正在建立台股回測、量化研究平台或 AI agent workflow,歷史股價 API 應該先處理三個問題:
- 1. 價格是否調整
- 2. 日期與交易日曆是否正確
- 3. response schema 是否能穩定接進 Python、database 和 backtester
Need historical Taiwan market data for your backtest, dashboard, or AI agent workflow?
本文討論資料工程、API 設計、量化研究與 AI workflow,不構成投資建議。