Парсинг цен акций Hang Seng Index в Hong Kong с помощью Rselenium (R)
Пошаговое руководство по парсингу индекса Hang Seng с Yahoo Finance с использованием Rselenium.
_Весь код и данные загружены на мой GitHub. Вы можете проверить и скопировать _этот репозиторий_ для дальнейшего изучения модели. _=)
Цель
Эта статья направлена на то, чтобы показать, как использовать R для парсинга цен акций в Гонконге на Yahoo Finance. В предстоящих статьях мы будем использовать этот набор данных в качестве примера для демонстрации анализа финансовых данных и также для выбора портфеля.
Индекс Ханг Сенг (HSI)
Для парсинга цен на акции необходим список индексов акций. HSI - это рыночный индекс акций Гонконга, взвешенный по капитализации. Он отражает и отслеживает ежедневные изменения крупнейших компаний гонконгской фондовой биржи. Он является основным показателем общей рыночной динамики в Гонконге. Всего в нем 50 компаний.
# Импорт библиотек
require(XML)
require(RSelenium)
require(data.table)# Открытие удаленного браузера
remDr = remoteDriver(remoteServerAddr = "localhost", browserName = "chrome")
remDr$open()
remDr$setTimeout(type = "implicit", milliseconds = 50000)
remDr$setTimeout(type = "page load", milliseconds = 50000)# Список HSI
remDr$navigate("[http://www.etnet.com.hk/www/eng/stocks/indexes_detail.php?subtype=HSI](http://www.etnet.com.hk/www/eng/stocks/indexes_detail.php?subtype=HSI)")
tables = getNodeSet(htmlParse(remDr$getPageSource()[[1]]), "//table")
df = readHTMLTable(tables[[3]],Encoding("UTF-8"))
hsi_list = paste(substr(as.character(df$V1[-1]), 2, 5), "HK", sep = ".")
Yahoo Finance
После получения списка акций, входящих в HSI, мы можем начать парсить цены акций с Yahoo Finance.
# Загрузка CSV файлов
for (hsi_idx in c("^HSI", hsi_list)){
website = paste("[https://finance.yahoo.com/quote/](https://finance.yahoo.com/quote/)", hsi_idx, "/history?period1=536342400&period2=1569772800&interval=1d&filter=history&frequency=1d", sep = "")
remDr$navigate(website)
remDr$findElement(using = "xpath", '//*[[@id](http://twitter.com/id)="Col1-1-HistoricalDataTable-Proxy"]/section/div[1]/div[2]/span[2]/a/span')$clickElement()
}
Через несколько минут автоматически загрузятся несколько CSV файлов.
Исходный DataFrame
Следующим шагом является объединение их в один CSV файл.
# Объединение CSV файлов
file_list = list.files(pattern = ".csv")
raw_df = NULL
for (file in file_list){
df = read.csv(file, stringsAsFactors = F)
df$Index = substr(file, 1, nchar(file) - 4)
raw_df = rbind(raw_df, df)
}
write.csv(raw_df, "raw_df.csv", row.names = F)
Предобработка данных
Нельзя принимать хорошие бизнес-решения на основе плохих данных!
Очистка данных - одна из основных задач, с которой сталкиваются дата-сайентисты или исследователи данных, тратя много времени на ее выполнение.
- Удаление пропущенных данных
master_df = raw_df[!raw_df$Close == "null",]
- Преобразование типов данных
master_df$Date = as.Date(master_df$Date)
for (col_idx in c(2:7))
master_df[, col_idx] = as.numeric(master_df[, col_idx])
- Выравнивание начальной даты
master_dt = setDT(master_df)
start_date_df = master_dt[, .(Start_Date = min(Date)), by = Index]
Выбор выровненной начальной даты не имеет однозначного ответа. Вам нужно найти баланс между количеством акций (столбцов) и количеством записей о датах (строк). Например, я удалю первые четыре акции (0027.HK, 1997.HK, 1113.HK и 0288.HK), чтобы получить около 9 лет данных (с 01.11.2010 по 30.09.2019).
ignore_list = c("0027.HK", "1997.HK", "1113.HK", "0288.HK")
master_dt = master_dt[!master_dt$Index %in% ignore_list,]
master_dt = master_dt[master_dt$Date >= "2010-11-01",]
- Выравнивание торговых дат
Хотя мы выровняли начальную и конечную дату, мы не можем гарантировать выравнивание торговой даты.
count_date_df = master_dt[, .N, by = Date]
Очевидно, что наши опасения оправданы, и обнаружено, что 9 дней не выровнены. Фактически, мы должны исследовать причины этого, но для простоты я просто удаляю эти девять дней. =)
date_miss_df = subset(count_date_df, N != 47)
master_dt = master_dt[!master_dt$Date %in% date_miss_df$Date,]
Датафрейм акций
Наконец, мы можем преобразовать данные в датафрейм акций.
stock_df = data.frame(matrix(master_dt$Close, ncol = 47))
colnames(stock_df) = master_dt$Index[!duplicated(master_dt$Index)]
stock_df = cbind(Date = master_dt$Date[!duplicated(master_dt$Date)], stock_df)
write.csv(stock_df, "stock_df.csv", row.names = F)
Вот и все! Теперь у нас есть 46 акций и 1 HSI с записями о 2190 торговых днях. Теперь вы можете перейти к Шагу 2 - Риск и доходность. =)