ETF Holdings
Retrieve the daily constituent list of a given ETF within a date range, including constituent symbol, name, holding quantity, weight, and change from the previous available data date.
GET /ownership/etf-holdings/{symbol}
Version Note
Available since v2.2.9
Parameters
| Name | Type | Description |
|---|---|---|
symbol* | string | ETF symbol (e.g. 0050, 00981A), path parameter |
from | string | Start date (format: yyyy-MM-dd), defaults to 30 days ago; the range up to to must be shorter than 1 year |
to | string | End date (format: yyyy-MM-dd), defaults to today |
sort | string | Sort by date, defaults to desc; asc is also supported |
Response
| Name | Type | Description |
|---|---|---|
symbol* | string | ETF symbol |
type* | string | Security type |
exchange* | string | Exchange |
market* | string | Market |
data* | object[] | Daily constituent data, one entry per date |
data.date* | string | Date |
data.components* | object[] | Constituent list |
data.components.symbol* | string | Constituent symbol (overseas ETFs may return a foreign symbol, e.g. AAPL UQ) |
data.components.name | string | Constituent name |
data.components.quantity | number | Holding quantity (shares) |
data.components.weight | number | Weight (%) |
data.components.quantityChange | number | Change in holding quantity from the previous available data date (omitted on the first available date) |
data.components.weightChange | number | Change in weight from the previous available data date (omitted on the first available date) |
Data Notes
- Data source: Compiled from daily constituent disclosures published by each ETF's issuing investment trust company. For reference only — the actual holdings are subject to the disclosures published by each issuer / fund prospectus.
- Query range: The range between
fromandtoin a single query must be shorter than 1 year, otherwise400is returned; an invalid date format orfromlater thantoalso returns400. - Historical coverage: Constituent data goes back to 2019; the actual start varies by each ETF's listing date and issuer disclosures. Trading days for which the issuer did not provide constituent data will not appear in the response
dataarray — rely on the actual response. - Weight coverage: This data only covers the ETF's equity holdings, so weights do not necessarily sum to 100% (the remainder being cash, futures, bonds or undisclosed positions). Taiwan equity ETFs (passive or active) are usually close to 100%; overseas equity ETFs are mostly around 90%; balanced / multi-asset and leveraged ETFs only return the equity portion and may sum to only a few tens of percent; ETFs with no equity holdings (pure bond, futures, commodity, inverse, and some currency-hedged / foreign-currency share classes) return
data: []. - Change fields:
quantityChange/weightChangeare calculated against "the ETF's previous date with constituent data," not guaranteed to be the previous trading day. These two fields are omitted on the ETF's first available data date. - No data: A non-ETF symbol, a non-existent symbol, or a range with no disclosures all return
200withdata: [](not404); in that casetype/exchange/marketare default values and do not reflect the symbol's actual attributes.
Example
- Python
- Node.js
- C#
from fubon_neo.sdk import FubonSDK, Order
sdk = FubonSDK()
accounts = sdk.login("Your ID", "Your password", "Your cert path", "Your cert password")
sdk.init_realtime() # Establish market data connection
reststock = sdk.marketdata.rest_client.stock
## Version 2.2.6 and later using following Exception for error handling
from fubon_neo.sdk import FugleAPIError
try:
response = reststock.ownership.etf_holdings(**{"symbol": "0050", "from": "2026-07-09", "to": "2026-07-09"})
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"}
print(response)
const { FubonSDK } = require('fubon-neo');
const sdk = new FubonSDK();
const accounts = sdk.login("Your ID", "Your Password", "Your Cert Path", "Your Cert Password");
sdk.initRealtime(); // Establish market data connection
const client = sdk.marketdata.restClient
client.stock.ownership.etfHoldings({ symbol: '0050', from: '2026-07-09', to: '2026-07-09' })
.then(data => console.log(data));
using FubonNeo.Sdk;
using FugleMarketData.QueryModels.Stock.Ownership;
var sdk = new FubonSDK();
var result = sdk.Login("Your ID", "Your Password", "Your Cert Path", "Your Cert Password");
sdk.InitRealtime(); // Establish market data connection
var rest = sdk.MarketData.RestClient.Stock;
var etfHoldings = await rest.Ownership.EtfHoldings(new()
{
Symbol = "0050",
From = fromDate,
To = toDate
});
var etfHoldings_cont = etfHoldings.Content.ReadAsStringAsync().Result;
Console.WriteLine(etfHoldings_cont);
Response Body (to save space, components only lists the top 3 constituents, truncated with ...; the actual response includes all constituents for the date. Example based on data as of the 2026-07-09 close; the default query range returns 21 trading days):
{
"symbol": "0050",
"type": "EQUITY",
"exchange": "TWSE",
"market": "TSE",
"data": [
{
"date": "2026-07-09",
"components": [
{
"symbol": "2330",
"name": "台積電",
"quantity": 530358242,
"weight": 58.82,
"quantityChange": 370562,
"weightChange": 0.17
},
{
"symbol": "2454",
"name": "聯發科",
"quantity": 32045645,
"weight": 5.76,
"quantityChange": 22388,
"weightChange": -0.09
},
{
"symbol": "2308",
"name": "台達電",
"quantity": 41931322,
"weight": 3.56,
"quantityChange": 29348,
"weightChange": -0.03
}
// ... remaining constituents omitted
]
}
// ... remaining trading days omitted
]
}