相關套件


# instal.packages("quantmod")
library(quantmod)
library(kableExtra)

參考文獻


* quantmod
  - Introductions - a quick start to quantmod
  - Data Handling - quantmod and xts tools ← Updated!
  - Financial Charting with quantmod and TTR ← Finally done!
* Jason, 2017-06-23. Quantmod Tutorial:数据获取(一)
* Jason, 2017-06-24. Quantmod Tutorial:数据处理(二)
* Jason, 2017-06-26. Quantmod Tutorial:图形分析(三)
* 李東風, 2019. 金融時間數列分析講義, 1.7 quantmod 包的功能。

1 quantmod套件的介紹

套件quantmod可以輔助量化投資者(quantitative trader),發展或測試以統計為基礎的交易模型。該套件中並沒有新的統計方法,但有著完整的工具來做資料處理、視覺化,使得量化投資者能夠快速地探索及清楚的建立交易模型。

套件中最常用的兩個函數為loadSymbols()及chartSeries(),前者可以讓我們很容易抓取股票市場或金融資料庫的各種資料,後者則是可以畫出股票市場或金融資料分析中常見的各種圖形。底下就一一介紹。

2 函數 loadSymbols()

函數loadSymbols()讓我們能夠下載股票市場上的個股資料或金融資料庫的金融相關資料,底下是它的常用參數。

getSymbols(Symbols=NULL, 
           src="yahoo", 
           from="2007-01-01", to=Sys.Date(), 
           auto.assign=getOption('getSymbols.auto.assign',TRUE))

例子:抓取蘋果股票。

# 抓取頻果公司(市場代號為AAPL)的股票資料,資料會儲存在名稱為AAPL的物件中。
# getSymbols(Symbols="AAPL") # 以前的用法
AAPL = loadSymbols(Symbols="AAPL", 
                   auto.assign=FALSE) # 這一定要設定
str(AAPL)   #  xts 格式,這種格式的資料很重要,會另闢章節介紹
## An 'xts' object on 2007-01-03/2021-09-22 containing:
##   Data: num [1:3707, 1:6] 3.08 3 3.06 3.07 3.09 ...
##  - attr(*, "dimnames")=List of 2
##   ..$ : NULL
##   ..$ : chr [1:6] "AAPL.Open" "AAPL.High" "AAPL.Low" "AAPL.Close" ...
##   Indexed by objects of class: [Date] TZ: UTC
##   xts Attributes:  
## List of 2
##  $ src    : chr "yahoo"
##  $ updated: POSIXct[1:1], format: "2021-09-23 10:18:56"
head(AAPL)  # 注意列名稱為日期
##            AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume AAPL.Adjusted
## 2007-01-03  3.081786  3.092143 2.925000   2.992857  1238319600      2.569716
## 2007-01-04  3.001786  3.069643 2.993571   3.059286   847260400      2.626753
## 2007-01-05  3.063214  3.078571 3.014286   3.037500   834741600      2.608047
## 2007-01-08  3.070000  3.090357 3.045714   3.052500   797106800      2.620926
## 2007-01-09  3.087500  3.320714 3.041071   3.306071  3349298400      2.838647
## 2007-01-10  3.383929  3.492857 3.337500   3.464286  2952880000      2.974493
AAPL.df = as.data.frame(AAPL) # 轉成較熟悉的資料框格式。
str(AAPL.df)
## 'data.frame':    3707 obs. of  6 variables:
##  $ AAPL.Open    : num  3.08 3 3.06 3.07 3.09 ...
##  $ AAPL.High    : num  3.09 3.07 3.08 3.09 3.32 ...
##  $ AAPL.Low     : num  2.92 2.99 3.01 3.05 3.04 ...
##  $ AAPL.Close   : num  2.99 3.06 3.04 3.05 3.31 ...
##  $ AAPL.Volume  : num  1.24e+09 8.47e+08 8.35e+08 7.97e+08 3.35e+09 ...
##  $ AAPL.Adjusted: num  2.57 2.63 2.61 2.62 2.84 ...
head(AAPL.df)
##            AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume AAPL.Adjusted
## 2007-01-03  3.081786  3.092143 2.925000   2.992857  1238319600      2.569716
## 2007-01-04  3.001786  3.069643 2.993571   3.059286   847260400      2.626753
## 2007-01-05  3.063214  3.078571 3.014286   3.037500   834741600      2.608047
## 2007-01-08  3.070000  3.090357 3.045714   3.052500   797106800      2.620926
## 2007-01-09  3.087500  3.320714 3.041071   3.306071  3349298400      2.838647
## 2007-01-10  3.383929  3.492857 3.337500   3.464286  2952880000      2.974493

