Course: YOUR COURSE NAME Instructor: INSTRUCTOR NAME
Download the daily adjusted prices of three Taiwan ETFs (0050, 0052, 0056) from the TEJ database, import them into R, and convert them into a time-series object with one column per ETF.
The data were downloaded from the TEJ database using
TEJ Pro. The variable used is the daily adjusted
closing price (Close(NTD)) of:
| Code | ETF |
|---|---|
| 0050 | 元大台灣50 (Yuanta Taiwan Top50) |
| 0052 | 富邦科技 (FB Technology) |
| 0056 | 元大高股息 (Yuanta High Dividend / PTD) |
Requested range: 2010-01-01 to 2026-09-22. The first trading day in the range is 2010-01-04.
The TEJ Pro export is a tab-delimited, UTF-16 encoded text file in “long” format (one row per ETF per day).
candidates <- c("20260924061630.csv",
"~/Downloads/20260924061630.csv",
"~/Desktop/20260924061630.csv")
file_path <- candidates[file.exists(candidates)][1]
raw <- read.delim(file_path, fileEncoding = "UTF-16",
check.names = FALSE, stringsAsFactors = FALSE)
names(raw) <- sub("^\ufeff", "", names(raw)) # remove a hidden BOM character if present
names(raw)
## [1] "CO_ID" "Date" "Close(NTD)"
str(raw)
## 'data.frame': 12297 obs. of 3 variables:
## $ CO_ID : chr "0050 Yuanta Taiwan Top50" "0052 FB Technology" "0056 PTD" "0050 Yuanta Taiwan Top50" ...
## $ Date : int 20100104 20100104 20100104 20100105 20100105 20100105 20100106 20100106 20100106 20100107 ...
## $ Close(NTD): num 8.45 2.92 8.47 8.45 2.93 ...
etf_long <- raw %>%
rename(security = `CO_ID`, date = `Date`, price = `Close(NTD)`) %>%
mutate(
code = substr(security, 1, 4),
date = as.Date(as.character(date), format = "%Y%m%d"),
price = as.numeric(price)
) %>%
select(date, code, price) %>%
arrange(code, date)
head(etf_long)
## date code price
## 1 2010-01-04 0050 8.4501
## 2 2010-01-05 0050 8.4501
## 3 2010-01-06 0050 8.6072
## 4 2010-01-07 0050 8.5847
## 5 2010-01-08 0050 8.6371
## 6 2010-01-11 0050 8.6595
The xts package (built on zoo) is the
standard R structure for financial time series: the dates are the index
and each ETF is a column.
etf_wide <- etf_long %>%
pivot_wider(names_from = code, values_from = price) %>%
arrange(date) %>%
select(date, `0050`, `0052`, `0056`)
etf_xts <- xts(as.matrix(etf_wide[, c("0050", "0052", "0056")]),
order.by = etf_wide$date)
colnames(etf_xts) <- c("0050 元大台灣50", "0052 富邦科技", "0056 元大高股息")
head(etf_xts) # first six rows of the full sample
## 0050 元大台灣50 0052 富邦科技 0056 元大高股息
## 2010-01-04 8.4501 2.9216 8.4679
## 2010-01-05 8.4501 2.9256 8.4318
## 2010-01-06 8.6072 2.9936 8.5579
## 2010-01-07 8.5847 2.9616 8.4859
## 2010-01-08 8.6371 2.9528 8.5760
## 2010-01-11 8.6595 2.9696 8.6660
head(etf_xts["2020-01-02/2020-01-09"], 6) # rows to compare with the example
## 0050 元大台灣50 0052 富邦科技 0056 元大高股息
## 2020-01-02 19.8573 8.1422 16.9530
## 2020-01-03 19.8573 8.0922 17.0054
## 2020-01-06 19.6031 8.0033 16.8772
## 2020-01-07 19.5421 7.9755 16.7199
## 2020-01-08 19.4506 7.9144 16.6091
## 2020-01-09 19.7149 8.0477 16.7257
tail(etf_xts)
## 0050 元大台灣50 0052 富邦科技 0056 元大高股息
## 2026-09-15 106.25 61.60 55.00
## 2026-09-16 106.90 61.95 55.55
## 2026-09-17 108.05 62.70 56.30
## 2026-09-18 109.85 63.80 56.85
## 2026-09-21 111.35 64.55 57.15
## 2026-09-22 111.85 64.75 56.85
dim(etf_xts)
## [1] 4099 3
class(etf_xts)
## [1] "xts" "zoo"
checks <- data.frame(
check = c("Number of observations (days)",
"Minimum date",
"Maximum date",
"Missing values",
"Duplicated dates (time series)",
"Duplicated code/date pairs (long data)",
"All three ETFs present",
"Prices numeric",
"Sorted by date"),
result = c(nrow(etf_xts),
as.character(min(index(etf_xts))),
as.character(max(index(etf_xts))),
sum(is.na(etf_xts)),
sum(duplicated(index(etf_xts))),
sum(duplicated(etf_long[, c("code", "date")])),
all(c("0050", "0052", "0056") %in% etf_long$code),
is.numeric(coredata(etf_xts)),
!is.unsorted(index(etf_xts)))
)
checks
## check result
## 1 Number of observations (days) 4099
## 2 Minimum date 2010-01-04
## 3 Maximum date 2026-09-22
## 4 Missing values 0
## 5 Duplicated dates (time series) 0
## 6 Duplicated code/date pairs (long data) 0
## 7 All three ETFs present TRUE
## 8 Prices numeric TRUE
## 9 Sorted by date TRUE
etf_long %>%
group_by(code) %>%
summarise(n = n(), first_date = min(date), last_date = max(date),
missing = sum(is.na(price)))
## # A tibble: 3 × 5
## code n first_date last_date missing
## <chr> <int> <date> <date> <int>
## 1 0050 4099 2010-01-04 2026-09-22 0
## 2 0052 4099 2010-01-04 2026-09-22 0
## 3 0056 4099 2010-01-04 2026-09-22 0
The daily adjusted prices of ETFs 0050, 0052 and 0056 were imported
from TEJ Pro, cleaned, and converted into a single xts time
series with one column per ETF. The series covers 2010-01-04 to
2026-09-22, contains no missing values or duplicated dates, and is
sorted chronologically. The rows for January 2020 match the format and
values in the assignment example.