本文的作者是某国际知名制药公司在华研究中心的工程师,今年8月他们部门接受了我们的R语言培训,这篇文章就是培训后他做的presentation.

目标:通过数据的股票代码获取中国股票信息

这个项目以利用shiny获取和展示股票信息为目标。

数据准备

新浪是获取中国股票信息源数据的理想场所,我们可以利用下面的代码来得到数据,然而,sina.com还能够提供准确到分钟的精确信息。

1
2
3
4
5
6
library(RCurl)
library(XML)
library(plyr)
raw <- getURL("http://biz.finance.sina.com.cn/stock/flash_hq/kline_data.php?symbol=sh600000&end_date=20121231&begin_date=20111231")
raw
do.call(rbind, xmlToList(raw))

但是来自新浪的数据格式并不规范,我们需要花大量的时间去清洗和整理。我的主要目标是利用shiny来展示股市数据,因此我使用雅虎为数据源然后直接使用quantmod程序包来提取数据。

Server.R

下面服务终端代码。代码非常简单。让人吃惊的是R居然能如此完美的处理这一大堆股票数据。

1
2
3
if (!require(quantmod)) { 
  stop("This app requires the quantmod package. To install it, run 'install.packages(\"quantmod\")'.\n") 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Download data for a stock if needed, and return the data
require_symbol <- function(symbol, envir = parent.frame()) {
  if (is.null(envir[[symbol]])) {
    envir[[symbol]] <- getSymbols(symbol, auto.assign = FALSE)
  }
  
  envir[[symbol]]
}


shinyServer(function(input, output) {  
  # Create an environment for storing data
  symbol_env <- new.env()
  
  # Make a chart for a symbol, with the settings from the inputs
  make_chart <- function(symbol) {
    symbol_data <- require_symbol(symbol, symbol_env)
    #TA_STR <- paste0()
    chartSeries(symbol_data,
                name       = symbol,
                type       = input$chart_type,
                subset     = paste("last", input$time_num, input$time_unit),
                #log.scale = input$log_y,
                theme      = "white")
  }
  
  output$plot_1 <- renderPlot({ make_chart(input$stock1) })
  output$plot_2 <- renderPlot({ make_chart(input$stock2) })
  output$plot_3 <- renderPlot({ make_chart(input$stock3) })
  output$plot_4 <- renderPlot({ make_chart(input$stock4) })
  output$plot_5 <- renderPlot({ make_chart(input$stock5) })
})

ui.R

接着是前端代码,它主要包括前端组件的构建。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
shinyUI(pageWithSidebar(
  headerPanel("炒股神器 发财大计"),  
  sidebarPanel(
    wellPanel(
      p(strong("股票")),
      textInput(inputId = "stock1", label = "股票1"),
      textInput(inputId = "stock2", label = "股票2"),
      textInput(inputId = "stock3",  label = "股票3"),
      textInput(inputId = "stock4", label = "股票4"),
      textInput(inputId = "stock5", label = "股票5")), 
    selectInput(inputId = "chart_type",
                label = "图形",
                choices = c("蜡烛图" = "candlesticks",
                            "火柴图" = "matchsticks",
                            "柱形图" = "bars",
                            "线型图" = "line")),    
    wellPanel(
      p(strong("日期范围 (从现在起倒推)")),
      sliderInput(inputId = "time_num",
                  label = "时间个数",
                  min = 1, max = 24, step = 1, value = 6),
      
      selectInput(inputId = "time_unit",
                  label = "时间单位",
                  choices = c("日" = "days",
                              "周" = "weeks",
                              "月" = "months",
                              "年" = "years"),
                  selected = "Months"))    
    #checkboxInput(inputId = "log_y", label = "log y axis", value = FALSE)
  ),  
  mainPanel(
    conditionalPanel(condition = "input.stock1",
                     br(),
                     div(plotOutput(outputId = "plot_1"))),    
    conditionalPanel(condition = "input.stock2",
                     br(),
                     div(plotOutput(outputId = "plot_2"))),    
    conditionalPanel(condition = "input.stock3",
                     br(),
                     div(plotOutput(outputId = "plot_3"))),    
    conditionalPanel(condition = "input.stock4",
                     br(),
                     div(plotOutput(outputId = "plot_4"))),    
    conditionalPanel(condition = "input.stock5",
                     br(),
                     plotOutput(outputId = "plot_5"))
  )
)
)

最终生成的shiny app的效果是这样的:

shiny效果图

结论

Shiny十分强大,它就像是我信息部的同事一样能应用各种各样的工具来处理数据,然后展现给科学家们查看。以前我常常提出这样的问题,怎么样才能为我整理好的数据建立一个规范的端口,然后让用户在各个方向上灵活地分析。Shiny和R恰好是一个好的解决方法,但是我依然需要找到一个将shiny应用于用户的便捷方法。

我衷心感谢SupStat团队,他们为我上了一堂生动的课程,使我能应用新的工具来加速我的数据处理工作。