31 個端點 · 行情 · 基本面 · 籌碼面 · 其他
https://api.blave.orgapi-key 與 secret-key 標頭API plan or Blave Agent planstock_id:TWSE(上市)/TPEx(上櫃)代號,例如 2330、0050、00878、006208。英文字母與數字(可含點),≤ 8 字元,否則回 400 {"error": "Invalid stock_id"}。start/end:YYYY-MM-DD,含當日。除非該端點另有說明,否則不做格式驗證(以字串比較過濾),所以一律送 YYYY-MM-DD。503 {"error": "Upstream rate limit. Please retry shortly."},稍後重試。batch/<data_type>(每次 ≤ 50 檔);不要拿單股端點對整個股票池跑迴圈。/studio/market/twstock/list 無。
data = requests.get(f"{BASE_URL}/studio/market/twstock/list" , headers=headers, timeout=60).json()["data"]# [{"stock_id": "00400A", "name": "主動國泰動能高息", "close": 14.72, "market": "TWSE",# "industry_code": None, "listing_date": None}, ...] # 2,392 rows in this response{"data": [...]},約 2,400 列(上市+上櫃,含 ETF;不含興櫃)。
| 欄位 | 型別 | 說明 |
|---|---|---|
stock_id | string | 代號 |
name | string | 名稱 |
close | float | null | 最新日收盤價(上游沒有資料時為 null,例如暫停交易) |
market | string | TWSE(上市)或 TPEx(上櫃) |
industry_code | string | null | TWSE/TPEx 原始的數字產業別代碼,原樣傳回(不解碼)。ETF/非公司型證券為 null。常見代碼:15 航運業、17 金融保險業、22 生技醫療業、24 半導體業、25 電腦及週邊設備業、26 光電業、27 通信網路業、28 電子零組件業、29 電子通路業、30 資訊服務業、31 其他電子業 |
listing_date | string | null | YYYY-MM-DD;ETF/非公司型證券為 null |
只有共用錯誤(兩個市場都失敗時回 500)。
[:N] 截斷會集中在少數幾個產業。/studio/market/twstock/info/<stock_id> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 代號 | 見本類別共通規則 |
info = requests.get(f"{BASE_URL}/studio/market/twstock/info/2330" , headers=headers, timeout=30).json()["data"]# {"stock_id": "2330", "name": "台積電", "close": 2410.0, "industry_code": "24", "listing_date": "1994-09-05"}{"stock_id": "<stock_id>", "data": {...}};data 的欄位與 /list 的一列相同。
| 狀態碼 | 回應內容 | 情況 |
|---|---|---|
| 400 | {"error": "Invalid stock_id"} | 格式檢查未通過 |
| 404 | {"error": "Stock not found"} | 不是目前上市櫃的證券 |
/list 共用同一份快取。/studio/market/twstock/price/<stock_id> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 上市或上櫃股票/ETF 代號 | 英文字母/數字(可含點),≤ 8 字元,例如 2330、0050、00878、006208 | |
startstring · query | 起始日,含當日 | YYYY-MM-DD | 完整歷史 |
endstring · query | 結束日,含當日 | YYYY-MM-DD | 最新一天 |
response = requests.get(f"{BASE_URL}/studio/market/twstock/price/2330" , headers=headers, timeout=60)data = response.json()["data"] # no start/end → full history, 8,069 rows# [{"date": "1994-10-01", "stock_id": "2330", "open": 171.0, "high": 172.0,# "low": 171.0, "close": 172.0, "spread": 1.0,# "volume": 1660506, "turnover_value": 284858008, "turnover_count": 684},# {"date": "1994-10-03", "stock_id": "2330", "open": 172.0, "high": 173.0,# "low": 171.0, "close": 172.0, "spread": 0.0,# "volume": 1560000, "turnover_value": 268084000, "turnover_count": 711}, ...]{"stock_id": "<stock_id>", "data": [ ... ]},依 date 由舊到新排序。
| 欄位 | 型別 | 單位 | 說明 |
|---|---|---|---|
date | string | YYYY-MM-DD | 交易日 |
stock_id | string | — | 股票代號 |
open / high / low / close | float | 元 | 未還原價格 |
spread | float | 元 | 與前一日收盤價的差額 |
volume | int | 股 | 成交股數 |
turnover_value | int | 元 | 成交金額 |
turnover_count | int | 筆 | 成交筆數 |
| 狀態碼 | 回應內容 | 情況 |
|---|---|---|
| 400 | {"error": "Invalid stock_id"} | stock_id 格式檢查未通過 |
| 404 | {"error": "No data found for stock_id: <stock_id>"} | 未知代號/上游沒有資料 |
| 503 | {"error": "Upstream rate limit. Please retry shortly."} | 上游配額耗盡,稍後重試 |
start/end 不做格式驗證:格式錯誤的值會改用字串比較過濾,而不是回 400,所以一律送 YYYY-MM-DD。price_adj;這個端點是未還原價格。batch/price(每次 ≤ 50 檔),不要對這個端點跑迴圈。/studio/market/twstock/price_adj/<stock_id> 同 /price/<stock_id>。
params = {"start": "2020-01-01", "end": "2024-12-31"}data = requests.get(f"{BASE_URL}/studio/market/twstock/price_adj/2330" , headers=headers, params=params, timeout=60).json()["data"]形狀與欄位同 /price/<stock_id>;open/high/low/close 是還原後的價格,volume/turnover_* 與原始序列相同。
同 /price/<stock_id>。
/price 序列有新資料時重建。/studio/market/twstock/quote/<stock_id> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 代號 | 見本類別共通規則 |
data = requests.get(f"{BASE_URL}/studio/market/twstock/quote/2330" , headers=headers, timeout=30).json()["data"]# {"open": 2415.0, "high": 2465.0, "low": 2415.0, "close": 2445.0,# "change_price": -20.0, "change_rate": -0.81, "average_price": 2432.58,# "volume": 4245, "total_volume": 26403, "amount": 10379025000, "total_amount": 64227410000,# "yesterday_volume": 27390, "buy_price": 2445.0, "buy_volume": 17,# "sell_price": 2450.0, "sell_volume": 11, "volume_ratio": 0.96,# "quote_time": "2026-07-03 14:30:00", "stock_id": "2330", "tick_type": 2}{"stock_id": "<stock_id>", "data": {...}};data 是扁平物件。
| 欄位 | 型別 | 說明 |
|---|---|---|
open / high / low / close | float | 今日至今的 OHLC |
change_price / change_rate | float | 與前一日收盤價的漲跌(元/%) |
average_price | float | 成交均價 |
volume | int | 最新一筆的成交量 |
total_volume | int | 今日累計成交量 |
amount / total_amount | float | 最新一筆/累計成交金額 |
yesterday_volume | int | 前一日成交量 |
buy_price / buy_volume | float / int | 最佳買價 |
sell_price / sell_volume | float / int | 最佳賣價 |
volume_ratio | float | 量比 |
quote_time | string | YYYY-MM-DD HH:MM:SS,是完整時間戳,不像其他端點只有 date |
stock_id | string | 代號 |
tick_type | int | 0 無法判斷、1 賣盤成交、2 買盤成交 |
| 狀態碼 | 回應內容 | 情況 |
|---|---|---|
| 400 | {"error": "Invalid stock_id"} | 格式檢查未通過 |
| 404 | {"error": "No data found for stock_id: <stock_id>"} | 沒有報價 |
| 503 | {"error": "Upstream rate limit. Please retry shortly."} | 上游配額耗盡 |
/studio/market/twstock/quote | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idsstring · query必填 | 代號 | 逗號分隔,≤ 50 檔 |
data = requests.get(f"{BASE_URL}/studio/market/twstock/quote" , headers=headers, params={"stock_ids": "2330,2317"}, timeout=30).json()["data"]# {"2330": {...}, "2317": {...}}{"data": {"<stock_id>": {...quote fields...}, ...}};欄位同 /quote/<stock_id>。沒有報價的代號不會出現。
| 狀態碼 | 回應內容 | 情況 |
|---|---|---|
| 400 | {"error": "stock_ids parameter required"} | 缺少 |
| 400 | {"error": "stock_ids exceeds max 50 per request"} | 超過上限 |
| 400 | {"error": "Invalid stock_id in list"} | 有代號格式檢查未通過 |
| 503 | {"error": "Upstream rate limit. Please retry shortly."} | 上游配額耗盡 |
/studio/market/twstock/quote/all 無。
rows = requests.get(f"{BASE_URL}/studio/market/twstock/quote/all" , headers=headers, timeout=30).json()["data"]{"data": [{...quote fields...}, ...]}(約 2,800 列);欄位同 /quote/<stock_id>。
| 狀態碼 | 回應內容 | 情況 |
|---|---|---|
| 503 | {"error": "Upstream rate limit. Please retry shortly."} | 上游配額耗盡 |
/studio/market/twstock/minute/ohlcv/<stock_id>/<schema> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 代號 | 目前上市櫃的 TWSE/TPEx 代號,或 TAIEX(加權指數) | |
schemastring · path必填 | K 棒週期 | 1m, 5m, 15m, 30m, 60m, 1d | |
startstring · query | 起始日 | YYYY-MM-DD | end − 該週期的最大區間 |
endstring · query | 結束日(含當日) | YYYY-MM-DD | 今天(UTC) |
adjuststring · query | 1 = 還原(後復權)OHLC,因子同 /price_adj;volume 一律不還原 | 0, 1, true, false | 0 |
每次請求的最大區間(end − start):1m 31 天 · 5m 62 天 · 15m 93 天 · 30m 186 天 · 60m 365 天 · 1d 3650 天。
body = requests.get(f"{BASE_URL}/studio/market/twstock/minute/ohlcv/2330/1m" , headers=headers, params={"start": "2026-08-06", "end": "2026-08-06"}, timeout=60).json()# {"stock_id": "2330", "schema": "1m", "data": [# {"close": 2385.0, "high": 2395.0, "low": 2385.0, "open": 2395.0, "ts": "2026-08-06 01:00:00+00:00", "volume": 2540}, ...]}{"stock_id", "schema", "data": [...]}.
| 欄位 | 型別 | 單位 | 說明 |
|---|---|---|---|
ts | string | UTC ISO 格式 | K 棒開始時間(以分鐘起點標記);台北時間 13:30 那根是收盤集合競價 |
open / high / low / close | float | 元 | 價格 |
volume | int | 張,不是股 | 成交量。TAIEX 的 K 棒在每個週期都是 volume: 0:指數沒有成交量,所以不提供;不要當成成交金額來讀 |
| 狀態碼 | 回應內容 | 情況 |
|---|---|---|
| 400 | {"error": "Invalid stock_id (must be a listed TWSE/TPEx security)"} | 未上市櫃 |
| 400 | {"error": "Invalid schema. Allowed: [...]"} | 週期不對 |
| 400 | {"error": "Invalid adjust (use 0 or 1)"} | adjust 不對 |
| 400 | {"error": "Invalid date format. Use YYYY-MM-DD"} | 日期格式錯誤 |
| 400 | {"error": "date_range_too_large", "message": "...", "max_days": <n>} | 區間超過上限 |
| 503 | {"error": "market data temporarily unavailable"} | 資料庫讀取失敗 |
| 503 | {"error": "adjust factors temporarily unavailable"} | adjust=1 但取不到還原因子:絕不會默默改給未還原資料 |
minute/ohlcv/symbols。200 與 []。/quote/<stock_id>。/studio/market/twstock/minute/ohlcv/symbols 無。
covered = requests.get(f"{BASE_URL}/studio/market/twstock/minute/ohlcv/symbols" , headers=headers, timeout=30).json()["data"]{"data": ["2330", "TAIEX", ...]}:已經有分鐘線資料的代號(目前上市櫃的股票加上 TAIEX),已排序。
只有共用錯誤。
/studio/market/twstock/kbar/<stock_id> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 代號 | 目前上市櫃的 TWSE/TPEx 代號,或 TAIEX | |
startstring · query | 起始日 | YYYY-MM-DD | 今天 − 6 天 |
endstring · query | 結束日;end − start ≤ 31 天 | YYYY-MM-DD | 今天 |
data = requests.get(f"{BASE_URL}/studio/market/twstock/kbar/2330" , headers=headers, params={"start": "2026-08-03", "end": "2026-08-07"}, timeout=60).json()["data"]{"stock_id", "data": [...]},由舊到新。
| 欄位 | 型別 | 說明 |
|---|---|---|
date | string | YYYY-MM-DD(台北時間) |
minute | string | HH:MM:SS 台北時間,K 棒開始時間(09:00–13:30) |
stock_id | string | 代號 |
open / high / low / close | float | 元 |
volume | int | 張 |
| 狀態碼 | 回應內容 | 情況 |
|---|---|---|
| 400 | {"error": "Invalid stock_id (must be a listed TWSE/TPEx security)"} | 未上市櫃 |
| 400 | {"error": "Date range exceeds 31 days"} | 區間太長,或日期格式錯誤 |
minute/ohlcv/<stock_id>/1m。上市櫃股票沒有分鐘資料時回 [](這個端點不會觸發回補)。minute/ohlcv/symbols 涵蓋的代號有資料。/studio/market/twstock/market_value/<stock_id> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 代號 | 見本類別共通規則 | |
startstring · query | 起始日 | YYYY-MM-DD | 完整歷史 |
endstring · query | 結束日 | YYYY-MM-DD | 最新 |
data = requests.get(f"{BASE_URL}/studio/market/twstock/market_value/2330" , headers=headers, params={"start": "2026-01-01"}, timeout=60).json()["data"]{"stock_id", "data": [{"date", "stock_id", "market_value"}]};market_value 單位為元。
400 stock_id 無效、404 沒有資料、503 上游配額耗盡。
/studio/market/twstock/market_value/all | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
topint · query | 只留市值前 N 名 | 1–3000 | 全部(約 2,400) |
body = requests.get(f"{BASE_URL}/studio/market/twstock/market_value/all" , headers=headers, params={"top": 10}, timeout=60).json()# {"date": "2026-09-17", "twse_ex_etf_market_value": 150952470507848,# "data": [{"is_etf": false, "market": "TWSE", "market_value": 62885997412475,# "name": "台積電", "rank": 1, "stock_id": "2330"},# ...,# {"is_etf": true, "market": "TWSE", "market_value": 2383312875000,# "name": "元大台灣50", "rank": 6, "stock_id": "0050"}, ...]}# Index weight of a 上市 non-ETF stock (works with any `top`, the denominator is whole-market)row = body["data"][0] # 2330 — market "TWSE", is_etf falseshare = row["market_value"] / body["twse_ex_etf_market_value"]# ETFs rank alongside stocks (0050 is rank 6) — filter them with `is_etf`. Never by code prefix,# and never by re-fetching a classification: `is_etf` already IS that classification.rows = requests.get(f"{BASE_URL}/studio/market/twstock/market_value/all" , headers=headers, params={"top": 100}, timeout=60).json()["data"]top50 = [r["stock_id"] for r in rows if not r["is_etf"]][:50] # ETF-free market-cap top 50tpex_only = [r["stock_id"] for r in rows if r["market"] == "TPEx"] # board filter is exact{"date": "YYYY-MM-DD", "twse_ex_etf_market_value": int, "data": [...]},依市值由大到小排序。
| 欄位 | 型別 | 說明 |
|---|---|---|
date | string | 實際採用的基準日(最新公布日;可能比今天晚一天) |
twse_ex_etf_market_value | int | 元。同一基準日 market == "TWSE" 且非 ETF 各列的加總。這是全市場分母,不會因 top 而縮小 |
data[].rank | int | 名次,從 1 起算 |
data[].stock_id | string | 代號 |
data[].name | string | 名稱 |
data[].market | string | "TWSE"(上市)或 "TPEx"(上櫃),取自 TWSE/TPEx 的上市櫃名冊 |
data[].market_value | int | 元 |
data[].is_etf | bool | 排行中的 ETF 為 true(2026-09-17 的 2,370 列中有 359 列)。false 代表「不在 ETF 集合裡」,不代表「確認不是 ETF」:沒有產業類別的證券(例如 REIT 01010T)會是 false,而且仍算在 twse_ex_etf_market_value 裡 |
| 狀態碼 | 回應內容 | 情況 |
|---|---|---|
| 400 | {"error": "top must be an integer between 1 and 3000"} | top 不對 |
| 404 | {"error": "No recent market value data available"}(或上市櫃清單不完整的訊息) | 沒有近期資料 |
| 503 | {"error": "Upstream rate limit. Please retry shortly."} | 上游配額耗盡 |
/market_value/<stock_id> 跑迴圈。rank 與 twse_ex_etf_market_value 的母體不同。rank 是全市場排名(上市+上櫃,含 ETF),加上分母之後也沒有改變。分母只算上市、排除 ETF(industry_category 屬於 {ETF, 上櫃ETF, 上櫃指數股票型基金(ETF)});REIT 與特別股沒有排除。所以 market_value / twse_ex_etf_market_value 只有在該列 market 為 "TWSE" 且不是 ETF 時才是指數權重,上櫃或 ETF 的列除以這個分母不是權重;rank 則仍是全市場排名。不要把兩者當成同一個排行來讀。market 是掛牌板別標記,不是 ETF 旗標,is_etf 才是 ETF 旗標。要排除 ETF 的股票池就用它。不要從 stock_id 開頭推斷 ETF(00 是市場慣例而不是規格,而且會漏掉 REIT 01xxxT),也不要再從別處抓一次分類。is_etf 正是 twse_ex_etf_market_value 計算時用的判準,所以用 is_etf 篩選的結果和分母不可能對不上。/studio/market/twstock/per/<stock_id> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 代號 | 見本類別共通規則 | |
startstring · query | 起始日 | YYYY-MM-DD | 完整歷史 |
endstring · query | 結束日 | YYYY-MM-DD | 最新 |
data = requests.get(f"{BASE_URL}/studio/market/twstock/per/2330" , headers=headers, params={"start": "2026-01-01", "end": "2026-07-22"}, timeout=60).json()["data"]# [{"date": "2026-07-21", "stock_id": "2330", "dividend_yield": 0.95, "PER": 34.87, "PBR": 11.05}, ...]{"stock_id", "data": [...]}.
| 欄位 | 型別 | 說明 |
|---|---|---|
date | string | 交易日 |
stock_id | string | 代號 |
dividend_yield | float | 殖利率(%) |
PER | float | 本益比 |
PBR | float | 股價淨值比 |
400 stock_id 無效、404 沒有資料、503 上游配額耗盡。
batch/per。/studio/market/twstock/financials/<stock_id> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 代號 | 見本類別共通規則 | |
startstring · query | 起始日 | YYYY-MM-DD | 2013-01-01 |
endstring · query | 結束日 | YYYY-MM-DD | 今天 |
import pandas as pddata = requests.get(f"{BASE_URL}/studio/market/twstock/financials/2330" , headers=headers, params={"start": "2022-01-01", "end": "2024-12-31"}, timeout=30).json()["data"]# [{"date": "2022-03-31", "stock_id": "2330", "type": "Revenue", "value": 491075000000.0, "origin_name": "營業收入"}, ...]wide = pd.DataFrame(data).pivot_table(index="date", columns="type", values="value", aggfunc="first"){"stock_id", "data": [...]},長格式(每季每個科目一列)。
| 欄位 | 型別 | 說明 |
|---|---|---|
date | string | 季末日(03-31/06-30/09-30/12-31) |
stock_id | string | 代號 |
type | string | 科目代碼,例如 Revenue、GrossProfit、OperatingIncome、NetIncome、EPS、TAX、OtherComprehensiveIncome |
value | float | 數值(元;EPS 為每股元) |
origin_name | string | 中文科目名稱,遇到不認得的 type 代碼時用它辨識 |
400 stock_id 無效、404 沒有資料、503 上游配額耗盡。
start 預設為 2013-01-01;送更早的 start 就會拿到更早的資料(2330 最早到 2000-06-30)。/studio/market/twstock/balance_sheet/<stock_id> 同 /financials/<stock_id>。
data = requests.get(f"{BASE_URL}/studio/market/twstock/balance_sheet/2330" , headers=headers, params={"start": "2022-01-01"}, timeout=30).json()["data"]長格式同 /financials/<stock_id>。主要 type 代碼:CashAndCashEquivalents、TotalAssets、TotalLiabilities、TotalEquity。結尾為 _per 的代碼是佔總資產的百分比。
400 stock_id 無效、404 沒有資料、503 上游配額耗盡。
start 預設為 2013-01-01;送更早的 start 就會拿到更早的資料(2330 最早到 2012-12-31)。/studio/market/twstock/cashflow/<stock_id> 同 /financials/<stock_id>。
import pandas as pddata = requests.get(f"{BASE_URL}/studio/market/twstock/cashflow/2330" , headers=headers, params={"start": "2022-01-01"}, timeout=30).json()["data"]cfo = (pd.DataFrame(data).query("type == 'CashFlowsFromOperatingActivities'") .assign(date=lambda d: pd.to_datetime(d["date"])).set_index("date")["value"].sort_index())cfo_q = cfo - cfo.groupby(cfo.index.year).shift(1).fillna(0) # YTD → single quarter長格式同 /financials/<stock_id>。主要 type 代碼(上游資料集自己的代碼;完整集合依公司與年度而異,以回應內容為準,下表沒有的用 origin_name 判讀)。篩選時用 type,不要用 origin_name:同一個代碼的中文名稱在不同年度會在全形與半形括號之間切換:
type | origin_name |
|---|---|
CashFlowsFromOperatingActivities | 營業活動之淨現金流入(流出) |
CashProvidedByInvestingActivities | 投資活動之淨現金流入(流出) |
CashFlowsProvidedFromFinancingActivities | 籌資活動之淨現金流入(流出) |
PropertyAndPlantAndEquipment | 取得不動產、廠房及設備(資本支出,負值) |
Depreciation / AmortizationExpense | 折舊費用 / 攤銷費用 |
CashBalancesIncrease | 本期現金及約當現金增加(減少)數 |
CashBalancesBeginningOfPeriod / CashBalancesEndOfPeriod | 期初(年初)/ 期末現金及約當現金餘額 |
流量科目是年初至今(YTD)累計,照台灣申報方式:03-31 那列只有 Q1,06-30 是 Q1–Q2,09-30 是 Q1–Q3,12-31 是全年。要單季數字就減掉同年前一季(Q1 不用減),所以 start 要從 1 月開始抓。CashBalancesEndOfPeriod 是季末餘額;CashBalancesBeginningOfPeriod 是年初餘額。這個端點沒有 period 參數,一律回 YTD(?period=quarter 單季檢視只存在於網頁圖表路由,這裡沒有)。
400 stock_id 無效、404 沒有資料、503 上游配額耗盡。
start 預設為 2013-01-01;送更早的 start 就會拿到更早的資料(2330 最早到 2012-03-31)。/studio/market/twstock/monthly_revenue/<stock_id> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 代號 | 見本類別共通規則 | |
startstring · query | 起始日 | YYYY-MM-DD | 2000-01-01 |
endstring · query | 結束日 | YYYY-MM-DD | 今天 |
import pandas as pddata = requests.get(f"{BASE_URL}/studio/market/twstock/monthly_revenue/2330" , headers=headers, params={"start": "2024-01-01", "end": "2024-12-31"}, timeout=30).json()["data"]df = pd.DataFrame(data).sort_values(["revenue_year", "revenue_month"])df["yoy_pct"] = df["revenue"].pct_change(periods=12) * 100# [{"date": "2024-01-01", "stock_id": "2330", "country": "Taiwan", "create_time": "",# "revenue": 176299866000, "revenue_year": 2023, "revenue_month": 12},# {"date": "2024-02-01", "stock_id": "2330", "country": "Taiwan", "create_time": "",# "revenue": 215785127000, "revenue_year": 2024, "revenue_month": 1}, ...]{"stock_id", "data": [...]},每月一列。
| 欄位 | 型別 | 說明 |
|---|---|---|
date | string | 營收月份的下一個月的第一天:2024-01-01 那列是 revenue_year: 2023、revenue_month: 12。絕不要拿它當營收期間 |
stock_id | string | 代號 |
country | string | 市場,觀察到的值是 Taiwan |
create_time | string | 每一列都觀察到是空字串("") |
revenue | int | 月營收,單位為元,不是千元。這是從數量級推得的,上游沒有註明:2330 的 revenue_year 2024, revenue_month 1 回 215785127000,只有讀成元(NT$215.8bn)才是合理的數字 |
revenue_month | int | 營收月份(1–12),營收期間看這個,不要看 date |
revenue_year | int | 營收年度 |
400 stock_id 無效、404 沒有資料、503 上游配額耗盡。
/studio/market/twstock/ratios/<stock_id> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 代號 | 見本類別共通規則 | |
startstring · query | 起始季末日 | YYYY-MM-DD | 2013-01-01 |
endstring · query | 結束季末日 | YYYY-MM-DD | 今天 |
import pandas as pddata = requests.get(f"{BASE_URL}/studio/market/twstock/ratios/2330" , headers=headers, params={"start": "2024-01-01"}, timeout=30).json()["data"]# [..., {"date": "2026-06-30", "stock_id": "2330",# "gross_margin_q": 67.7207, "gross_margin_ttm": 64.2302, "operating_margin_q": 60.3443, "operating_margin_ttm": 56.1009,# "net_margin_q": 55.6354, "net_margin_ttm": 50.3717, "roe_q": 11.3934, "roe_ttm": 40.3342, "roa_q": 7.8372, "roa_ttm": 27.3074,# "eps_q": 27.25, "eps_ttm": 86.28, "eps_yoy_q": 77.4089, "eps_yoy_ttm": 53.2232,# "revenue_yoy_q": 36.0453, "revenue_yoy_ttm": 30.5567, "revenue_qoq_q": 12.0163, "revenue_qoq_ttm": 8.2017,# "debt_ratio": 30.9438, "current_ratio": 245.7635, "quick_ratio": 225.0114, "equity_multiplier": 1.4481,# "interest_coverage_q": 280.5515, "interest_coverage_ttm": 227.0232,# "inventory_turnover_q": 1.1767, "inventory_turnover_ttm": 4.6058, "cfo_to_net_income_q": 1.1084, "cfo_to_net_income_ttm": 1.1779,# "fcf_q": 287363030000.0, "fcf_ttm": 1143556366000.0, "fcf_per_share_q": 11.0827, "fcf_per_share_ttm": 44.1036, ...}]df = pd.DataFrame(data).assign(date=lambda d: pd.to_datetime(d["date"])).set_index("date"){"stock_id", "data": [...]},寬格式:每季一列,由舊到新,每個比率一欄。每個比率都是四捨五入到 4 位小數的 float,或 null。
| 欄位 | 型別 | 說明 |
|---|---|---|
date | string | 季末日(03-31/06-30/09-30/12-31),不是財報公開的日期 |
stock_id | string | 代號 |
<ratio>_q | float | null | 單季 |
<ratio>_ttm | float | null | 近四季(四個單季加總);四季中任一季缺資料就是 null |
debt_ratio, current_ratio, quick_ratio, equity_multiplier | float | null | 期末資產負債表比率,沒有後綴 |
<ratio>(每個都有 _q 與 _ttm 兩種):
| 類別 | 比率 | 單位 |
|---|---|---|
| 獲利能力 | gross_margin, operating_margin, pretax_margin, net_margin, opex_ratio, roe, roa | %(已乘 100) |
| 每股 | eps, revenue_per_share, fcf_per_share | 每股元 |
| 成長 | revenue_yoy, revenue_qoq, operating_income_yoy, net_income_yoy, eps_yoy | %(已乘 100) |
| 結構 | interest_coverage | 倍 |
| 經營效率 | receivable_turnover, inventory_turnover, asset_turnover, cfo_to_net_income | 倍 |
| 現金流量 | fcf | 元,原始金額(不是千元) |
沒有後綴的欄位:debt_ratio、current_ratio、quick_ratio 是 %(已乘 100,流動比率 2.46 倍會回 245.7635);equity_multiplier 是倍數。
| 狀態碼 | 回應內容 | 情況 |
|---|---|---|
| 400 | {"error": "Invalid stock_id"} | 代號格式檢查未通過 |
| 404 | {"error": "No data found for stock_id: <id>"} | 這個代號沒有財報(例如 0050/00878 這類 ETF),或 start–end 範圍內沒有資料 |
| 503 | {"error": "Data temporarily unavailable. Please retry shortly."} | 比率資料庫還沒準備好,稍後重試,絕不要當成「沒有資料」 |
null(沒有毛利率、流動比率等)。date 對齊會有前視偏差。null,絕不會是 0。per/<stock_id>),以及月營收相關比率(自己用 monthly_revenue/<stock_id> 算年增/月增)。GET /studio/market/twstock/batch/ratios?stock_ids=...(每次 ≤ 50 檔)。start 也拿不到更早的資料。/studio/market/twstock/dividend/<stock_id> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 代號 | 目前上市櫃的代號(4–6 位數字,結尾可帶一個英文字母) | |
startstring · query | 起始生效日 | 嚴格 YYYY-MM-DD | 完整歷史 |
endstring · query | 結束生效日 | 嚴格 YYYY-MM-DD | 完整歷史 |
區間過濾用三層遞補的生效日:有 cash_ex_date 用它,否則 stock_ex_date,再否則 record_date;剛公告、還沒有除息日的事件也會出現。
data = requests.get(f"{BASE_URL}/studio/market/twstock/dividend/2330" , headers=headers, params={"start": "2025-01-01", "end": "2025-12-31"}, timeout=30).json()["data"]# [{"record_date": "2025-03-24", "period": "113年第3季", "announce_date": "2025-03-03",# "cash_ex_date": "2025-03-18", "stock_ex_date": "", "pay_date": "2025-04-10",# "cash": 4.50002042, "stock": 0.0, "stock_ratio": 0.0}, ...]{"stock_id", "data": [...]},每筆公告一列。
| 欄位 | 型別 | 說明 |
|---|---|---|
record_date | string | 權利分派基準日 YYYY-MM-DD |
period | string | 股利所屬期間,是不透明的標籤(114年第3季、113、不適用…);當字串比較,不要解析成年份 |
announce_date | string | 公告日;不明時為 "" |
cash_ex_date | string | 除息交易日;沒有或未定時為 "" |
stock_ex_date | string | 除權交易日;沒有時為 "" |
pay_date | string | 現金股利發放日;不明時為 "" |
cash | float | 每股現金股利(元,盈餘+公積) |
stock | float | 每股股票股利(元面額,盈餘+公積) |
stock_ratio | float | stock / 10,即拆分式的調整比例 |
| 狀態碼 | 回應內容 | 情況 |
|---|---|---|
| 400 | {"error": "Invalid stock_id"} | 格式檢查未通過 |
| 400 | {"error": "Invalid start date, expected YYYY-MM-DD"}(或 end) | 日期格式錯誤 |
| 404 | {"error": "No data found for stock_id: <id>"} / {"error": "No dividend records for stock_id: <id>"} | 未上市櫃,或完全沒有股利紀錄 |
| 503 | {"error": "Upstream rate limit. Please retry shortly."} | 上游配額耗盡 |
cash == 0 且 stock == 0)會保留,代表公告不分派。2330 的完整歷史查詢最後一列比請求日還晚一週。只要過去的事件就自己依日期過濾。200 + [](與 404 不同)。404。/studio/market/twstock/news/<stock_id> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 代號 | 見本類別共通規則 | |
startstring · query | 起始日 | YYYY-MM-DD | 今天 − 6 天 |
endstring · query | 結束日;end − start ≤ 31 天 | YYYY-MM-DD | 今天 |
data = requests.get(f"{BASE_URL}/studio/market/twstock/news/2330" , headers=headers, params={"start": "2026-08-01", "end": "2026-08-07"}, timeout=60).json()["data"]{"stock_id", "data": [...]},每天多則新聞(含週末)。
| 欄位 | 型別 | 說明 |
|---|---|---|
date | string | 發布時間 |
stock_id | string | 代號 |
title | string | 標題 |
source | string | 發布來源 |
link | string | 網址 |
| 狀態碼 | 回應內容 | 情況 |
|---|---|---|
| 400 | {"error": "Date range exceeds 31 days"} 或日期解析錯誤的訊息 | 區間太長/日期格式錯誤 |
| 503 | {"error": "Upstream rate limit. Please retry shortly."} | 上游配額耗盡 |
[]。/studio/market/twstock/institutional/<stock_id> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 代號 | 見本類別共通規則 | |
startstring · query | 起始日 | YYYY-MM-DD | 完整歷史 |
endstring · query | 結束日 | YYYY-MM-DD | 最新 |
data = requests.get(f"{BASE_URL}/studio/market/twstock/institutional/2330" , headers=headers, params={"start": "2024-01-01", "end": "2024-12-31"}, timeout=60).json()["data"]# [{"date": "2024-01-02", "stock_id": "2330", "foreign_buy": 28464159, "foreign_sell": 47404324,# "trust_buy": 5553520, "trust_sell": 269712, "dealer_self_buy": 452000, "dealer_self_sell": 366190,# "dealer_hedge_buy": 942546, "dealer_hedge_sell": 780090,# "foreign_dealer_self_buy": 0, "foreign_dealer_self_sell": 0}, ...]{"stock_id", "data": [...]},寬格式,每天一列。所有數值單位都是股。
| 欄位 | 說明 |
|---|---|
date, stock_id | 日期、代號 |
foreign_buy / foreign_sell | 外資(不含外資自營商) |
trust_buy / trust_sell | 投信 |
dealer_self_buy / dealer_self_sell | 自營商自行買賣 |
dealer_hedge_buy / dealer_hedge_sell | 自營商避險 |
foreign_dealer_self_buy / foreign_dealer_self_sell | 外資自營商(多半是 0) |
400 stock_id 無效、404 沒有資料、503 上游配額耗盡。
*_buy − *_sell。GET /studio/market/twmarket/institutional)的分組方式不同,見該節。/studio/market/twstock/margin/<stock_id> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 代號 | 見本類別共通規則 | |
startstring · query | 起始日 | YYYY-MM-DD | 完整歷史 |
endstring · query | 結束日 | YYYY-MM-DD | 最新 |
import pandas as pddata = requests.get(f"{BASE_URL}/studio/market/twstock/margin/2330" , headers=headers, params={"start": "2024-01-01"}, timeout=60).json()["data"]df = pd.DataFrame(data)df["margin_util"] = df["margin_balance"] / df["margin_limit"] # 融資使用率{"stock_id", "data": [...]},每天一列。數值單位是張,不是股,已對照 TWSE MI_MARGN 驗證:2026-09-15 的 2330 回 margin_balance: 29282 與 margin_limit: 6483092,與 TWSE 當日公布的今日餘額 29,282、次一營業日限額 6,483,092 完全相符。每一列都帶自己的 date 與 stock_id;讀完整歷史(不帶 start/end)時,每個數字都要取自同一列:margin_limit 每天重新公布,會隨時間改變。
| 欄位 | 說明 |
|---|---|
margin_buy / margin_sell | 融資買進/賣出 |
margin_cash_repay | 融資現金償還 |
margin_balance / margin_prev_balance | 融資今日/前日餘額 |
margin_limit | 融資限額,即 TWSE 在該列日期公布的次一營業日限額,也就是適用於下一個營業日的上限(2330 在 2026-09-15 為 6,483,092 張) |
short_buy / short_sell | 融券買進/賣出 |
short_cash_repay | 融券現金償還 |
short_balance / short_prev_balance | 融券今日/前日餘額 |
short_limit | 融券限額 |
offset_loan_short | 資券相抵 |
400 stock_id 無效、404 沒有資料、503 上游配額耗盡。
/studio/market/twstock/gov_bank/<stock_id> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 代號 | 見本類別共通規則 | |
startstring · query | 起始日 | YYYY-MM-DD | 今天 − 6 天 |
endstring · query | 結束日;end − start ≤ 31 天 | YYYY-MM-DD | 今天 |
data = requests.get(f"{BASE_URL}/studio/market/twstock/gov_bank/2330" , headers=headers, params={"start": "2026-08-01", "end": "2026-08-07"}, timeout=60).json()["data"]{"stock_id", "data": [...]},每天最多 8 列(每家行庫一列),依日期、行庫排序。
| 欄位 | 說明 |
|---|---|
date, stock_id | 日期、代號 |
bank_name | 行庫 |
buy / sell | 買進/賣出股數 |
buy_amount / sell_amount | 買進/賣出金額(元) |
| 狀態碼 | 回應內容 | 情況 |
|---|---|---|
| 400 | {"error": "Date range exceeds 31 days"} 或日期解析錯誤的訊息 | 區間太長/日期格式錯誤 |
| 503 | {"error": "Upstream rate limit. Please retry shortly."} | 上游配額耗盡 |
/studio/market/twstock/lending/<stock_id> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 代號 | 見本類別共通規則 | |
startstring · query | 起始日 | YYYY-MM-DD | 完整歷史 |
endstring · query | 結束日 | YYYY-MM-DD | 最新 |
data = requests.get(f"{BASE_URL}/studio/market/twstock/lending/2330" , headers=headers, params={"start": "2026-08-01"}, timeout=60).json()["data"]{"stock_id", "data": [...]},每天多列。
| 欄位 | 說明 |
|---|---|
date, stock_id | 日期、代號 |
transaction_type | 競價 / 議借 |
volume | 成交量 |
fee_rate | 借券費率 |
close | 收盤價 |
original_return_date | 原始還券日 |
original_lending_period | 原始借券期間 |
400 stock_id 無效、404 沒有資料、503 上游配額耗盡。
/studio/market/twstock/broker/search | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
namestring · query必填 | 要搜尋的分點名稱 | 任意子字串,不分大小寫 |
rows = requests.get(f"{BASE_URL}/studio/market/twstock/broker/search" , headers=headers, params={"name": "松山"}, timeout=30).json()["data"]# [{"broker_id": "9217", "broker_name": "凱基-松山"}, ...]{"query": "<name>", "data": [{"broker_id", "broker_name"}]}.
| 狀態碼 | 回應內容 | 情況 |
|---|---|---|
| 400 | {"error": "name parameter required"} | 缺少 |
| 503 | {"error": "Upstream rate limit. Please retry shortly."} | 上游配額耗盡 |
/studio/market/twstock/broker/stock/<stock_id> 查單日送 date,查區間送 start(+ end);兩者都送時以 start 為準。
| 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
stock_idstring · path必填 | 代號 | 見本類別共通規則 | |
datestring · query | 單日 | YYYY-MM-DD | 今天 |
startstring · query | 區間起點 | YYYY-MM-DD | |
endstring · query | 區間終點;區間 ≤ 366 天(含頭尾) | YYYY-MM-DD | start |
rows = requests.get(f"{BASE_URL}/studio/market/twstock/broker/stock/2330" , headers=headers, params={"start": "2026-08-03", "end": "2026-08-07"}, timeout=60).json()["data"]{"stock_id", "data": [...]},每個分點每天一列。
| 欄位 | 型別 | 說明 |
|---|---|---|
date | string | 交易日 |
stock_id | string | 代號 |
broker_id | string | 分點代號(可能含英文字母,例如 920A) |
broker_name | string | 分點名稱 |
price | float | 成交量加權平均價 |
buy / sell | int | 買進/賣出股數 |
| 狀態碼 | 回應內容 | 情況 |
|---|---|---|
| 400 | {"error": "Invalid stock_id"} | 格式檢查未通過 |
| 400 | {"error": "Invalid date (YYYY-MM-DD)"} | 日期格式錯誤 |
| 400 | {"error": "start/end range is <n> days; max 366 (inclusive) — split into smaller ranges"} | 區間太長 |
| 503 | {"error": "Upstream rate limit. Please retry shortly."} | 資料暫時無法取得,請重試;不要當成「沒有成交」 |
200 + []。start/end 設 2026-09-06 → 2026-09-13,broker/stock/<stock_id> 與 broker/trader/<trader_id> 都回了涵蓋五個交易日的資料。/studio/market/twstock/broker/trader/<trader_id> date/start/end 規則同 /broker/stock/<stock_id>。
| 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
trader_idstring · path必填 | 分點代號,從 /broker/search 取得 | 英文字母、數字、-(例如 9217、920A) | |
datestring · query | 單日 | YYYY-MM-DD | 今天 |
startstring · query | 區間起點 | YYYY-MM-DD | |
endstring · query | 區間終點;區間 ≤ 366 天(含頭尾) | YYYY-MM-DD | start |
rows = requests.get(f"{BASE_URL}/studio/market/twstock/broker/trader/9217" , headers=headers, params={"date": "2026-08-07"}, timeout=60).json()["data"]{"trader_id", "data": [...]},每檔股票每天一列;欄位為 date、broker_id、broker_name、stock_id、price、buy、sell(同 /broker/stock)。
同 /broker/stock/<stock_id>,另外代號錯誤時回 400 {"error": "Invalid trader_id"}。
/studio/market/twstock/alerts 給 date,或 start/end,或都不給(= 今天,台北時間)。
| 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
datestring · query | 單日:當天生效中的處置,以及當天公告的注意 | 嚴格 YYYY-MM-DD;不能與 start/end 同時使用 | |
startstring · query | 區間第一天 | 嚴格 YYYY-MM-DD | 有 stock_id 時為 2001-01-01,否則為 end − 365 天 |
endstring · query | 區間最後一天(含當日) | 嚴格 YYYY-MM-DD | 今天(start 較晚時改用它) |
kindstring · query | 公告類型 | disposal(處置)、notice(注意) | 兩者 |
marketstring · query | 交易所 | twse, tpex | 兩者 |
stock_idstring · query | 單一代號;不受 366 天上限限制 | 見本類別共通規則 | 全部 |
區間的意思:處置的期間(start–end)與查詢區間有重疊就回傳,注意則是公告 date 落在區間內才回傳。不帶 stock_id 時區間最多 366 天(含頭尾),全市場更長的區間要拆開查(一次查一個日曆年剛好放得下)。與本類別的預設不同,start/end/date 都會嚴格驗證。
# disposals in force on one daydata = requests.get(f"{BASE_URL}/studio/market/twstock/alerts" , headers=headers, params={"date": "2026-10-13", "kind": "disposal"}, timeout=30).json()["data"]# [..., {"date": "2026-10-12", "stock_id": "5228", "stock_name": "鈺鎧", "market": "tpex",# "kind": "disposal", "count": 2, "start": "2026-10-13", "end": "2026-10-19",# "condition": "連續3個營業日", "measure": "第一次處置", "match_minutes": 2,# "reason": "* 公布日期:115/10/12\n* 證券代號:5228\n…", "close": 59.6, "pe": 29.22},# {"date": "2026-10-12", "stock_id": "2492", "stock_name": "華新科", "market": "twse",# "kind": "disposal", "count": 8, "start": "2026-10-13", "end": "2026-10-19",# "condition": "連續三次", "measure": "第一次處置", "match_minutes": 2,# "reason": "1處置原因:該有價證券之交易,連續三個營業日達本公司「公布注意交易資訊」標準。\n2處置期間:…", "close": None, "pe": None}, ...] # 36 rows# notices announced on one daynotes = requests.get(f"{BASE_URL}/studio/market/twstock/alerts" , headers=headers, params={"date": "2026-10-12", "kind": "notice"}, timeout=30).json()["data"]# [..., {"date": "2026-10-12", "stock_id": "5228", "stock_name": "鈺鎧", "market": "tpex",# "kind": "notice", "count": 15, "start": None, "end": None, "condition": "第一款、第三款、第四款",# "measure": None, "match_minutes": None,# "reason": "最近六個營業日(含當日)累積之最後成交價漲幅達32.63%(第一款)\n…", "close": 59.6, "pe": 29.22}, ...]# one stock's disposal history (no range cap with stock_id)hist = requests.get(f"{BASE_URL}/studio/market/twstock/alerts" , headers=headers, params={"stock_id": "2492", "kind": "disposal", "start": "2001-01-01"}, timeout=30).json()["data"]# 10 rows: 2001-11-23~2001-11-29 收足五成款券 (match_minutes None), 2018-05-08~2018-05-21 第一次處置 (5), …,# 2026-10-13~2026-10-19 第一次處置 (2){"start", "end", "data": [...]};start/end 回顯實際採用的區間(送 date 時兩者都等於 date)。各列依 date、market、kind、stock_id 排序。每則公告一列。
| 欄位 | 型別 | 說明 |
|---|---|---|
date | string | 公告日 YYYY-MM-DD(處置從下一個交易日起生效) |
stock_id | string | 代號,包含權證、ETF 與可轉債(例如 037060、45402) |
stock_name | string | null | 公告上的名稱 |
market | string | twse(上市)或 tpex(上櫃) |
kind | string | disposal 或 notice |
count | int | 交易所的累計次數(累計/累計次數) |
start, end | string | null | 處置期間,頭尾兩天都算;注意為 null |
condition | string | null | 處置:公告上的觸發條件(連續三次、連續3個營業日、最近十個營業日已有六次 …)。注意:引用的款次(第一款、第五款);沒有時為 null |
measure | string | null | 處置類型:第一次處置、第二次處置、再次處置、人工管制撮合、收足五成款券 …;注意與早期 TPEx 的列為 null |
match_minutes | int | null | 處置:從內文讀出「約每N分鐘撮合一次」的 N。內文沒寫時(約 2011 年以前的 TWSE 處置內文都是空白,以及不是撮合類的措施)與注意皆為 null |
reason | string | null | 公告全文;交易所沒有公布內文時為 null(2011-03 以前的 TWSE 處置都沒有)(處置為處置內容,注意為注意交易資訊) |
close, pe | float | null | 公告當時的收盤價與本益比;TWSE 處置一律為 null |
| 狀態碼 | 回應內容 | 情況 |
|---|---|---|
| 400 | {"error": "Invalid start date, expected YYYY-MM-DD"}(或 end) | start/end 格式錯誤 |
| 400 | {"error": "start must not be after end"} | 區間顛倒 |
| 400 | {"error": "Invalid date, expected YYYY-MM-DD"} | date 格式錯誤 |
| 400 | {"error": "use either date or start/end"} | date 與 start 或 end 同時送出 |
| 400 | {"error": "Invalid stock_id"} | 格式檢查未通過 |
| 400 | {"error": "kind must be one of ['disposal', 'notice']"} / {"error": "market must be one of ['twse', 'tpex']"} | 不認得的值 |
| 400 | {"error": "start/end range is <n> days; max 366 (inclusive) without stock_id — split into smaller ranges"} | 不帶 stock_id 時區間超過 366 天 |
| 503 | {"error": "Data temporarily unavailable. Please retry shortly."} | 要查的表目前無法提供(48 小時沒更新,或讀不到),稍後重試,絕不要當成「沒有公告」。只檢查這次要查的 kind/market 那幾張表 |
date 是公告日,start 是生效第一天。要問「D 日是否處置中」,用 date=D(或 start=end=D),不要用公告日。start/end 是公告的期間;期間內遇到休市或暫停交易時,實際結束日會延後,這份資料沒有記錄。match_minutes 依當時的規則而定(TPEx 從 2026-08-10 起由 5/20 分鐘改為 2 分鐘),要逐列讀,絕不要假設固定值。/studio/market/twstock/batch/<data_type> | 名稱 | 說明 | 可用值 | 預設 |
|---|---|---|---|
data_typestring · path必填 | 資料集 | price, price_adj, per, institutional, shareholding, foreign_shareholding, financials, balance_sheet, monthly_revenue, ratios, dividend | |
stock_idsstring · query必填 | 代號 | 逗號分隔,≤ 50 | |
startstring · query | 起始日 | YYYY-MM-DD(只有 dividend 會嚴格驗證) | 依 data_type 而定 |
endstring · query | 結束日 | YYYY-MM-DD | 依 data_type 而定 |
payload = requests.get(f"{BASE_URL}/studio/market/twstock/batch/per" , headers=headers, params={"stock_ids": "2330,6182", "start": "2026-08-04", "end": "2026-08-08"}, timeout=120).json()# {"data_type": "per",# "data": {"2330": [{"date": "2026-08-04", "dividend_yield": 0.95, "PER": 31.19, "PBR": 10.21, "stock_id": "2330"}, ...],# "6182": [...]},# "failed": []}{"data_type", "data": {"<stock_id>": [...rows...]}, "failed": [...]}。各列與對應的單股端點完全相同。
failed:伺服器端抓取失敗的代號(頻率限制或上游錯誤),重試這些。data 與 failed 裡都沒有的代號,就是真的沒有資料。| 狀態碼 | 回應內容 | 情況 |
|---|---|---|
| 400 | {"error": "Unsupported data_type '<x>'. Supported: [...]"} | data_type 不對 |
| 400 | {"error": "stock_ids parameter required"} | 缺少 |
| 400 | {"error": "stock_ids exceeds max 50 per request"} | 超過上限 |
| 400 | {"error": "Invalid stock_id in list"} | 有代號格式檢查未通過 |
| 400 | {"error": "Invalid start date, expected YYYY-MM-DD"} | 限 dividend |
ratios(財務比率):每個代號的資料列就是 /ratios/<stock_id> 的寬格式季資料("data": {"2330": [{"date": "2026-06-30", "stock_id": "2330", "roe_q": 11.3934, ...}], "2317": [...]})。沒有財報的代號(ETF)不會出現在 data 也不會出現在 failed(不回 404);比率資料庫還沒準備好時,所有代號都會放進 failed(不回 503)。dividend 與 /dividend/<stock_id> 不同:只讀已存的資料(不更新);未知代號或沒有股利紀錄的股票會直接缺席(不回 404);上游配額問題會出現在 failed,而不是回 503。