常用參數的解釋:

  • Symbols="" :字串。設定所要抓取的股票代號,如蘋果的代號為“AAPL”,台股的台積電為“2230.TW”。
  • src=“yahoo”:字串。設定資料的來源,內定是yahoo。
    • src=“FRED”:設定資料來源為美國聯邦數據資料庫。
    • src=“oanda”:設定資料來源為萬達公司資料庫。
    • src=“google”:設定資料來源為google公司資料庫。但目前已經不提供。
  • from=“2007-01-01”:日期格式的字串。設定資料抓取的起始日期。內定是“2007-01-01”。
  • to=Sys.Date():日期格式的字串。設定資料抓取的結束日期。內訂為當天。
  • auto.assign=TRUE:邏輯值。設定抓到的資料要指定給哪一個物件。
    • 內定是『TRUE』,即指定給Symbols所設定的名稱。 – 如getSymbols(Symbols=“AAPL”),則抓回後的資料儲存在名稱為AAPL的物件中。
    • 若『auto.assign=FALSE』,則會將資料傳回到主控台,必須設定接收物件名稱。 – 如『q1 = getSymbols(Symbols=“2330.TW”, auto-assign=FALSE)』,則會將台積電的資料儲存在名稱為q1的物件中。 – 注意:若使用『auto.assign=FALSE』這種方式,2330.TW內就不會有資料,所以一定要設定接收物件。否則只會在螢幕上秀出資料。
  • 資料欄位:若是股票資料,基本上會抓取底下幾欄資料(這樣的資料一般稱為OHLC資料):
    • 日期為列名稱。
    • Open:當天開盤價。
    • High:當天最高價。
    • Low:當天最低價。
    • Close:當天收盤價。
    • Volumn:當天交易量。
    • Adjusted:調整後股價。
  • 抓取到資料,其格式為時間數列的xts格式。可利用as.data.frame()函數轉換成我們較熟悉的資料框格式。 用 kableExtra 輸出會較漂亮。
head(AAPL.df) %>%
  kableExtra::kable() %>%
  kableExtra::kable_styling() %>%
  scroll_box(width = "800px", height = "300px")
AAPL.Open   AAPL.High   AAPL.Low    AAPL.Close  AAPL.Volume AAPL.Adjusted
2007-01-03  3.081786    3.092143    2.925000    2.992857    1238319600  2.569716
2007-01-04  3.001786    3.069643    2.993571    3.059286    847260400   2.626753
2007-01-05  3.063214    3.078571    3.014286    3.037500    834741600   2.608047
2007-01-08  3.070000    3.090357    3.045714    3.052500    797106800   2.620926
2007-01-09  3.087500    3.320714    3.041071    3.306071    3349298400  2.838647
2007-01-10  3.383929    3.492857    3.337500    3.464286    2952880000  2.974493

例子:抓取長榮的2020年股票資料。

長榮的股票代號是2603.TW。若是如下的寫法,取回的資料會儲存在名稱為2603.TW的物件中。

# 
TW2603 = loadSymbols(Symbols="2603.TW", 
                     from="2020-01-01", 
                     to="2020-12-31",
                     src="yahoo", 
                   auto.assign=FALSE)
head(TW2603)

例子:一次抓數檔股票資料。 抓取長榮(2603.TW)及強生(4747.TWO)的 2019 年股票資料。

# 一次抓取數種股票時,不能使用『`auto.assign=FALSE`』
# 資料自動儲存在Symbols所指定的物件上。
loadSymbols(Symbols=c("2603.TW", "4747.TWO"), 
           from="2019-01-01", to="2019-12-31",
           src="yahoo", 
           auto.assign=TRUE)
