網頁

2016年4月29日 星期五

程式語言 : 用 R 理財, 下載歷史股價合併至財務報表

創用 CC 授權條款
南台灣。木星人MHYen製作,以創用CC 姓名標示-非商業性-禁止改作 3.0 台灣 授權條款釋出。
實在是沒料到最近開始學寫程式,一時間不知道該如何形容現在的感覺,而之前速寫裡只有這張跟電腦有關…,而圖中的阿奇表情非常的有意思呢!感覺這個世界真的是日新月異,開始學寫程式之後才發現,有這麼好用的統計軟體:R!

早在好幾年前就耳聞 R 這個軟體,當時的印象是認為像大學時統計學老師教的 SAS 軟體一樣,是一種「好用的統計軟體」,而 R 是免費的自由軟體。實際接觸後更體認到 R 有多強大!除了基本的資料框架的整理、字串編輯、資料合併、篩選等等,R 還有很多套件可以使用,其中 quantmod 屬於財經資料庫的套件,可以下載不同資料庫的財經資料 (網站說明:http://www.quantmod.com/examples/intro/#data),像是 yahoo finance、google finance、FRED等的的歷史股價,還可依據下載的資料繪製線圖,或是進行回測 (可參考:第一次使用R語言做回測:六分鐘,就上手!) 。當時看到 R 在理財方面如此強大的功能真是非常吃驚!因為股票的歷史股價資料非常龐大因而難整理,以往都是到證交所網站滑鼠點選下載 CSV 檔…。現在只要在 R 程式的 quantmod 套件下就可以在 5 分鐘內下載台股單日完整的交易資料!

而最近研究 R 的最大收穫,除了在恐懼寫程式的自己有所突破外,更體認到寫程式其實是與電腦溝通的方式,本質上在解決日常生活中大大小小的問題!套一句菜頭先生對寫程式的形容:『寫程式就是叫電腦做奴隸做的事!』日常中具規律性的工作,如果交給電腦可以在按下 enter 鍵那瞬間完成任務,這是一件多開心的事呀!而人腦則在「找出問題」然後想辦法「解決問題」!

所以今天的問題是:如何用 R 一次下載所有台股的歷史股價?

以下為 quantmod 下載股價的基本指令:
> library(quantmod) # 開啟套件
> getSymbols("YHOO", from = "2016-04-01", to = "2016-04-29", src="google")   # 用 getSymbols() 輸入"股票代碼""日期""資料庫來源"

要用 quantmod 下載股價首先必須要知道台股的代碼,若沒指定資料庫 quantmod 內建的設定是 yahoo finance,因此台股的代碼必須符合 yahoo finance 的格式,像台股代碼 3266 在 yahoo finance 是 3266.TW。先用從公開資訊觀測站下載的財報資料,代碼欄位進行字串編輯,再另外指定代碼欄位的變數,放入 getSymbols():
> library(quantmod)
> m_data_20160411 <- read.table("Desktop/R/m_data_20160411.csv", header=TRUE, sep=",") #匯入 CSV 財報檔
> name <- paste(m_data_20160411[,1],"TW", sep = ".") #依據財報檔的代碼欄位新增 .TW 於字串中,並指定為變數 "name" 
> getSymbols(name, from = "2016-04-27", to = "2016-04-27", src="yahoo") 

這個方式初步成功了,也產生了每支股票在指定日期內的所有資料,開盤價 Op、收盤價 Cl、最高價 Hi、最低價 Lo、成交量 Vo、均價 Ad 六個欄位的 data frame。
1101.TW於2016-04-27這天的成交資料
然而這個方法有一個很大的問題,就是如果 yahoo finance 或其他資料庫某幾支股票有一些問題無法下載時便會停止,查找後發現有 4 支股票的資料無法下載。為了這個問題在網路上找了很久,試過各種方式後來選擇用 loop 的方式解決 :
> dataset<- xts() #設置一個xts資料框架
以下為 loop 的寫法:
for(i in 1:length(name)) {
  name[i]-> symbol
  tryit <- try(getSymbols(symbol,from="2016-04-27", src='yahoo'))# specify the "from" date to desired start date
  if(inherits(tryit, "try-error")){
    i <- i+1
  } else {
    data <- getSymbols(symbol, from="2016-04-27", src='yahoo')# specify the "from" date to desired start date
  dataset <- merge(dataset, Cl(get(name[i])))#將所有股票的收盤價 Cl 合併成一個 data frame
  rm(symbol)
  }
 }
從指令可以看出是要電腦依據股票代碼,一個個到資料庫抓取資料,try() 的用法,然後用 if else 設條件,如果資料抓取失敗就跳到下一個股票,最後將所有股票的收盤價 Cl 合併成一個 data frame。
跑出一個很長的 data frame 總共找出 824 支股票(行)在 2016-04-27(列)的收盤價,
由此只要在設定期間內,每日的股價都可以下載
最後將股價資料合併至一開始匯入的財報檔:
> myDF <- as.data.frame(as.matrix(dataset))#將dataset轉換為data frame
> namex2 <- substr(name, start = 1, stop = 4)#先將股票代碼統一成m_data_20160411"公司代號"格式
> newrow = namex2
> datasetSS = rbind(myDF,newrow)#將股票代碼新增1列至myDF中
> datasetT <- t(datasetSS)#轉置datasetSS
> colnames(datasetT)[colnames(datasetT)=="2"] <- "公司代號" #更改datasetT股票代碼的欄位名稱
> m_data <- merge.data.frame(m_data_20160411,datasetT,by="公司代號",all=TRUE) #依照"公司代號"合併資料
> colnames(m_data)[colnames(m_data)=="2016-04-27 08:00:00"] <- "price.close" #更改欄位名稱為"price.close"
> write.table(m_data, file = "Desktop/R/m_data.csv", sep = ",")#將結果匯出成csv檔



最後關於寫程式有一些感觸,就是發覺人腦真的是很厲害,很多看似簡單在腦中的想法,對電腦來說往往要好多行程式才能完成…,但也發現其實電腦很單純,只要步驟、指令正確了,1 秒鐘不到電腦就可以完成任務。完全可以體會形容電腦是「超級稱職的奴隸」是怎麼一回事!

此外從剛開始對程式恐懼的心態,也發現先入為主的想法往往左右人面對事情的態度…,其實可以解決問題、可以應用就是最棒的方式!不一定要用很高深的 function、或很漂亮的寫法,即使很簡單的方法解決小問題,逐漸累積也可以建構出自己對程式語言的了解及用法,也會發現很多事情其實沒有想像中困難!因此 R 真的是很好學、很強大的工具,更因為是自由軟體,是大家智慧的累積!

所以要切入 R 真的一點都不難!網路上有許多對 R 的基礎教學,也建議可以買 1~2 本書研究一下,首先稍微了解 R 的資料格式、語法的邏輯等等,最重要的是從解決問題切入。這期間絕大時候都是這樣,先從問題出發,在網路上查找大量資料,中間偶而翻書了解一些特定語法。關於 R 的資料非常多,不用怕找不到答案!

以下推薦一些入門好用的教學網站:

沒有留言:

張貼留言