Shiny object not found

669 Views Asked by At

Shiny getsymbols works but no column name containing "close"

The above link is a question I asked two days ago which is solved. When I try to keep working on my project, I encounter a new problem.

I try to plot the summary graph but an error occurs. (object 'ret1' not found)

ui.R

library(shiny)
library(quantmod)
library(PerformanceAnalytics)
ui <- fluidPage(

      textInput("symb", "Stock Name", "AAPL"),
      
      dateRangeInput("dates",
                     "Date range",
                     start = "2020-01-01",
                     end = as.character(Sys.Date())),

      actionButton("GO","GO"),

      (plotOutput("perfsPlot"))
)

server.R

server <- function(input, output, session) {
data <- eventReactive(input$GO,{

    getSymbols(input$symb, src = "yahoo",
               from = input$dates[1],
               to = input$dates[2],
               auto.assign = FALSE)
    
    price <<- Cl(get(input$symb))
    r <<- price/Lag(price) - 1
    delta <<-0.005
    signal <<-c(NA) # first signal is NA
    
    
    for (i in 2: length(price)){
      if (r[i] > delta){
        signal[i]<- 1
      } else if (r[i]< -delta){
        signal[i]<- -1
      } else
        signal[i]<- 0
    }
    
    signal<<-reclass(signal,price)
    
    
    trade1 <<- Lag(signal)
    ret1<<-dailyReturn(input$symb)*trade1 # I tried to replace this code by assign(x = "ret1", value = dailyReturn(input$symb)*trade1, envir = .GlobalEnv)
  })
  
  
    output$perfsPlot <- renderPlot({
      charts.PerformanceSummary(ret1) #object 'ret1' not found, I tried to replace this code by data()
  })
)

I do some research and found that it may be related to "when a reactive block is done executing, all elements within it go away". As a result, ret1 is not being stored. I tried to assign each object, like price, r, delta... but still not working. How can I store all objects under eventReactive?

Here is the code that can run in R

price <- Cl(MSFT)
r <- price/Lag(price) - 1
delta<-0.005
signal <-c(NA) # first signal is NA


for (i in 2: length(Cl(MSFT))){
  if (r[i] > delta){
    signal[i]<- 1
  } else if (r[i]< -delta){
    signal[i]<- -1
  } else
    signal[i]<- 0
}

signal<-reclass(signal,Cl(MSFT))


trade1 <- Lag(signal)
ret1<-dailyReturn(MSFT)*trade1
names(ret1) <- 'Naive'
charts.PerformanceSummary(ret1)

Also, after I run this file in R, all objects stored in my local environment, the shiny app can show the graphic successfully.

1

There are 1 best solutions below

0
DaveArmstrong On

I think the main problem was that you were trying to save reactive elements back to the server's environment with <<-. Instead, I would suggest making a data object that is reactive and then using the reactive data to make the charts. Here is an example of how it would work. Note, in the UI, you don't need the action button, the data will be redrawn every time you change the inputs (more on that below).

library(shiny)
library(quantmod)
library(PerformanceAnalytics)
ui <- fluidPage(
  
  
  textInput("symb", "Stock Name", "AAPL"),
  
  dateRangeInput("dates",
                 "Date range",
                 start = "2020-01-01",
                 end = as.character(Sys.Date())),
  
#  actionButton("GO","GO"),
  
  plotOutput("perfsPlot")
)

The server is where things changed the most:

server <- function(input, output, session) {
  symb <- reactive(input$symb)
  symb_d <- symb %>% debounce(1000)
  dts <- reactive(input$dates)
  dts_d <- dts %>% debounce(1000)
  
  data <- reactive({
    d1 <- getSymbols(symb_d(), src = "yahoo",
               from = dts_d()[1],
               to = dts_d()[2],
               auto.assign = FALSE)
    
    price <- Cl(d1) 
    r <- price[,1]/Lag(price[,1]) - 1
    delta <-0.005
    signal <-c(NA) # first signal is NA
    
    
    for (i in 2: nrow(price)){
      if (r[i] > delta){
        signal[i]<- 1
      } else if (r[i]< -delta){
        signal[i]<- -1
      } else
        signal[i]<- 0
    }
    
    signal<-reclass(signal,price)
    
    
    trade1 <- Lag(signal)
    ret1 <- dailyReturn(d1)*trade1 # I tried to replace this code by assign(x = "ret1", value = dailyReturn(input$symb)*trade1, envir = .GlobalEnv)
    d1$price <- unname(price[,1])
    d1$signal <- signal
    d1$trade1 <- trade1
    d1$ret1 <- ret1
    d1
  })
  
  
  output$perfsPlot <- renderPlot({
    charts.PerformanceSummary(data()$ret1, 
                              main = paste0(input$symb, " Performance")) 
  })
}

Note, first, that I have put the inputs inside a reactive context and then "debounced" them, so that they will not try to update when you are still typing. Here's a post that explains debouncing and throttling. Next, I made the data a reactive object that returns a data frame that has the original output from getSymbol() along with the derived quantities price, signal, trade1 and ret1. All of these will be returned in a single reactive object that you can access with data(). In your code, there were several places where the code simply wasn't working. One example was:

price <<- Cl(get(input$symb))

which failed because get() didn't know how to operate on a character string, like "AAPL". When that didn't work, all of the subsequent calculations also failed. You can see in the plot, I used the data() object and then used the symbol in the main plot label:

charts.PerformanceSummary(data()$ret1, 
                          main = paste0(input$symb, " Performance")) 

Altogether, this produced an output that looked like the following:

enter image description here