## [1] "2603.TW"  "4747.TWO"
# 此時只能利用 get() 方法,將資料移轉到正常變數名稱的物件上
TW2330 = `2603.TW`; head(TW2603)
##           2603.TW.Open 2603.TW.High 2603.TW.Low 2603.TW.Close 2603.TW.Volume
##2019-01-02     11.96443     11.96443    11.76585      11.81550        5148552
##2019-01-03     11.81550     11.91479    11.71621      11.76585        5084558
##2019-01-04     11.71621     11.71621    11.31905      11.51763       12436011
##2019-01-07     11.71621     11.86514    11.61692      11.86514        7898152
##2019-01-08     11.86514     11.91479    11.76585      11.76585        4397822
##2019-01-09     11.86514     12.01408    11.86514      11.96443        9451330
##           2603.TW.Adjusted
##2019-01-02         11.59036
##2019-01-03         11.54166
##2019-01-04         11.29816
##2019-01-07         11.63906
##2019-01-08         11.54166
##2019-01-09         11.73645
TWO4747 = get("4747.TWO"); head(TWO4747)
##            4747.TWO.Open 4747.TWO.High 4747.TWO.Low 4747.TWO.Close
## 2019-01-02         38.85         39.00        38.85          39.00
## 2019-01-03         39.00         39.00        39.00          39.00
## 2019-01-04         39.00         39.05        39.00          39.00
## 2019-01-07         39.05         39.05        39.00          39.00
## 2019-01-08         39.05         39.25        39.00          39.25
## 2019-01-09         39.25         39.40        39.20          39.40
##            4747.TWO.Volume 4747.TWO.Adjusted
## 2019-01-02           14000          34.04548
## 2019-01-03           40000          34.04548
## 2019-01-04            8000          34.04548
## 2019-01-07           11000          34.04548
## 2019-01-08           34000          34.26372
## 2019-01-09           31625          34.39467

從FRED經濟資料庫下載資料

美國聯邦經濟數據資料庫(FRED)有高達11000種數據可以下載。

# 下載日本對美元匯率日數據
DEXJPUS <- loadSymbols("DEXJPUS", src="FRED", auto.assign=FALSE)
tail(DEXJPUS)
##            DEXJPUS
## 2021-09-10  109.93
## 2021-09-13  109.94
## 2021-09-14  109.66
## 2021-09-15  109.40
## 2021-09-16  109.67
## 2021-09-17  109.94
# 下載美國失業率月數據
UNRATE <- loadSymbols("UNRATE", src="FRED", auto.assign=FALSE)
tail(UNRATE)
##            UNRATE
## 2021-03-01    6.0
## 2021-04-01    6.1
## 2021-05-01    5.8
## 2021-06-01    5.9
## 2021-07-01    5.4
## 2021-08-01    5.2

3 函數 chartSeries()

函數chartSeries()可將loadSymbols()所傳回的物件或轉換成的資料框,畫成股票市場的時間數列圖。相關常用參數如下:

chartSeries(x,
            type = c("auto", "candlesticks", "matchsticks", "bars","line"), 
            subset = NULL,
            name = NULL,
            theme = chartTheme("black"),
            plot=TRUE,
            up.col, dn.col,
            TA = 'addVo()')
  • x:loadSymbols()所傳回的物件或轉換成的資料框。
  • type="":字串,指定顯示圖形的種類。
    • type=“candlesticks”:畫K線圖。
    • type=“matchsticks”:K線圖的另一種表法。
    • type=“bars”:K線圖的另一種表法。
    • type=“lines”:收盤價的曲線圖。
  • subset=NULL:指定繪圖的部分資料。
    • subset=“first 1 day”
    • subset=“first 10 days”
    • subset=“last 10 days”
    • subset=“first 2 months”
    • subset=“last 2 months”
    • subset=“last 2 weeks”
    • subset=“2019-01::2019-03”
  • name=NULL:字串。指定圖上的股票名稱。
  • theme=chartTheme(“black”):顏色字串。設定背景顏色,內定是黑色。
  • up.col:顏色字串。設定上漲資料的顏色。
  • dn.col:顏色字串。設定下跌資料的顏色。
  • plot=TRUE:邏輯值。設定是否顯示圖形。
  • TA = ‘addVo()’:字串向量。指定加在圖上的其他圖形,內定是成交量。
    • 若是設成TA=NULL,則不會附加圖形在原圖上面。

