
利用eval函數計算多個移動平均線指標
前言
我們通常會利用dplyr
套件搭配TTR
套件的SMA
函數來計算移動平均線指標。舉例來說,我們要計算5日、10日及20日移動平均線,則在R裡面的寫法為:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
stockData <- stockData %>% | |
mutate(MA5 = SMA(close, 5), | |
MA10 = SMA(close, 10), | |
MA20 = SMA(close, 20)) |
但上述的寫法有一個缺點,如果我們計算更多不同天期的移動平均線,例如10日、20日、30日…至100日移動平均線,這樣就需要寫10行的SMA函數才行。程式碼會變得很複雜,而且使用者還要一直複製貼上程式碼,並修改參數,這顯然是很麻煩的事情。
這篇文章主要是來解決上述問題,我們可以透過eval函數來處理這個問題。
eval函數
eval
函數是R軟體的內建函數,主要是將一段文字以命令的方式讓程式去執行,以下我們做一個簡單的範例。假設說我們想要產生一個變數叫做a,並且指派數值1給a。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## 變數a指派為1 | |
# 方法1: 一般寫法 | |
a <- 1 | |
# 方法2: eval函數寫法 | |
string <- "a <- 1" | |
eval(parse(text = string)) |
上述的兩個不同方法,其結果都會讓變數a為1。由於eval
函數將文字變成命令送到程式,因此我們可以透過修改字串的方式,並搭配迴圈,來計算不同天期的移動平均線。
資料來源
資料來源部分,我們使用tidyqunat
套件,這個套件整合quantmode
套件與tidyverse
套件。利用此套件的tq_get
函數至Yahoo Finance下載台股大盤股價資料,做為此次的範例資料集。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library(tidyquant) | |
stockData <- c("^TWII") %>% | |
tq_get(get = "stock.price") %>% | |
na.omit() %>% | |
select(date, close) |
以下為sockData
的資料內容,我們只取出日期及收盤價資訊:
## # A tibble: 2,573 x 2
## date close
## <date> <dbl>
## 1 2008-01-02 8323.05
## 2 2008-01-03 8184.20
## 3 2008-01-04 8221.10
## 4 2008-01-07 7883.37
## 5 2008-01-08 7962.91
## 6 2008-01-09 8085.06
## 7 2008-01-10 8057.27
## 8 2008-01-11 8029.31
## 9 2008-01-14 8173.41
## 10 2008-01-15 8428.84
## # ... with 2,563 more rows
快速計算MA
假設我們要計算5日、10日、20日、60日及90日移動平均線,則寫法為:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
maDays <- c(5, 10, 20, 60, 90) | |
for(ix in maDays){ | |
evalCommand <- paste0("stockData <- stockData %>% mutate(MA",ix," = SMA(close, ", ix,"))") | |
eval(parse(text=evalCommand)) | |
} |
可以看到evalCommand
的文字內容,就是在執行mutate
函數搭配SMA
函數計算移動平均線指標。而SMA
函數內的日數參數,則變為for
迴圈的對象,因此每次for
迴圈就會去新增一個新的移動平均線欄位。
執行上述程式碼後,即會得到各天期的移動平均線:
## # A tibble: 2,573 x 7
## date close MA5 MA10 MA20 MA60 MA90
## <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2008-01-02 8323.05 NA NA NA NA NA
## 2 2008-01-03 8184.20 NA NA NA NA NA
## 3 2008-01-04 8221.10 NA NA NA NA NA
## 4 2008-01-07 7883.37 NA NA NA NA NA
## 5 2008-01-08 7962.91 8114.926 NA NA NA NA
## 6 2008-01-09 8085.06 8067.328 NA NA NA NA
## 7 2008-01-10 8057.27 8041.942 NA NA NA NA
## 8 2008-01-11 8029.31 8003.584 NA NA NA NA
## 9 2008-01-14 8173.41 8061.592 NA NA NA NA
## 10 2008-01-15 8428.84 8154.778 8134.852 NA NA NA
## # ... with 2,563 more rows
只要將想要計算的移動平均線日數放入maDays
向量,透過for
迴圈及eval
函數運作就可解決我們的問題,不用寫太多相似的程式碼。
範例完整程式碼
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library(tidyquant) | |
# 下載資料 | |
stockData <- c("^TWII") %>% | |
tq_get(get = "stock.price") %>% | |
na.omit() %>% | |
select(date, close) | |
# 計算不同天期之移動平均線 | |
maDays <- c(5, 10, 20, 60, 90) | |
for(ix in maDays){ | |
evalCommand <- paste0("stockData <- stockData %>% mutate(MA",ix," = SMA(close, ", ix,"))") | |
eval(parse(text=evalCommand)) | |
} |