R shiny stock analysis

December 16, 2017
By

(This article was first published on R – Artificial thoughts, and kindly contributed to R-bloggers)

Introduction

This post we deploy our own R-shiny app.

  1. You can select a stock
  2. The app fetches the data, does some number crunching and plots the results

The source code is on github.

Bear in mind that I might not run the demo-server indefinitely, or that it might not be responsive, so first here’s a screenshot:

Here is the demo:

If you want to see this in a full page view here’s the link: https://arthought.shinyapps.io/15_stock_analysis/

Remark: This application might not be available as there is a fairly tight limit on the number of hours the free-plan shinyapps.io based apps will run. There is another server accessible using this link.

 

There are various options as to how you can use Shiny server:

  1. You can host your own server, instructions are here and then here
  2. You can sign up at https://www.shinyapps.io/

There are pros and cons to either, here’s a summary:

  Own server https://www.shinyapps.io/
Complexity
Cost
Scalability

For this post we choose the free account option of https://www.shinyapps.io , which is limited to 5 Applications and 25 Active Hours (per month).

We then use an iframe to reference the shiny app in this post (as shown in the previous post).

Discussion of the code

In the typical shiny app there are two files, one representing the “frontend”/user interface called ui.R, and one representing the “backend” called server.R.  The ui.R defines the user interface widgets, the server.R defines e.g. calculations or plots.

So let’s briefly discuss these two components in our app.

The “frontend”/user interface called ui.R

In the ui.R file we have the following:

  • We download the current DAX components from a Wikipedia page, using the htmltab library : https://en.wikipedia.org/wiki/DAX
    ## Initialization
      library(htmltab)
      {## get dax components names
        
        tabledata.url <- "https://en.wikipedia.org/wiki/DAX"
        DAX.components = htmltab(doc = tabledata.url, which=3, rm_nodata_cols = F)
        DAX.components.Symbol = paste0( DAX.components[['Ticker symbol']], '.DE')
        names(DAX.components.Symbol) =  paste0( DAX.components[['Company']], ' (', DAX.components[['Prime Standard industry group']] ,')' )
        
      } # {## get dax components names
    # end: ## Initialization
  • This list is fed into a selectInput box named DAX stock
    selectInput("stock_id", "DAX Stock:",
                    DAX.components.Symbol),

    There is also a sliderInput

    # Specification of range within an interval
        helpText("Specify Range (in % of data)"),
        sliderInput("range", "Range:",
                    min = 0, max = 100, value = c(0,100))
  • Once you, the user, select a stock this information is passed to server.R which defines that the data is downloaded from yahoo, analysed and shown in the plot; the server.R file is discussed below. However the way these plots are presented is defined in the ui.R. The definitions in the ui.R use a hierarchy of panels, in this case the hierarchy is mainPanel,tabsetPanel and tabPanel :
    # Show a hierarchy of panels with plots 
      mainPanel(
        
        tabsetPanel(
          tabPanel(
            "Timeseries", 
              plotOutput("timeseries")
            ),
          
          tabPanel("Boxplot",
                   plotOutput("boxplot")
          ),
          
          tabPanel("Histograms",
              plotOutput("histogram.stockdata"),
              plotOutput("histogram.GDAXI")
          ) 
        )
      )

     

    The “backend” called server.R

In the server.R we have the following

  • We download the data for the DAX index, using the getSymbols function from the quantmod package.
    ## Intialize DAX data
    AdjustedPrice = 6
    .GDAXI = getSymbols('^GDAXI', warnings = FALSE, auto.assign = FALSE)
    GDAXI = na.fill(.GDAXI, fill = "extend")[,AdjustedPrice, drop=FALSE]
  • The input “stock_id” from the selectInput box in the ui.R (=input$stock_id)  is fed into what’s called a reactive expression.
    The reactive expression is “informed” if and when any input has changed. When this happens the expression is recalculated, i.e. it reacts. In our case the reactive expression is the following function:

    # Return the requested dataset
      datasetInput <- reactive({
        
        
         .stockdata = getSymbols(input$stock_id, warnings = FALSE, auto.assign = FALSE)
         stockdata = na.fill(.stockdata, fill = "extend")[, AdjustedPrice, drop=FALSE]
         
         stockdata = merge (GDAXI, stockdata)
    
         no_of_datapoints = dim(stockdata)[1]
         
         min = input$range[1]/100 * no_of_datapoints
         max = input$range[2]/100 * no_of_datapoints
         
         # AdjustedPrice
         out = stockdata[min:max,]
         
         return (out)
      })

    When either input$stock_id or input$range are updated, the result of the datasetInput is updated wherever it is used, for instance in the plotting functions.
    What this “datasetInput” function actually returns is a merge of the DAX and the stock’s data, restricted to the range defined by the slider, where the range is specified in terms of two percentage values of the total number of rows of the data table.

  •  The server.R also has the definitions of the output plotting functions. These in turn make use of plotting functions from the package PerformanceAnalytics. The functions from PerformanceAnalytics that are used here are charts.PerformanceSummary, chart.Histogram and chart.Boxplot. As input they expect return type data. For charts.PerformanceSummary we use daily returns, for chart.Histogram and chart.Boxplot we use monthly returns.
    # generate a plot
      output$timeseries <- renderPlot({
    
        AdjustedPrice <- datasetInput()
        
        
        Returns <- AdjustedPrice/lag(AdjustedPrice, 1) -1 # daily returns
        charts.PerformanceSummary(Returns)
        
      })
      
      # generate a plot
      output$histogram.GDAXI <- renderPlot({
        
        AdjustedPrice <- datasetInput()[,1,drop=FALSE]
        Returns <- AdjustedPrice/lag(AdjustedPrice, 25) -1 # ~ monthly returns (because 1 month ~ 25 business days)
        
        chart.Histogram(Returns, methods = c( "add.density", "add.normal"), xlim = c(-0.4, 0.4))
        
      })
      
      # generate a plot
      output$histogram.stockdata <- renderPlot({
        
        AdjustedPrice <- datasetInput()[,2,drop=FALSE]
        Returns <- AdjustedPrice/lag(AdjustedPrice, 25) -1 # ~ monthly returns (because 1 month ~ 25 business days)
        
        chart.Histogram(Returns, methods = c( "add.density", "add.normal"), xlim = c(-0.4, 0.4))
        
      })
      
      # generate a plot
      output$boxplot <- renderPlot({
        
        AdjustedPrice <- datasetInput()
        Returns <- AdjustedPrice/lag(AdjustedPrice, 25) -1 # ~ monthly returns (because 1 month ~ 25 business days)
        
        chart.Boxplot(Returns)
        
      })

    Please note that these plotting functions use the reactive function datasetInput(). Therefore the plots are automatically updated whenever the inputs input$stock_id or input$range, used in datasetInput(), have changed.

Success!

To leave a comment for the author, please follow the link and comment on their blog: R – Artificial thoughts.

R-bloggers.com offers daily e-mail updates about R news and tutorials on topics such as: Data science, Big Data, R jobs, visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...



If you got this far, why not subscribe for updates from the site? Choose your flavor: e-mail, twitter, RSS, or facebook...

Comments are closed.

Search R-bloggers

Sponsors

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)