例子:畫出2021年一月至今,長榮股票的時間數列圖。

TW2603 = loadSymbols(Symbols="2603.TW", 
                     from="2021-01-01", 
                     auto.assign=FALSE)
#
chartSeries(TW2603)



# 注意左上角文字的變化
chartSeries(TW2603, name="長榮")



# 畫出部分資料
chartSeries(TW2603, name="長榮", subset="2021-04-01::2021-04-30")



例子:學習chartSeries()的各種樣式(type)的圖形。

chartSeries(TW2603, name="長榮auto", type="auto", theme=chartTheme("white"),
            subset="2021-04-01::2021-04-30")



chartSeries(TW2603, name="長榮candle", type="candlesticks", theme=chartTheme("white"), 
            subset="2021-04-01::2021-04-30")



chartSeries(TW2603, name="長榮match", type="matchsticks", theme=chartTheme("white"), 
            subset="2021-04-01::2021-04-30")



chartSeries(TW2603, name="長榮bars", type="bars", theme=chartTheme("white"), 
            subset="2021-04-01::2021-04-30")



chartSeries(TW2603, name="長榮line", type="line", theme=chartTheme("white"), 
            subset="2021-04-01::2021-04-30")



K線圖


K線圖(candlesticks)。

#
head(TW2603)
##           2603.TW.Open 2603.TW.High 2603.TW.Low 2603.TW.Close 2603.TW.Volume 2603.TW.Adjusted
##2021-01-04        42.35        44.75       42.15         44.75      513626515         43.89732
##2021-01-05        45.00        45.50       43.15         45.50      533867334         44.63303
##2021-01-06        44.75        46.20       42.25         42.55      564149052         41.73924
##2021-01-07        43.30        43.80       38.30         38.45      775697280         37.71736
##2021-01-08        38.50        40.75       37.20         40.30      548579386         39.53211
##2021-01-11        41.50        42.80       40.60         42.65      408138044         41.83733
#
tail(TW2603)
##           2603.TW.Open 2603.TW.High 2603.TW.Low 2603.TW.Close 2603.TW.Volume 2603.TW.Adjusted
##2021-09-15        124.5        126.0       119.5         124.5      190195692            124.5
##2021-09-16        125.5        125.5       123.5         124.0       71577866            124.0
##2021-09-17        125.0        129.0       124.0         128.0      115545644            128.0
##2021-09-22        124.0        127.5       124.0         125.0       86877716            125.0
##2021-09-23        128.0        129.5       127.0         127.5       78894197            127.5
##2021-09-24        129.5        135.5       129.5         134.0      187275147            134.0
#
chartSeries(TW2603, name="長榮", 
            type="candlesticks", 
            theme=chartTheme("white"), 
            subset="2021-04-01::2021-04-30")



在K線圖中,

  • 每一個長條圖形都會表示出當天的開盤、收盤、最高與最低價。
  • 長條圖形中的箱型兩端的Y軸為開盤價與收盤價。
    • 不一定開盤價在上面或下面,與顏色有關。
  • 長條圖形(包含相形與往上往下線條)的最高與最低表示當天的最高價與最低價。
  • 開低收高稱為陽線,以綠色表示;開高收低稱為陰線,以紅色表示。
  • 四月1日是陰線,表示開高收低。最高價為開盤價,收盤價比最低價高一些。
  • 四月8日是陽線,表示開低收高。最高價為收盤價,開盤價比最低價高一些。

例子:將股票資料圖形儲存成圖檔

可以利用jpeg()與dev.off()兩個函數,將圖形儲存成圖檔。

  • jpeg(filename, width=480, height=480):將後續的圖形儲存成jpeg格式的圖檔,且不顯示在螢幕上。
    • filename=:字串。設定要儲存的檔案名稱。
    • width=480:數值。設定圖檔的寬度。內訂為480。
    • height=480:數值。設定要儲存的圖檔長度。內訂為480。
  • dev.off():關閉存檔的動作。
  • 若filename沒有設定目錄,則圖檔會儲存在工作目錄下。所以,在存檔前,先確認工作目錄在哪裡。
