CoderCastrov logo
CoderCastrov
Наука о данных

Парсинг цен акций Hang Seng Index в Hong Kong с помощью Rselenium (R)

Парсинг цен акций Hang Seng Index в Hong Kong с помощью Rselenium (R)
просмотров
3 мин чтение
#Наука о данных

Пошаговое руководство по парсингу индекса 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 = ".")
Список составляющих индекса HSI

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)
Исходный DataFrame (raw_df.csv)

Предобработка данных

Нельзя принимать хорошие бизнес-решения на основе плохих данных!

Очистка данных - одна из основных задач, с которой сталкиваются дата-сайентисты или исследователи данных, тратя много времени на ее выполнение.

  1. Удаление пропущенных данных
master_df = raw_df[!raw_df$Close == "null",]
  1. Преобразование типов данных
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])
  1. Выравнивание начальной даты
master_dt = setDT(master_df)
start_date_df = master_dt[, .(Start_Date = min(Date)), by = Index]
start_date_df

Выбор выровненной начальной даты не имеет однозначного ответа. Вам нужно найти баланс между количеством акций (столбцов) и количеством записей о датах (строк). Например, я удалю первые четыре акции (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",]
  1. Выравнивание торговых дат

Хотя мы выровняли начальную и конечную дату, мы не можем гарантировать выравнивание торговой даты.

count_date_df = master_dt[, .N, by = Date]
count_date_df

Очевидно, что наши опасения оправданы, и обнаружено, что 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)
Датафрейм акций (stock_df.csv)

Вот и все! Теперь у нас есть 46 акций и 1 HSI с записями о 2190 торговых днях. Теперь вы можете перейти к Шагу 2 - Риск и доходность. =)