Monitoring Stock Performance made easy with R and Shiny | by Peer Christensen | Towards Data Science

Comparing the performance of many stocks in a single visualization can be time consuming. It is particularly tedious if you want to do this over and over again. With the help of R and Shiny, you can easily create and track a stock portfolio to see how individual stocks perform over time — all in one interactive visualization.
In this article, we will go through the process step by step and do the following:
Gather stock closing prices for a given time periodCreate a simple user interface allowing the user to select the data to be displayedDefine server functions
Gather stock closing prices for a given time period
Create a simple user interface allowing the user to select the data to be displayed
Define server functions
Let’s first load the R packages that we’ll be using in our app. You will need to install them on your system using the install.packages() function.
library(shiny)library(shinyWidgets)library(shinythemes)library(plotly)library(tidyverse)library(tidyquant)
We first define our portfolio’s ticker symbols and two stock indices as benchmarks. Then, we use the tq_get() function from the tidyquant package to get stock (closing) prices from Yahoo Finance. The to and from arguments are used to specify the desired date range.
tickers <- c("GRVY","SE","PLTR","U","NET","SNOW","MDB")benchmarks <- c("^NDX","^GSPC") # Nasdaq100 and SP500prices <- tq_get(tickers,                  get  = "stock.prices",                 from = today()-months(12),                 to   = today(),                 complete_cases = F) %>%     select(symbol,date,close)bench <- tq_get(benchmarks,                get  = "stock.prices",                from = today()-months(12),                to   = today()) %>%  select(symbol,date,close)
The code specifying the user interface will be wrapped in the fluidPage function and saved in a variable that we callui . This is demonstrated at the bottom of the article where we will put it all together.
Our app will have three main UI components:
A title panelA sidebar where users can select and filter the dataA main panel for visualizing the data
A title panel
A sidebar where users can select and filter the data
A main panel for visualizing the data
This one is easy. We simple write the following:
titlePanel("My Tech Stock Portfolio")
This part requires a bit more work, since this is where we specify what the user can do. In our app, we will need some input components that allow the user to pick and choose between stocks, the desired time range and whether or not to include a benchmark. Please have a look at the bottom of the article to see how we put the individual components together in our sidebar.
First, a pickerInput lets the user pick between stocks and select/deselect all. All are selected by default using the selected argument. Importantly, we specify the inputId in order to reference the selected stocks in our server logic.
pickerInput(                inputId = "stocks",                label   = h4("Stocks"),                choices = c(                "Gravity"       = tickers[1],                 "Sea Limited"   = tickers[2],                "Palantir"      = tickers[3],                "Unity"         = tickers[4],                "Cloudflare"    = tickers[5],                "Snowflake"     = tickers[6],                "MongoDB"       = tickers[7]),                selected = tickers,                   options = list(`actions-box` = TRUE),                 multiple = T            )
Then, radioButtons() provides different time ranges to choose from, as well as whether to include a benchmark index in the visualization.
# Time rangeradioButtons(   inputId = "period",    label   = h4("Period"),   choices = list("1 month" = 1, "3 months" = 2, "6 months" = 3, "12      months" = 4, "YTD" = 5),    selected = 4)# BenchmarkradioButtons(   inputId  = "benchmark",    label    = h4("Benchmark"),   choices  = list("SP500" = 1, "Nasdaq100" = 2,"None" = 3),   selected = 3)
This is where the plot goes. In our case, this is pretty straightforward.
mainPanel(plotlyOutput("plot", height=800))
Based on the user input, we need to specify how our app should behave. This is all done in the server part of our code. Because we want our app to be responsive and modify the visualization according user input, we wrap the logic to filter the data inside observeEvent .
For the sake of brevity, not all the input logic is included in the code chunk below. The complete code for this part is provided at the end.
observeEvent(c(input$period,input$stocks,input$benchmark), {        # filter stock symbols    prices <- prices %>%        filter(symbol %in% input$stocks)# filter time period (example)    if (input$period == 1) {        prices <- prices %>%            filter(                date >= today()-months(1)) }# filter benchmark (example)    if (input$benchmark == 1) {        bench <- bench %>%            filter(symbol=="^GSPC",                   date >= min(prices$date))        prices <- rbind(prices,bench) }# add more server logic here..})
Finally, we can plot our data combining ggplot2 and plotly . In order to better compare our stocks, we also need to recalculate their price levels to index base 100.
output$plot <- renderPlotly({ print(   ggplotly(prices %>%     # index 100       group_by(symbol) %>%     mutate(init_close = if_else(       date == min(date), close,NA_real_)) %>%     mutate(       value = round(100 * close / sum(init_close, na.rm=T),1)) %>%     ungroup() %>%     ggplot(aes(date, value, colour = symbol)) +       geom_line(size = 1, alpha = .9) +       #uncomment line below to show area under curves       #geom_area(aes(fill = symbol),position="identity",alpha=.2) +           theme_minimal(base_size=16) +           theme(axis.title = element_blank(),           plot.background  = element_rect(fill = "black"),           panel.background = element_rect(fill = "black"),           panel.grid       = element_blank(),           legend.text      = element_text(colour = "white"))                     )            )    })
That’s it!
We’ve walked through pretty much everything we need to create our app. Now, we only need to put the pieces together. Below is the full code for our shiny new stock portfolio app!
You can check out the app here
As you can see, I’ve chosen a dark theme supplied by the shinythemes package.