# 抓取資料
#TW2330 = getSymbols(Symbols="2330.TW", from="2019-01-01", auto.assign=FALSE)
#畫出時間數列圖,並儲存
getwd() # 顯示出目前的工作目錄
jpeg("tw2330.jpg", width=800, height=600)
chartSeries(TW2330, name="TSMC", theme=chartTheme("white"),
           up.col="red", dn.col="black")
dev.off() # 察看在工作目錄下是否有該圖檔。

3.1 在圖形上加上其他技術指標

我們可以利用參數TA=""指定加上一些技術指標,也可以利用函數在原圖上再畫上技術指標。

利用參數TA=""指定加上一些技術指標

# 抓取資料
TW2603 = getSymbols(Symbols="2603.TW", from="2021-01-01", auto.assign=FALSE)
# 加了TA=NULL,就沒有出現下面成交量的圖。
chartSeries(TW2603, name="長榮", type="candlesticks", theme=chartTheme("white"),
            TA=NULL)



# 添加5日移動平均線到圖上。
chartSeries(TW2603, name="長榮", type="candlesticks", theme=chartTheme("white"),
            TA="addSMA(5)")



# 添加5日移動平均線及成交量到圖上。
chartSeries(TW2603, name="長榮", type="candlesticks", theme=chartTheme("white"),
            TA="addSMA(5); addVo()")



利用函數在原圖上再畫上技術指標

# 抓取資料
TW2603 = getSymbols(Symbols="2603.TW", from="2021-01-01", auto.assign=FALSE)
# 加了TA=NULL,就沒有出現下面成交量的圖。
chartSeries(TW2603, name="長榮", type="candlesticks", theme=chartTheme("white"),
            TA=NULL)



# 添加5日移動平均線到圖上。
addSMA(5)



# 添加5日移動平均線到圖上。
addVo()



底下列出所提供的各種技術指標名稱及其相關函數。最後第二欄是函數在套件TTR中的名稱,最後一欄則是函數在套件quantmod中的名稱。

Indicator TTR Name quantmod Name Welles Wilder’s Directional Movement Indicator ADX addADX Average True Range ATR addATR Bollinger Bands BBands addBBands Bollinger Band Width N/A addBBands Bollinger %b N/A addBBands Commodity Channel Index CCI addCCI Chaiken Money Flow CMF addCMF Chande Momentum Oscillator CMO addCMO Double Exponential Moving Average DEMA addDEMA Detrended Price Oscillator DPO addDPO Exponential Moving Average EMA addEMA Price Envelope N/A addEnvelope Exponential Volume Weigthed Moving Average EVWMA addEVWMA Options and Futures Expiration N/A addExpiry Moving Average Convergence Divergence MACD addMACD Momentum momentum addMomentum Rate of Change ROC addROC Relative Strength Indicator RSI addRSI Parabolic Stop and Reverse SAR addSAR Simple Moving Average SMA addSMA Stocastic Momentum Index SMI addSMI Triple Smoothed Exponential Oscillator TRIX addTRIX Volume N/A addVo Weighted Moving Average WMA addWMA Williams %R WPR addWPR ZLEMA ZLEMA addZLEMA

畫出鴻海股價的月資料,並增加幾個技術指標。

stockID = "2317"
stockType = "TW"
stockName = "鴻海"

stockSymbol = paste(stockID, ".", stockType, sep="")
#

stockData = loadSymbols(Symbols=stockSymbol, 
           from="2010-01-01",src="yahoo",
           auto.assign=FALSE)
## Warning: 2317.TW contains missing values. Some functions will not work if
## objects contain missing values in the middle of the series. Consider using
## na.omit(), na.approx(), na.fill(), etc to remove or replace them.
stockData.na= na.omit(stockData)

# 增加製表時間在圖上
str=paste(stockSymbol, Sys.time(), sep="")
chartSeries(to.monthly(stockData.na), name=str, 
            type="auto", 
            theme=chartTheme("white"),
            TA="addVo(); addSAR(); addRSI(); addSMA(3)",
            up.col="green", dn.col="red")



4 其他計算功能

4.1 轉換各種時間間隔

可以利用函數,將日資料轉換成各種時間間隔(週、月、季)資料再畫圖。

  • to.weekly()
  • to.monthly()
  • to.quarterly()
  • to.weekly()
  • to.yearly()
  • to.daily()
  • to.hourly()
  • to.minutes()
  • to.minutes3()
  • to.minutes5()
  • to.period():最具彈性的函數。
  • “seconds”, “minutes”, “hours”, “days”, “weeks”, “months”, “quarters”, and “years”

