Skip to main content

Historical Candles

Query historical stock prices for listed, OTC, and emerging (ESB) stocks by symbol. A single query range is limited to 1 year; daily data for individual stocks goes back to 2010, index data goes back to 2015, and emerging stock data goes back to 2024.

historical/candles/{symbol}

Parameters

NameTypeDescription
symbol*stringStock Number
fromstringStart Date (Format: yyyy-MM-dd), defaults to 1 month ago if omitted
tostringEnd Date (Format: yyyy-MM-dd), defaults to today if omitted
timeframestringKLine Timeframe, defaults to D (day) if omitted; offer 1 1m; 3 3m; 5 5m; 10 10m; 15 15m; 30 30m; 60 60m; D day; W week; M month
adjustedstringAdjusted stock price, offer true, false (only applicable to day / week / month K) (Available >= v2.2.8)
fieldsstringField selection, offer open, high, low, close, volume, average, turnover, change (see the Response table below for applicable timeframes)
sortstringSorting, default desc descent, also offer asc ascent
info
  • Daily data update time is tentatively set to 15:30 on each trading day.
  • A single query range (from ~ to) is limited to 1 year. Exceeding this returns 400 Bad Request (error message: Date range must be less than one year).
  • Minute-level historical data is available from 2023-05-23 onward. If the query range falls entirely before this start date, or contains no trading days at all, the API returns 404 Resource Not Found (instead of an empty array).
  • Emerging stock (ESB) historical data goes back to 2024 (the actual starting point varies by symbol).

Response

NameTypeDescriptionApplicable Timeframe
type*stringSecurity Type
exchange*stringExchange
market*stringMarket Type
symbol*stringStock Number
timeframe*stringKLine Timeframe
data*object[]KLine Data
data.date*stringDate (yyyy-MM-dd for day / week / month K; ISO 8601 with timezone for minute K, e.g. 2026-07-09T13:30:00.000+08:00)All
data.opennumberOpening PriceAll
data.highnumberHighest PriceAll
data.lownumberLowest PriceAll
data.closenumberClose PriceAll
data.volumenumberVolume / Value, see the unit note belowAll
data.averagenumberAverage Price (cumulative from market open)Minute K only
data.turnovernumberTurnover (in NTD)Day / Week / Month K only
data.changenumberPrice ChangeDay / Week / Month K only
caution

The unit of volume differs by symbol type and timeframe:

  • Common stocks: sheets on minute K, shares on day / week / month K (1 sheet = 1,000 shares).
  • Emerging (ESB) stocks: shares on both minute K and day / week / month K.
  • Indices: value on minute K, shares on day / week / month K.

Examples

Day K Example

Query day K with a specified date range:

from fubon_neo.sdk import FubonSDK, Order

sdk = FubonSDK()

accounts = sdk.login("Your ID", "Your password", "Your cert path", "Your cert password") # Login first before connecting market-data

sdk.init_realtime() # Establish market-data

reststock = sdk.marketdata.rest_client.stock
# reststock.historical.candles(**{"symbol": "0050", "from": "2026-06-01", "to": "2026-06-05"}) # Version 2.2.3 and before

## After version 2.2.4 (use Exception for exception handling)
from fubon_neo.fugle_marketdata.rest.base_rest import FugleAPIError

try:
reststock.historical.candles(**{"symbol": "0050", "from": "2026-06-01", "to": "2026-06-05", "fields": "open,high,low,close,volume,turnover,change"})
except FugleAPIError as e:
print(f"Error: {e}")
print("------------")
print(f"Status Code: {e.status_code}") # Ex: 429
print(f"Response Text: {e.response_text}") # Ex: {"statusCode":429,"message":"Rate limit exceeded"}

Response Body:

{
"symbol": "0050",
"type": "EQUITY",
"exchange": "TWSE",
"market": "TSE",
"timeframe": "D",
"data": [
{
"date": "2026-06-05",
"open": 105,
"high": 105.35,
"low": 102.8,
"close": 104.15,
"volume": 337031371,
"turnover": 34914259576,
"change": -1.95
},
{
"date": "2026-06-04",
"open": 106.75,
"high": 107,
"low": 106.05,
"close": 106.1,
"volume": 236782252,
"turnover": 25181889523,
"change": -1.5
},
{
"date": "2026-06-03",
"open": 107.3,
"high": 107.85,
"low": 107.1,
"close": 107.6,
"volume": 79592362,
"turnover": 8559208311,
"change": 1.9
}
]
}

Minute K Example

Query 1-minute K with a specified date range (including average price average):

from fubon_neo.sdk import FubonSDK, Order

sdk = FubonSDK()

accounts = sdk.login("Your ID", "Your password", "Your cert path", "Your cert password") # Login first before connecting market-data

sdk.init_realtime() # Establish market-data

reststock = sdk.marketdata.rest_client.stock

## After version 2.2.4 (use Exception for exception handling)
from fubon_neo.fugle_marketdata.rest.base_rest import FugleAPIError

try:
reststock.historical.candles(**{"symbol": "2330", "from": "2026-07-09", "to": "2026-07-09", "timeframe": "1", "fields": "open,high,low,close,volume,average"})
except FugleAPIError as e:
print(f"Error: {e}")
print("------------")
print(f"Status Code: {e.status_code}") # Ex: 429
print(f"Response Text: {e.response_text}") # Ex: {"statusCode":429,"message":"Rate limit exceeded"}

Response Body:

{
"symbol": "2330",
"type": "EQUITY",
"exchange": "TWSE",
"market": "TSE",
"timeframe": "1",
"data": [
{
"date": "2026-07-09T13:30:00.000+08:00",
"open": 2415,
"high": 2415,
"low": 2415,
"close": 2415,
"volume": 6261,
"average": 2433.85
},
{
"date": "2026-07-09T13:24:00.000+08:00",
"open": 2430,
"high": 2435,
"low": 2430,
"close": 2435,
"volume": 114,
"average": 2439.56
},
{
"date": "2026-07-09T13:23:00.000+08:00",
"open": 2435,
"high": 2440,
"low": 2430,
"close": 2430,
"volume": 262,
"average": 2439.6
}
]
}
info

'*' Indicates mandatory disclosure fields.