In April this year, Rstudio notified early users of shiny that Glimmer and Spark servers which host interactive-applications would be decommissioned. Basically, the company is moving forward to generate revenues from this great interactive application service. For us aspirants who use the service strictly as a hobby, that means, in a word: pay.
Basic subscription now costs around 40$ per month. Keeping your applications free of charge is possible BUT, as long as it is not used for more than 25 hours per month. So if your site generate some traffic, most users would simply not be able to access the app. Apart from that, you are subject to some built-in Rstudio’s logo which can’t be removed without having a paid subscription. That is a shame, but a company’s gotta eat right? I am using Rstudio’s services from their very beginning, and the company definitely deserve to eat! only I wish there would be another step between the monthly 0$ option which provides too slim capabilities, and the monthly 40$ option which is, in my admittedly biased opinion, too pricey for a ‘sometimes’ hobby.
Why this rant?
First, complaining is a terrific sport. Second, I now have two interactive applications running which I sometimes look at. The one measures cross assets correlations using ETF’s, live rolling correlation plot. The other measures volatility of the ETF’s using TGARCH, live volatility monitor. So the rant is to explain why you may, or may not be able to use it, depends on the amount of people used it already, and on the exact date as Rstudio reset the budget once per month.
Code for the first app is here
Code for the second app is below.
Code
Code for the user side
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 |
shinyUI(fluidPage(includeCSS("bootstrap_cosmo.css"), titlePanel(title=HTML("Live Volatility Monitor")), sidebarPanel( numericInput("nobs", "Type here how much history you would like to see (in days, maximum three years back) and click the 'Go' button", value = 60, min = 5, max = 700, step = 1), tags$div(class="header", checked=NA, style="color:#846666", #display= "inline",style= "font-size: 4em", tags$p("For the 10 Exchange Traded Funds: 'XLY','XLP','XLE','XLF','XLV','XLI','XLB','XLK','XLU' and 'SPY', we compute the volatility based on the last three years of daily close to close returns. The model used is a threshold garch (AKA GJR garch). Computaion is done using 'rugarch' package (Alexios Ghalanos, 2014)."), #tags$p("You can change the number of weeks you wish to use as a rolling window in the box above. A lower number will give #a more 'choppy' line, but more up-to-date, a high number will result in a smooth line, but calculation is then based on data further in the past."), # tags$p("The function to generate to plot is available under the code section in this blog.") # under the code section in this blog.") tags$p("The function to generate to plot is available"), span( tags$a(href="https://eranraviv.com/category/code/", "here",target="blank"), style = "color:blue" ) ), checkboxGroupInput("etf","Ticker", c('XLY','XLP','XLE','XLF','XLV','XLI','XLB','XLK','XLU','SPY'), selected = 'SPY'),#numericInput("nobs", "Number of most recent quarters (multiples of 4)",20,4,52, step = 4), submitButton(text="Go") ), mainPanel( h3(textOutput("")), plotOutput("volplot", width = "100%", height = "750px") ) )) |
Code for the server side
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# Download data library(quantmod) library(rugarch) symetf = c('XLY','XLP','XLE','XLF','XLV','XLI','XLB','XLK','XLU','SPY') end<- format(Sys.Date(),"%Y-%m-%d") start<-format(Sys.Date() - (3*365),"%Y-%m-%d") # 3 years of data l = length(symetf) dat0 <- lapply(symetf, getSymbols,src="yahoo", from=start, to=end, auto.assign = F,warnings = FALSE,symbol.lookup = F) n <- NROW(dat0[[l]]) # Return matrix, close to close ret <- lapply(dat0, function(x) {100*(as.numeric(x[2:n, 4])/as.numeric(x[1:(n-1), 4]) - 1) } ) # end.time <- Sys.time() # print(end.time - start.time) time <- index(dat0[[l]]) dat1 <- do.call(cbind,lapply(dat0, function(x) {as.numeric(x[, 4]) } ) ) Ticker <- symetf names(Ticker) <- symetf # Specify mean model as RW since returns are daily gjrtspec <- ugarchspec(mean.model=list(armaOrder=c(0,0)),variance.model =list(model = "gjrGARCH"),distribution="std") Tgjrmodel = lapply(ret, ugarchfit, spec=gjrtspec) # Extract the annualized volatility volatility_fit <- lapply(Tgjrmodel, function(x) sqrt(250)*as.numeric(sigma(x))) vol_mat <- do.call(cbind, volatility_fit) colnames(vol_mat) <- symetf TT <- NROW(vol_mat) shinyServer(function(input, output) { lwd1 <- fontt <- 2 mplotfun <- function(ind, nobs){ par(mfrow = c(2,1), bg = "white", bty ="o", fg = "black" ,font.lab = fontt, font.axis = fontt, font.main = fontt, col.axis = "black", col.lab = "black",las=1, cex.axis = 1.3, pch = 21, tck = -0.02, cex.lab = 1.3, cex.main = 1.4, mar = c(3, 3.5, 3.5, .9) ) sind = sum(ind) # First plot plot(tail(vol_mat[, which(ind==1)[1] ], nobs)~tail(time, nobs), ty = "o",lwd = lwd1, xlab = "", ylim = range(tail(vol_mat[, which(ind==1)], nobs)), ylab = "", main = "Volatility (%, annualized)", pch = 1,lty = 1, col = 1) if(length(which(ind==1))>1){ for(i in 2:length(which(ind==1))){ lines(tail(vol_mat[, which(ind==1)[i] ], nobs)~tail(time, nobs), ty = "o",lwd = lwd1, pch = i,lty = i, col = i) } } legend("topleft", bty = "n",lwd = rep(lwd1,sind),colnames(vol_mat)[ind==1], ncol=3, lty = 1:sind, col = 1:sind, pch = 1:sind, xpd=T, text.col= 1:sind, merge = TRUE) grid(col = "grey") # Second plot dat2 <- 100*(tail(dat1,nobs)/t(replicate(nobs,dat1[(n-nobs+1),])) - 1) plot(dat2[, which(ind==1)[1] ]~tail(time, nobs), ty = "b",lwd = lwd1, xlab = "", ylim = range(dat2), ylab = "", main = paste("ETF % move ", "(", time[(n-nobs+1)], " = 0)",sep="" ), pch = 1,lty = 1, col = 1) if(length(which(ind==1))>1){ for(i in 2:length(which(ind==1))){ lines(dat2[, which(ind==1)[i] ]~tail(time, nobs), ty = "o", lwd = lwd1, pch = i, lty = i, col = i) } } legend("topleft", bty = "n",lwd = rep(lwd1,sind),colnames(vol_mat)[ind==1], ncol=3, lty = 1:sind, col = 1:sind, pch = 1:sind, xpd=T, text.col= 1:sind, merge = TRUE) grid(col = "grey") } output$volplot <- renderPlot({ mplotfun(ind= Ticker%in% input$etf, nobs = input$nobs) # 5 bussiness days in a week }) }) |