資料時間間隔的轉換

# 抓取資料
TW2603 = loadSymbols(Symbols="2603.TW", 
                     from="2010-01-01", 
                     auto.assign=FALSE)
## Warning: 2603.TW contains missing values. Some functions will not work if
## objects contain missing values in the middle of the series. Consider using
## na.omit(), na.approx(), na.fill(), etc to remove or replace them.
# 剔除遺失值
TW2603.na = na.omit(TW2603)

# 轉換成月資料再畫圖
chartSeries(to.monthly(TW2603.na), name="長榮", 
            type="candlesticks", theme=chartTheme("white"))



# 轉換成季資料再畫圖
chartSeries(to.quarterly(TW2603.na), name="長榮", 
            type="candlesticks", theme=chartTheme("white"))



# period 的寫法
chartSeries(to.period(TW2603.na, period="weeks"), name="長榮", 
            type="candlesticks", theme=chartTheme("white"))



4.2 更多的函數

quantmod中提供許多管理OHLC數據的函數。底下簡介這些函數:

若x是一個OHLC數據:

  • Op(x), Hi(x), Lo(x), Cl(x), Vo(x), Ad(x) 分别提取出開盤、最高、最低、收盤、成交量、調整收盤價。
  • is.OHLC(x)判斷是否OHLC數據。
  • has.OHLC(x)判斷是否包含OHLC數據
  • has.xxx(x)判斷是否有各個成分(xxx分别取Op, Hi, Lo, Cl, Vo, Ad)。
  • seriesHi(x)求每個分量的最大值
  • seriesLo(x)求每個分量的最小值。

對每個時間點:

  • OpCl(x)計算開盤價到收盤價的變化率;
  • HiCl(x)計算最高價到收盘價的變化率;
  • LoCl(x)計算最低價到收盘價的變化率;
  • LoHi(x)計算最低價到最高價的變化率;
  • OpHi(x)計算開盤價到最高價的變化率;
  • OpLo(x)計算開盤價到最低價的變化率。
  • OpOp(x)計算前後兩個時間點的開盘價的變化率, ClCl(x)計算前後两個時間點的收盤價的變化率。 也是簡單收益率。
# 抓取資料
TW2603 = loadSymbols(Symbols="2603.TW", 
                     from="2021-01-01", 
                     auto.assign=FALSE)
## Warning: 2603.TW contains missing values. Some functions will not work if
## objects contain missing values in the middle of the series. Consider using
## na.omit(), na.approx(), na.fill(), etc to remove or replace them.
# 剔除遺失值
TW2603.na = na.omit(TW2603)

# 抓取各欄位(分量)的最大值
seriesHi(TW2603.na)
##            2603.TW.Open 2603.TW.High 2603.TW.Low 2603.TW.Close 2603.TW.Volume 2603.TW.Adjusted
##2021-07-06        218.5          233         212           224      526356651         219.7318
# 計算開盤收盤價差變化率
q1 = OpCl(TW2603.na)
q1[1:10]
##           OpCl.TW2603.na
##2021-01-04    0.056670652
##2021-01-05    0.011111111
##2021-01-06   -0.049162034
##2021-01-07   -0.112009194
##2021-01-08    0.046753221
##2021-01-11    0.027710892
##2021-01-12   -0.098245637
##2021-01-13   -0.011873377
##2021-01-14    0.007946993
##2021-01-15   -0.098684211
# 抓取各欄位資料
q2 = HLC(TW2603.na)
q2[1:10,]
##           2603.TW.High 2603.TW.Low 2603.TW.Close
##2021-01-04        44.75       42.15         44.75
##2021-01-05        45.50       43.15         45.50
##2021-01-06        46.20       42.25         42.55
##2021-01-07        43.80       38.30         38.45
##2021-01-08        40.75       37.20         40.30
##2021-01-11        42.80       40.60         42.65
##2021-01-12        42.75       38.50         38.55
##2021-01-13        39.15       37.10         37.45
##2021-01-14        39.50       37.70         38.05
##2021-01-15        38.00       34.25         34.25