Reproducible Finance with R: A Sharpe Ratio Shiny App

[This article was first published on RStudio, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

by Jonathan Regenstein

In this previous post, we used an R Notebook to grab the monthly return data on three stocks, build a portfolio, visualize portfolio performance, and calculate the Sharpe Ratio. The Notebook format emphasized reproducibility and reuse by other R coders.

Today, we’ll convert that Notebook into a Shiny application that allows end users to build their own portfolios, and then calculate performance/Sharpe Ratio. Friday = fun day!

Here is the link to the app.

Close readers of the source code for this app will see that it was built in an Rmarkdown file (with output: flexdashboard::flexdashboard and runtime: shiny added to the YAML header).

---
title: "Sharpe Ratio Shiny"
runtime: shiny
output:
  flexdashboard::flex_dashboard:
    orientation: rows
    source_code: embed
---

This app could have been built using an app.r file, but I prefer to use a flexdashboard because it keeps the entire workflow in the Rmarkdown world. In the previous post, we started with a Notebook (also an Rmarkdown file type) and made use of code chunks to enforce logic on our data import, calculations and visualizations. This Shiny app makes use of the same code chunk structure, and I find that the logic translates well. For example, the setup chunks are almost identical and contain our most important function.

```{r setup, message = FALSE}
library(shiny)
library(flexdashboard)
library(PerformanceAnalytics)
library(quantmod)
library(dygraphs)

# Function to calculate monthly returns on a stock 
monthly_stock_returns <- function(ticker, start_year) {
  # Download the data from Yahoo finance
  symbol <- getSymbols(ticker, src = 'yahoo', from = start_year, 
                       auto.assign = FALSE, warnings = FALSE) 
  # Tranform it to monthly returns using the periodReturn function from quantmod
  data <- periodReturn(symbol, period = 'monthly', type = 'log')
  
  # Let's rename the column of returns to something intuitive because the column
  # name is what will eventually be displayed on the time series graph
  colnames(data) <- as.character(ticker)
  
  # We want to be able to work with the xts objects that result from this function 
  # so let's explicitly put them to the global environment with an easy to use 
  # name, the stock ticker
  assign(ticker, data, .GlobalEnv)
}
```

The sidebar code chunk is, of course, unique to the Shiny app, because there are no reactive inputs in a Notebook. But the dygraphs code chunks are similar enough that it’s easy to transfer the Notebook code, with a few changes, over to the flexdashboard:

```{r}
##dygraph chunk
dygraphOutput("dygraphDollarGrowth")


output$dygraphDollarGrowth<-renderDygraph({
  dygraph(portfolio_growth(), main = "Growth of $1 Invested in Your Portfolio") %>%
    dyAxis("y", label = "$") %>%
    dyOptions(axisLineWidth = 1.5, fillGraph = TRUE, drawGrid = TRUE)
})
```

File formats aside, from a team workflow perspective, this conversion to a Shiny app is super important - it’s where the R coders co-mingle with team members who need to make use of R’s analytical tools, but do not want to touch the code. For example, we can imagine a portfolio manager who wants the ability to quickly iterate through different portfolios and compare Sharpe Ratios, for internal construction purposes or perhaps even in a client-facing context. The PM does not want to write or reproduce this R code; he or she wants to focus on the portfolio.

In other words, a PM wants to see this:

Not this:

```{r}
##dygraph chunk
dygraphOutput("dygraphDollarGrowth")


output$dygraphDollarGrowth<-renderDygraph({
  dygraph(portfolio_growth(), main = "Growth of $1 Invested in Your Portfolio") %>%
    dyAxis("y", label = "$") %>%
    dyOptions(axisLineWidth = 1.5, fillGraph = TRUE, drawGrid = TRUE)
})
```

```{r}
valueBoxOutput("approvalBox1")
output$approvalBox1<-renderValueBox({
  valueBox(value = sharpe_ratio(), icon = "fa-line-chart", color = "primary")
})
```

Note that the portfolio performance and Share Ratio calculations are consolidated and moved to the front page, and the individual stock returns are on the second page. The original Notebook had the opposite layout - we began with individual returns and progressed to the portfolio - because it was emphasizing the steps involved in arriving at the conclusion. We wanted our collaborators to start with the basics of grabbing stock return data and then proceed through each logical step.

With this Shiny app, we don’t want to force our collaborators to go through our logic, because that is not the purpose of this app. End users of this app build and analyze portfolios, so let’s put those tools front and center. Give the users what they want!

Have fun with this app, dream about buying tech stocks at their lows, and remember, as with our previous Notebook, that this app is a starting point. End users might want the ability to choose more than three stocks, or add bonds to the portfolio, or benchmark against a return other than a risk-free rate. This is where R coders and portfolio managers start to collaborate and build things bigger and better. Have a good weekend!

To leave a comment for the author, please follow the link and comment on their blog: RStudio.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

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)