概述
和Python计算环境中的tushare
包一样,在R中我们使用quantmod
包接入第三方数据源,实现自定义量化分析平台的构建。
本文打算以陌陌的股票分析为背景,介绍如何通过quantmod
包构建专属的量化分析平台。
什么是quantmod
quantmod就是提供给宽客们使用的专业模块,Quantmod本身提供强大的数据接入能力,默认是雅虎财经的数据源,此外quantmod还以绘制专业的行情分析图表以及各种技术指标计算等功能著称,常常只要几行函数就能完成从数据获取和处理到画图的复杂功能,其工作效率之高让行家里手都觉得膛目结舌。
利用API读取在线行情
首先,我们利用雅虎财经的默认接口直接体验一下读取多只股票。
原理
利用API读取的方式,我们需要设定一个读取序列和对应的配置,获取行情函数getSymbols
类似于原生的assign
和get
函数,用函数的方式将变量名传入后完成变量的赋值。
基于这个原理,我写了一个Quote
函数来优化参数配置的体验。首先我们需要定义一个股票池序列,然后调用Quote
函数获取某只股票的行情返回数据。
下面以美股的陌陌、360和A股的平安银行为例:
代码
# 加载quantmod包
if(!require(quantmod)){
install.packages("quantmod")
}
# 股票行情匹配函数
Quote = function(code){
index = match(code,universes)
temp = lapply(universes,get)
return(temp[[index]])
}
# 基本配置
universes <<- c("000001.SZ","QIHU","MOMO")
from = "2015-01-04"
to = Sys.Date() # 结束时间设为当前日期
src= "yahoo" # 来源雅虎财经
# 行情加载 速度有点慢,耐心等待
quantmod::getSymbols(universes,from=from,to=to,src=src)
# 绘制行情
quantmod::chartSeries(Quote("MOMO"),up.col='red',dn.col='green',TA="addVo(); addADX();addMACD(); addSMA(n=10);addBBands(n=14,sd=2,draw=\"bands\")")
效果
利用CSV读取离线行情
接着,在离线模式或者网络访问缓慢的情况下,我们也可以用一些实现准备好的CSV文件来读取行情。
原理
分析底层数据结构后,我们知道quantmod
包读取后的数据格式是 xts 和 zoo,我们只需要将csv文件按一定的格式读取到内存后再进行相应变换,quantmod
强大的分析和作图能力就可以为我们所用。
zoo本身是一种时间序列格式,而xts则是在这基础上一种时间序列格式的加强版。在读取csv的时候,我们需要用首行确定header。在转化为zoo时,我们则需要首列来确定时间序列对应的时间。最后通过xts转化为可以被quantmod识别的xts时间序列对象。下面以平安银行为例:
代码
# 加载 zoo 时间序列包
library(zoo)
library(quantmod)
# 配置文件路径
filePath = '/Users/harryzhu/temp.csv'
# 读取CSV并转化时间格式
csv <- read.csv(filePath,header=TRUE,sep=",")
csv$LZ_GPA_QUOTE_TCLOSE <- as.POSIXct(as.character(csv$LZ_GPA_QUOTE_TCLOSE),tz="",format="%Y%m%d")
# 转化为zoo类型
temp = read.zoo(csv)
# 转化我xts类型
payh =as.xts(temp[,1]);colnames(payh)="Close"
# 制图
chartSeries(payh,name="000001.SZ")
# 添加MACD曲线
addMACD()
效果
指标计算
参考官方文档,我们知道,利用quantmod
和TTR
包,我们可以快速计算常见指标,下面是对应的计算列表。
指标名 | TTR 函数名 | quantmod 函数名 |
---|---|---|
威尔斯怀尔德移动方向指标 | ADX | addADX |
真实波幅 | ATR | addATR |
布林通道 | BBands | addBBands |
布林带宽 | N/A | addBBands |
百分比布林带 | N/A | addBBands |
顺势指标 | CCI | addCCI |
资金流动 | CMF | addCMF |
钱德动量指标 | CMO | addCMO |
双指数移动平均线 | DEMA | addDEMA |
离势价格偏离指数 | DPO | addDPO |
指数平滑移动平均线 | EMA | addEMA |
价格信封 | N/A | addEnvelope |
指数量权移动平均线 | EVWMA | addEVWMA |
期权期货到期 | N/A | addExpiry |
异同平均线 | MACD | addMACD |
动量 | momentum | addMomentum |
变动率 | ROC | addROC |
相对强弱指数 | RSI | addRSI |
转折点信号 | SAR | addSAR |
简单移动平均线 | SMA | addSMA |
随机动量指数 | SMI | addSMI |
三重平滑振荡指数 | TRIX | addTRIX |
成交量 | N/A | addVo |
加权移动平均法 | WMA | addWMA |
零延迟指数移动平均线 | ZLEMA | addZLEMA |
Web应用构建
参考 Rich Harken大神 制作的 shiny app以及源码,我们可以将上述参数暴露为网页上的选项,利用shiny的ajax和websocket的实时链接特性定制我们的chartSeries函数,达到通过选项实时作图的功能。
效果图
ui.R
library(shiny)
# 为应用程序定义UI,演示R包quantmod作图功能
shinyUI(
navbarPage("R quantmod Demonstration for Data Products Class", inverse=FALSE,
tabPanel("Documentation",
fluidPage(
verticalLayout(
h2("How to use the R quantmod Demonstration App", align="center"),
hr(),
h3("Directions"),
p("To get started using this application, you'll need to look at the banner line above titled \"R quantmod Demonstration for Data Products Class\" and click \"Demo\". This will take you to the application itself. You can click \"Documentation\" to return to this screen."),
p("The application begins by displaying the stock symbol \"^DJI\" which represents the Dow Jones Industrial Average. You can enter whatever stock symbol you would like (without the caret \"^\") and the graph will update accordingly. If your stock symbol is not valid - no graph will display"),
p("There are 3 other areas you can play with to change the current display for the selected stock:"),
tags$ol(tags$li("Date Range - you can change the date range selected for the price display"),
tags$li("Chart Theme - you can change how the graph is diplayed by choosing a supported theme"),
tags$li("Add Optional Technical Analysis Overlays - you can add additional chart items that will calculate some industry analytics and overlay them on the existing chart. Also a small warning here - some analytics require at least 3 months of data. If you don't have at least 3 months of data selected in the date range - you may get an error in display of the graph.")),
p("The graph will immediately respond to any changes you make. Feel free to experiment and explore this application based on R, Shiny, and the quantmod package for R!"),
br(),
h3("About the App"),
p("This application was written for the project in the Coursera course \"Developing Data Products\". It is an example of how to use the quantmod package within R, and what some of its capabilities are."),
p("The app starts by providing a user interface that collects a stock symbol, date range, and optional analytics to perform on the provided stock symbol. When anything changes in the user interface, the application reacts to the changes by updating the graphs calculated by the server code."),
tags$ol(tags$li("Input"), tags$ul(tags$li("Stock Symbol - textInput()"), tags$li("Date Range - dateRangeInput()"), tags$li("Chart Theme - radioButtions()"), tags$li("Technical Analysis - checkBoxGroupInput()")),
tags$li("Operation/Calculation", tags$ul(tags$li("Call to getSymbols() to retrieve data"), tags$li("preparation of variables for graphic display"))),
tags$li("Reactive Output"), tags$ul(tags$li("Call to render graph calculations within the quantmod libraries"), tags$li("Display of the rendered graph"))),
hr(),
h3("Application Source Code"),
h4("ui.R"),
pre(includeText("ui.R")),
h4("server.R"),
pre(includeText("server.R")),
p("Note: Some code used in this demo is based on the Shiny quantmod tutorial but was not copied wholesale. The work demonstrated above represents a significant departure from the tutorial.")
)
)
),
tabPanel("Demo",
fluidPage(
# 应用程序标题
#titlePanel("R quantmod Demonstration"),
# 为 quantmod 绘图功能提供参数入口的输入栏
sidebarLayout(
sidebarPanel(
textInput("stock", "Enter a stock symbol", value = "^DJI", width = "30%"),
# submitButton(text="Get Stock Quote"),
br(),
dateRangeInput("dtRange", "Date Range", start = Sys.Date()-90, end = NULL, min = NULL, max = NULL, format = "yyyy-mm-dd", startview = "month", weekstart = 0, language = "en", separator = " to ", width = NULL),
hr(),
flowLayout(radioButtons("theme", "Chart Theme:",
c("White" = "white",
"White Mono" = "white.mono",
"Black" = "black",
"Black Mono" = "black.mono",
"Beige" = "beige",
"WSJ"= "wsj"
)),
checkboxGroupInput("ta", "Add Optional Technical Analysis Overlays:",
c("Directional Movement Index" = "addADX()",
"Average True Range" = "addATR()",
"Bollenger Bands" = "addBBands()",
"Commodity Channel Index" = "addCCI()",
"Chaiken Money Flow" = "addCMF()",
"Chande Momentum Oscillator" = "addCMO()",
"Contract Expiration Bars" = "addExpiry()",
"De-trended Price Oscillator" = "addDPO()",
"Simple Moving Average" = "addSMA()",
"Expotential Moving Average" = "addEMA()",
"Weighted Moving Average" = "addWMA()",
"Double Expotential Moving Average" = "addDEMA()",
"Expotential Volume Weighted Moving Average" = "addEVWMA()",
"ZLEMA" = "addZLEMA()",
"Moving Average Convergence Divergence" = "addMACD()",
"Price Envelope" = "addEnvelope()",
"Relative Strength Index" = "addRSI()",
"Parabolic Stop and Reversal Indicator" = "addSAR()",
"Rate of Change" = "addROC()",
"Stochastic Momemtum Indicator" = "addSMI()"
))
)
),
# 作图
mainPanel(
plotOutput("distPlot", height="885px")
# ,textOutput("dispPrint")
)
)
)
)
)
)
server.R
library(shiny)
library(quantmod)
options("getSymbols.warning4.0"=FALSE)
# Define server logic required to draw a histogram
shinyServer(function(input, output) {
# Expression that generates the stock chart plot. The expression is
# wrapped in a call to renderPlot to indicate that:
#
# 1) It is "reactive" and therefore should re-execute automatically
# when inputs change
# 2) Its output type is a plot
sSymbol <- reactive({
tryCatch({
suppressWarnings(getSymbols(input$stock, from=input$dtRange[1], to=input$dtRange[2],
auto.assign = FALSE))
}, error = function(err) {
return(NULL)
})
})
output$distPlot <- renderPlot({
taStr<-"addVo()"
if (!is.null(input$ta)) {
for (ta in input$ta) {
taStr<-paste(taStr, paste(";", ta))
}
}
if(!is.null(sSymbol())) {
chartSeries(sSymbol(), name=input$stock, TA=taStr, theme=chartTheme(input$theme))
}
})
output$dispPrint <- renderPrint({
print(sSymbol())
})
})
尾注
综上所述,我们可以发现,利用quantmod、shiny包,我们可以快速实现各种姿势的行情获取以及常见的关键指标的计算和绘制,并且转化为实时的Web应用,建立一个专属的量化分析Web平台。
参考资料
作为分享主义者(sharism),本人所有互联网发布的图文均遵从CC版权,转载请保留作者信息并注明作者 Harry Zhu 的 FinanceR 专栏:https://segmentfault.com/blog/harryprince,如果涉及源代码请注明GitHub地址:https://github.com/harryprince。微信号: harryzhustudio
商业使用请联系作者。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。