<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Forecasting on R Views</title>
    <link>https://rviews.rstudio.com/tags/forecasting/</link>
    <description>Recent content in Forecasting on R Views</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Thu, 07 Apr 2022 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://rviews.rstudio.com/tags/forecasting/" rel="self" type="application/rss+xml" />
    
    
    
    
    <item>
      <title>A Macroeconomics Dashboard on Turkey Inflation</title>
      <link>https://rviews.rstudio.com/2022/04/07/a-macroeconomics-dashboard-on-turkey-inflation/</link>
      <pubDate>Thu, 07 Apr 2022 00:00:00 +0000</pubDate>
      
      <guid>https://rviews.rstudio.com/2022/04/07/a-macroeconomics-dashboard-on-turkey-inflation/</guid>
      <description>
        
&lt;script src=&#34;/2022/04/07/a-macroeconomics-dashboard-on-turkey-inflation/index_files/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;&lt;em&gt;Enes Gencer is a lead data scientist at &lt;a href=&#34;https://www.doktar.com/en/&#34;&gt;Doktar&lt;/a&gt; and a graduate of Tilburg University (Research Master, Economics). Enes’ interests include data science problems in Economics, Finance, and Agriculture.&lt;/em&gt;&lt;/p&gt;
&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Inflation is a hot topic for both globally and in Turkey nowadays. Inspired by Rami Krispin, I reverse engineered his &lt;a href=&#34;https://ramikrispin.github.io/USelectricity/&#34;&gt;U.S. Electricity dashboard&lt;/a&gt; and created a &lt;a href=&#34;https://enesgencer18.github.io/turkey-macro-dashboard/&#34;&gt;dashboard&lt;/a&gt; to explore a forecast for inflation in Turkey. In this post, I would like to begin to describe some of the technology that went into creating the dashboard.&lt;/p&gt;
&lt;p&gt;The data and machine learning pipelines are automated via Docker, Github Actions, and R Markdown. The dashboard has too many dimensions to cover in a single blog post so in this blog post, I focus on the underlying economics and the forecasting method I choose, Elastic Net. In the coming blog posts, I might write on different aspects like flexdashboard, Docker, or a more interesting forecasting method like LSTM using Keras on R.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;getting-started&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;First, we load the required libraries and data set.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyverse)
library(lubridate) 
library(caret)
library(zoo)
library(ggthemes)
library(magick)

load(&amp;quot;processed_data.Rdata&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;dataset&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Dataset&lt;/h2&gt;
&lt;p&gt;The data set consists of monthly macroeconomic variables. The dependent variable is the Y-o-Y change in CPI, and the independent variables are lags of&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Price indexes&lt;/li&gt;
&lt;li&gt;Tendency surveys of the economic agents&lt;/li&gt;
&lt;li&gt;Production statistics&lt;/li&gt;
&lt;li&gt;Balance of payments statistics&lt;/li&gt;
&lt;li&gt;Exchange rate return&lt;/li&gt;
&lt;li&gt;Month (to take into account seasonality)&lt;/li&gt;
&lt;li&gt;CPI Forecast of TBATS model (inspired by the stacking methods)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First, I only included lags to avoid hindsight bias or the “knew-it-all-along” phenomenon. For instance, as of today, the model predicts March inflation. However, March statistics are not announced yet. If the model is constructed to use March statistics, then it has no value in real-life prediction.&lt;/p&gt;
&lt;p&gt;Second, the analysis does not cover the effect of interest rates on inflation. That is only because I have a pre-written script to pull monthly variables. Therefore, I do not want to spend time adjusting the frequency. Also, the effect of the interest rate is known anyway. Central banks shift the price of money (or cost of borrowing) by changing interest rates, which is the primary tool to manage inflation. A rise in interest rate has two effects: first, it makes borrowing more costly, so people defer their consumption. Second, it might reduce the present value of financial assets. Hence, creating a negative wealth effect. Both impacts cause the inflationary pressures to ease.&lt;/p&gt;
&lt;p&gt;We have the training data:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;forecast_date = &amp;quot;2022-03-31&amp;quot;

train_data &amp;lt;- forecast_df %&amp;gt;% 
  filter(Date &amp;lt; forecast_date)

tail(train_data,3)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tibble: 3 × 94
##   Date         CPI CPI_Lag1 CLI_Lag1 Domestic_PPI_Lag1 Inflation_Expectation_La…
##   &amp;lt;date&amp;gt;     &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;             &amp;lt;dbl&amp;gt;                     &amp;lt;dbl&amp;gt;
## 1 2021-12-31 0.361    0.213     102.             0.546                      15.6
## 2 2022-01-31 0.487    0.361     102.             0.799                      21.4
## 3 2022-02-28 0.544    0.487     101.             0.935                      25.4
## # … with 88 more variables: FS_Confidience_Lag1 &amp;lt;dbl&amp;gt;,
## #   RS_Confidience_Lag1 &amp;lt;dbl&amp;gt;, Production_Volume_Lag1 &amp;lt;dbl&amp;gt;,
## #   Export_Orders_Lag1 &amp;lt;dbl&amp;gt;, BoP_Lag1 &amp;lt;dbl&amp;gt;, Utilization_Rate_Lag1 &amp;lt;dbl&amp;gt;,
## #   Consumer_Confidience_Lag1 &amp;lt;dbl&amp;gt;, Import_Annual_Ret_Lag1 &amp;lt;dbl&amp;gt;,
## #   Import_Monthly_Ret_Lag1 &amp;lt;dbl&amp;gt;, UsdTry_Annual_Ret_Lag1 &amp;lt;dbl&amp;gt;,
## #   UsdTry_Monthly_Ret_Lag1 &amp;lt;dbl&amp;gt;, CPI_Lag2 &amp;lt;dbl&amp;gt;, CLI_Lag2 &amp;lt;dbl&amp;gt;,
## #   Domestic_PPI_Lag2 &amp;lt;dbl&amp;gt;, Inflation_Expectation_Lag2 &amp;lt;dbl&amp;gt;, …&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the test data:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_data &amp;lt;- forecast_df %&amp;gt;% 
  filter(Date  == forecast_date)

head(test_data)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tibble: 1 × 94
##   Date         CPI CPI_Lag1 CLI_Lag1 Domestic_PPI_Lag1 Inflation_Expectation_La…
##   &amp;lt;date&amp;gt;     &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;             &amp;lt;dbl&amp;gt;                     &amp;lt;dbl&amp;gt;
## 1 2022-03-31    NA    0.544     101.              1.05                      24.8
## # … with 88 more variables: FS_Confidience_Lag1 &amp;lt;dbl&amp;gt;,
## #   RS_Confidience_Lag1 &amp;lt;dbl&amp;gt;, Production_Volume_Lag1 &amp;lt;dbl&amp;gt;,
## #   Export_Orders_Lag1 &amp;lt;dbl&amp;gt;, BoP_Lag1 &amp;lt;dbl&amp;gt;, Utilization_Rate_Lag1 &amp;lt;dbl&amp;gt;,
## #   Consumer_Confidience_Lag1 &amp;lt;dbl&amp;gt;, Import_Annual_Ret_Lag1 &amp;lt;dbl&amp;gt;,
## #   Import_Monthly_Ret_Lag1 &amp;lt;dbl&amp;gt;, UsdTry_Annual_Ret_Lag1 &amp;lt;dbl&amp;gt;,
## #   UsdTry_Monthly_Ret_Lag1 &amp;lt;dbl&amp;gt;, CPI_Lag2 &amp;lt;dbl&amp;gt;, CLI_Lag2 &amp;lt;dbl&amp;gt;,
## #   Domestic_PPI_Lag2 &amp;lt;dbl&amp;gt;, Inflation_Expectation_Lag2 &amp;lt;dbl&amp;gt;, …&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;modelling&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Modelling&lt;/h2&gt;
&lt;p&gt;I evaluated multiple machine learning algorithms: Elastic Net, generalized linear models, Random Forest, and Support Vector Machines. I decided that Elastic Net has crucial advantages. First, there is a very high correlation between the explanatory variables. Notice that I included multiple lags of a given variable. Also, two different variables might have associations through multiple macroeconomic channels. Hence, multi-collinearity has to be taken into account. Second, I prefer an interpretable model to validate the model results with stylized macroeconomic facts. Third, in this case, it has higher performance (in terms of RMSE and MAPE) compared to more complex models like Support Vector Machines or Random Forest. Therefore, Elastic Net provides me a sweet spot for interpretability, performance, and speed.&lt;/p&gt;
&lt;p&gt;So, what is Elastic Net? It is a regularized regression technique that linearly combines L_1 and L_2 penalties. Basically, it is a combination of LASSO and Ridge regressions. In other words, it sets a group of the coefficient to zero and shrinks the remaining ones towards zero.&lt;/p&gt;
&lt;p&gt;Mathematically, Elastic Net optimizes the following equation:&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math inline&#34;&gt;\(\min_{\beta_0,\beta} \frac{1}{N} \sum_{i=1}^{N} w_i l(y_i,\beta_0+\beta^T x_i) + \lambda\left[(1-\alpha)\|\beta\|_2^2/2 + \alpha \|\beta\|_1\right]\)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Visual comparison between LASSO, Ridge, and Elastic Net penalties:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;magick::image_read(path = &amp;quot;elastic-net.png&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/2022/04/07/a-macroeconomics-dashboard-on-turkey-inflation/index_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;100%&#34; /&gt;
Source: Zou, H., &amp;amp; Hastie, T. (2005). Regularization and variable selection via the elastic net.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Construct time slices for time-series cross validation

time_slices &amp;lt;- trainControl(
  method = &amp;quot;timeslice&amp;quot;,
  initialWindow = 36,
  fixedWindow = TRUE,
  horizon = 3,
  savePredictions = TRUE,
  verboseIter = FALSE
)

# Train the model

elastic_net_fit &amp;lt;- train(
  CPI ~ .,
  data = train_data[,-1],
  na.action = &amp;quot;na.pass&amp;quot;,
  method = &amp;quot;glmnet&amp;quot;,
  preProcess = c(&amp;quot;center&amp;quot;, &amp;quot;scale&amp;quot;),
  trControl = time_slices
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I use time-series cross-validation with a fixed window size to tune the hyper-parameters and evaluate the model performance. My idea is that the inflation dynamics might evolve. For instance, we have observed the increasing effect of the exchange rate on inflation in recent years. However, as a result of the commodity super-cycle, we might see the producer price index come into play. Therefore, having a more flexible model structure with respect to time makes sense.&lt;/p&gt;
&lt;p&gt;In this case, the model is trained on the first 36 observations and evaluated on the 3 consecutive values on the test set. Then, the time slice shifts one month.&lt;/p&gt;
&lt;p&gt;To learn more details on time-series cross-validation, please visit: &lt;a href=&#34;https://robjhyndman.com/hyndsight/tscv/&#34; class=&#34;uri&#34;&gt;https://robjhyndman.com/hyndsight/tscv/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;results&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Results&lt;/h2&gt;
&lt;p&gt;First, I get the best hyper parameters and collect the predictions of the selected model.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Visualize results

lasso_preds %&amp;gt;% 
  rename(Actual = CPI,
         Forecasted = pred) %&amp;gt;% 
  gather(key = &amp;quot;Variable&amp;quot;, value = &amp;quot;Value&amp;quot;, Actual:Forecasted) %&amp;gt;% 
  ggplot(aes(x = Date, y = Value, color = Variable))+
  geom_line(size = 0.75, alpha = 0.5)+
  geom_point(size = 0.75, alpha = 0.75)+
  scale_color_manual(values = c(&amp;quot;steelblue4&amp;quot;, &amp;quot;darkred&amp;quot;))+
  theme_bw()+
  scale_y_continuous(labels = scales::percent)+
  scale_x_date(breaks = seq(min(lasso_preds$Date), 
                            max(lasso_preds$Date), 
                            by=&amp;quot;4 months&amp;quot;),
             date_labels = &amp;#39;%m-%y&amp;#39;)+
  labs(x = &amp;quot;&amp;quot;,
       y = &amp;quot;&amp;quot;,
       subtitle = &amp;quot;Based on YoY CPI changes&amp;quot;,
       title = &amp;quot;One-month ahead inflation forecast&amp;quot;,
       color = &amp;quot;&amp;quot;)+
  expand_limits(y = 0)+
  theme(plot.subtitle = element_text(face = &amp;quot;italic&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/2022/04/07/a-macroeconomics-dashboard-on-turkey-inflation/index_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The plot shows a one-month ahead inflation forecast and actual inflation based on the YoY CPI changes.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;lasso_preds %&amp;gt;% 
  ggplot(aes(x = pred, y = CPI))+
  geom_point(size = 1.5, alpha = 0.8, color = &amp;quot;darkred&amp;quot;)+
  geom_abline(intercept = 0, 
              slope = 1, 
              size = 0.3, 
              linetype = 3, 
              alpha = 0.8, 
              color = &amp;quot;steelblue4&amp;quot;)+
  theme_bw()+
  scale_y_continuous(labels = scales::percent)+
  scale_x_continuous(labels = scales::percent)+
  expand_limits(y = 0, x = 0)+
  labs(title = &amp;quot;Model Prediction &amp;amp; True Value&amp;quot;,
       x = &amp;quot;Model Prediction&amp;quot;,
       y = &amp;quot;True Value&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/2022/04/07/a-macroeconomics-dashboard-on-turkey-inflation/index_files/figure-html/unnamed-chunk-8-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The second plot shows the predictions vs. the real values. You would expect to see the points are piled up around the 45-degree line. The model seems consistent in its predictions except for the three outliers, which will become sounder in the following plot.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;lasso_preds %&amp;gt;% 
  mutate(Residual = CPI - pred) %&amp;gt;% 
  ggplot(aes(x = Date, y = Residual))+
  geom_point(size = 1.5, alpha = 0.8, color = &amp;quot;steelblue4&amp;quot;)+
  geom_ribbon(stat=&amp;#39;smooth&amp;#39;, se=TRUE, alpha=0.05) +
  geom_line(stat=&amp;#39;smooth&amp;#39;, alpha=1, color = &amp;quot;darkred&amp;quot;)+
  theme_bw() +
  labs(y = &amp;quot;Residuals&amp;quot;,
       x = &amp;quot;&amp;quot;,
       title = &amp;quot;Elastic Net Model Residuals&amp;quot;,
       subtitle = &amp;quot;Over time&amp;quot;)+
  scale_y_continuous(labels = scales::percent)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/2022/04/07/a-macroeconomics-dashboard-on-turkey-inflation/index_files/figure-html/unnamed-chunk-9-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The third plot shows the model residuals over time. Notice that the model performance improves over time (until 2021), the smoothed residual curve gets closer to zero, and the frequency of outliers decreases. However, since 2021, the model performance has started to deteriorate caused by economic shocks. A different dynamic that cannot be taken into account comes into play.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;var_names &amp;lt;- coef(elastic_net_fit$finalModel, 
                  elastic_net_fit$finalModel$lambdaOpt) %&amp;gt;% 
  rownames()

var_values &amp;lt;- coef(elastic_net_fit$finalModel, 
                   elastic_net_fit$finalModel$lambdaOpt) %&amp;gt;% 
  as.numeric()

model_result &amp;lt;- tibble(Variable_Names = var_names,
                       Coefficients = var_values)

model_result %&amp;gt;% 
  mutate(Variable = gsub(&amp;#39;[[:digit:]]+&amp;#39;, &amp;#39;&amp;#39;, 
                         str_remove(model_result$Variable_Names, 
                                    &amp;quot;_Lag&amp;quot;))) %&amp;gt;% 
  group_by(Variable) %&amp;gt;% 
  summarise(Overall_Effect = sum(Coefficients)) %&amp;gt;% 
  filter(!Overall_Effect == 0) %&amp;gt;%
  filter(!Variable == &amp;quot;(Intercept)&amp;quot;) %&amp;gt;% 
  mutate(If_Positive = ifelse(Overall_Effect &amp;gt;0, &amp;quot;Positive&amp;quot;, &amp;quot;Negative&amp;quot;)) %&amp;gt;% 
  mutate(Sum = sum(abs(Overall_Effect))) %&amp;gt;% 
  mutate(Percent_Effect = Overall_Effect / Sum) %&amp;gt;% 
  ggplot(aes(x = reorder(Variable, abs(Overall_Effect)), y = abs(Percent_Effect), fill = If_Positive))+
  geom_col(alpha = 3)+
  scale_y_continuous(labels = scales::percent)+
  expand_limits(y = c(0,0.45))+
  coord_flip() +
  labs(y = &amp;quot;&amp;quot;,
       x = &amp;quot;&amp;quot;,
       fill = &amp;quot;&amp;quot;,
       title = &amp;quot;The weighted effects macroeconomic variables on Turkey&amp;#39;s Inflation&amp;quot;,
       subtitle = &amp;quot;Shows the overall effect through different lags&amp;quot;, 
       caption = &amp;quot;Source: CBRT&amp;quot;)+
  theme_bw()+
  scale_fill_wsj()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/2022/04/07/a-macroeconomics-dashboard-on-turkey-inflation/index_files/figure-html/unnamed-chunk-10-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The final plot shows the weighted effect of macroeconomic variables on Turkey’s inflation. Notice two things. First, the values on the x-axis are not coefficients, but the share of each variable in total effect. Second, it shows the overall impact coming through multiple lags. Beyond the predictive abilities, the findings are consistent with macroeconomic facts. Remember that we want to interpret the model results. First, the highest share of CPI confirms the well-known “inertia’ phenomenon in inflation.”Inertia&#34; refers to a situation in which prices in the whole economy adjust with the change in the price index. Therefore, it creates a self-sustaining loop.&lt;/p&gt;
&lt;p&gt;Secondly, the effect of annual changes in import prices follows CPI. It is known as one of the most significant determinants of Turkey’s inflation. It is mainly because of the structure of the Turkish economy and production. Inflation expectations have the third-highest effect.&lt;/p&gt;
&lt;p&gt;Theoretically, economic agents process all the information available constitutes expectation about the future and maximizes their utility. When the economic agents believe that future inflation rises, and behave accordingly, it turns into a self-fulfilling prophecy. Hence, it shows the importance of shaping the economic agents’ beliefs and expectations for a policy-maker.&lt;/p&gt;
&lt;p&gt;Finally, the domestic producer price index is a variable with a relatively higher weight, which is consistent with the “pass-through effect”. The producer price index is more volatile due to its higher sensitivity towards shocks, however, it is expected that the producer and consumer price indexes move together in the long run. Therefore, in a relatively short-term analysis (which covers six months), we observe a partial “pass-through” effect.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;To sum up, I focus on the underlying economics and machine learning algorithm used to forecast inflation. The elastic net algorithm is chosen considering the three factors: interpretability of model results, time efficiency, and model performance. The model results are consistent with the stylized facts of Turkey’s macroeconomics and underlying economic theory.&lt;/p&gt;
&lt;p&gt;Beyond economics and theory, however, there is still a lot to uncover. The data and machine learning pipelines are automated via Github Actions and Docker. The dashboard is constructed with R Markdown and flexdashboard. Hopefully, I will discuss them in the coming posts with different dashboards. Till then, you can always reach me if you have any questions.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: for more information on the code and data used in this post, please see the author’s &lt;a href=&#34;https://github.com/enesgencer18/turkey-macro-dashboard&#34;&gt;Github repository&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;

        &lt;script&gt;window.location.href=&#39;https://rviews.rstudio.com/2022/04/07/a-macroeconomics-dashboard-on-turkey-inflation/&#39;;&lt;/script&gt;
      </description>
    </item>
    
    <item>
      <title>A Shiny App for Importing and Forecasting Commodities Prices from Quandl</title>
      <link>https://rviews.rstudio.com/2017/04/21/a-shiny-app-for-importing-and-forecasting-commodities-prices-from-quandl/</link>
      <pubDate>Fri, 21 Apr 2017 00:00:00 +0000</pubDate>
      
      <guid>https://rviews.rstudio.com/2017/04/21/a-shiny-app-for-importing-and-forecasting-commodities-prices-from-quandl/</guid>
      <description>
        
&lt;!-- BLOGDOWN-HEAD --&gt;
&lt;!-- /BLOGDOWN-HEAD --&gt;

&lt;!-- BLOGDOWN-BODY-BEFORE --&gt;
&lt;!-- /BLOGDOWN-BODY-BEFORE --&gt;
&lt;p&gt;In a &lt;a href=&#34;https://rviews.rstudio.com/2017/03/17/quandl-and-forecasting/&#34;&gt;previous post&lt;/a&gt;, we imported oil data from Quandl and applied a simple model to it. Today, we’ll port that work over to a Shiny app (by way of flexdashboard, of course) that allows a user to choose a commodity (oil, copper or gold), choose a frequency for the time series, and choose how many periods ahead to forecast. The app will display the price history and the forecasted price. To see it in action, have a look &lt;a href=&#34;http://colorado.rstudio.com:3939/commodities-quandl-flexdb/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As with the previous Notebook, the main purpose of this post is to build a template where a more sophisticated or proprietary model could be used for forecasting. By setting it up so that models could be selected as inputs, several different models could be included. We are not as concerned with the modeling as much as we are with providing a format that is friendly to both end users and any future collaborator that might want to take this app and expand upon it.&lt;/p&gt;
&lt;p&gt;Let’s get to it! In the code chunk below, we are immediately faced with a few important decisions. The first of those is the format of the user input. At the extreme, we could use &lt;code&gt;textInput&lt;/code&gt; and simply allow the user to enter the code for the desired data set. The benefit is that we 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.&lt;/p&gt;
&lt;p&gt;For example, to import WTI oil prices, the user would have to type in “FRED/DCOILWTICO”. That’s no problem if most of the end users know that code, but it’s a big problem otherwise. We want to emphasize convenience and broad usability, so we are going with &lt;code&gt;selectInput&lt;/code&gt; instead of &lt;code&gt;textInput&lt;/code&gt;, meaning our app will show a drop-down of a few choices. The user just selects “WTI oil” instead of typing “FRED/DCOILWTICO”“, or selects”copper&amp;quot; instead of typing “ODA/PCOPP_USD”. But, if a user wants to work with a data set that we haven’t included, said user is out of luck.&lt;/p&gt;
&lt;p&gt;Another big decision is how many choices to give the user. I have included only 3: oil, gold and copper. In industry, you would probably include several more, perhaps all of the industrial metals, but there’s is a cutoff somewhere. Or maybe we prefer one choice, because this app is just for oil analysis. Either way, the number of options in the drop-down menu is another trade-off between usability and flexibility.&lt;/p&gt;
&lt;p&gt;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 peek at the object called &lt;code&gt;dataChoices&lt;/code&gt;, and you might notice that we don’t strictly need that object. We could have put the vector of choices as an argument to &lt;code&gt;selectInput&lt;/code&gt;, so that our code would have read &lt;code&gt;choices = c(&amp;quot;WTI oil&amp;quot; = &amp;quot;FRED/DCOILWTICO&amp;quot;, ...)&lt;/code&gt; instead of &lt;code&gt;choices = dataChoices&lt;/code&gt;. In that choice assignment, “WTI oil” is called the name and “FRED/DCOILWTICO” is called the value (together we can think of them as a name-value pair). The entire reason for building a separate &lt;code&gt;dataChoices&lt;/code&gt; 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 as well when we label our graph.&lt;/p&gt;
&lt;p&gt;The ability to extract names and values will become even more useful when we get to the frequency of the time series and forecasting. For now, let’s look at &lt;code&gt;dataChoices&lt;/code&gt; and &lt;code&gt;selectInput&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Notice a tradeoff here: we&amp;#39;re making it easy on our users because they don&amp;#39;t need to 
# remember the naming conventions. But, we&amp;#39;re also forced to severely limit their choices. 
# The dataChoices object is going to allow us to add a nicer label to the graph. 
# Notice also how easily we can include datasets from different sources, and not worry about
# their formats. Thanks, Quandl!

dataChoices &amp;lt;- c(&amp;quot;WTI oil&amp;quot; = &amp;quot;FRED/DCOILWTICO&amp;quot;, # oil data from Fred
                 &amp;quot;Copper&amp;quot; = &amp;quot;ODA/PCOPP_USD&amp;quot;, # copper data from ODA
                 &amp;quot;Gold&amp;quot; = &amp;quot;CHRIS/CME_GC1&amp;quot;) # gold data from CME

selectInput(&amp;quot;dataSet&amp;quot;,
            &amp;quot;Commodity&amp;quot;,
            choices = dataChoices,
            selected = &amp;quot;WTI oil&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Alright, we have given the user the ability to choose a commodity. Next we want to ask about the frequency, and this gets a bit more complicated. We need to tell Quandl the frequency of the time series to import using the “daily”, “weekly”, “monthly” convention, so we set those to the values. But, further down the app when we want to store the forecast results, we’ll need to use the “days”, “weeks”, “months” phrasing and we’ll need to pull out the names from the name-value pair in &lt;code&gt;frequencyChoices&lt;/code&gt;. We knew that this would be necessary because when we built our Notebook for importing, wrangling, and testing, we noted the different conventions and started thinking about how to deal with them in the Shiny context.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# The frequencyChoices object is going to allow us to pass different period conventions
# to different places further down the app. 

frequencyChoices &amp;lt;- c(&amp;quot;days&amp;quot; = &amp;quot;daily&amp;quot;,
                      &amp;quot;weeks&amp;quot; = &amp;quot;weekly&amp;quot;, 
                      &amp;quot;months&amp;quot; = &amp;quot;monthly&amp;quot;)

selectInput(&amp;quot;frequency&amp;quot;,
            &amp;quot;freq&amp;quot;,
            choices = frequencyChoices, 
            selected = &amp;quot;months&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The remainder of the inputs should look familiar as they are in standard format.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dateRangeInput(&amp;quot;dateRange&amp;quot;,
               &amp;quot;Date range&amp;quot;,
               start = &amp;quot;1980-01-01&amp;quot;,
               end   = &amp;quot;2016-12-31&amp;quot;)

numericInput(&amp;quot;periods&amp;quot;, &amp;quot;Periods to Forecast&amp;quot;, 6, min = 1, max = 100)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now that we’ve built the sidebar inputs, let’s put them to use. First, we will import the commodity time series data from Quandl. This will be familiar from the Notebook, but note in particular that we will use the value from the &lt;code&gt;input$frequency&lt;/code&gt; choice because Quandl uses the “daily/weekly/monthly” frequency format.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Let&amp;#39;s pull in the Quandl data. 
# Nothing fancy here except we are going to use the reactive inputs.
# We will pass in the value from the input$dataSet key-value pair.
# We will also pass in the value from the input$frequency key-value pair. 

commodity &amp;lt;- reactive({
  # It might be a good idea to include your quandl api key if this will be used more than 50 times in a day. 
  Quandl.api_key(&amp;quot;your_apikey_here&amp;quot;)
  
  commodity &amp;lt;- Quandl(input$dataSet,
                      start_date = format(input$dateRange[1]),
                      end_date = format(input$dateRange[2]),
                      order = &amp;quot;asc&amp;quot;,
                      type = &amp;quot;xts&amp;quot;,
                      collapse = as.character(input$frequency)
  )
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We have imported a time series object for the dataset, date range and frequency chosen by the user. Now we want to do some forecasting and create a visualization. We’ll first use the &lt;code&gt;forecast()&lt;/code&gt; function, then we’ll combine the forecasted prices and the historical prices into one xts object that can be passed to dygraph. Let’s handle this in one reactive.&lt;/p&gt;
&lt;p&gt;First, we’ll call &lt;code&gt;forecast&lt;/code&gt; and pass it the &lt;code&gt;periods&lt;/code&gt; input from the user.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;combined_xts &amp;lt;- reactive({
  
  # Just like the Notebook, except periods is a reactive input.
  
  forecasted &amp;lt;- forecast(commodity(), h = input$periods)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we need to combine that forecasted object with the commodity object that was created in a previous code chunk. Here we will finally thank ourselves for thinking about the name-value issue when assigning &lt;code&gt;frequencyChoices&lt;/code&gt;. When we create a dataframe to hold the forecasted time series, we build a ‘date’ column using the &lt;code&gt;seq()&lt;/code&gt; function. The column starts on the end date of the historical data (which the user selected with the &lt;code&gt;dateRange&lt;/code&gt; input) and runs for as many periods as the user chose in the &lt;code&gt;periods&lt;/code&gt; input. But, we need to supply a value to the &lt;code&gt;by = ...&lt;/code&gt; argument of the &lt;code&gt;seq()&lt;/code&gt; function so that it knows if we want to move 6 days, 6 weeks, 6 months, etc. To do that, we need to extract the name (“days/weeks/months”) from the &lt;code&gt;frequencyChoices&lt;/code&gt; name-value pair and pass it to seq. The way we extract the name is with this selection statement: &lt;code&gt;names(frequencyChoices[frequencyChoices == input$frequency])&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;  forecast_dataframe &amp;lt;- data.frame(
    date = seq(input$dateRange[2], 
               # The next line is very important, and it&amp;#39;s the reason we 
               # created the frequencyChoices object.
               by = names(frequencyChoices[frequencyChoices == input$frequency]),
               length.out = input$periods),
    Forecast = forecasted$mean,
    Hi_95 = forecasted$upper[,2],
    Lo_95 = forecasted$lower[,2])&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we convert the &lt;code&gt;forecast_dataframe&lt;/code&gt; object to an xts and combine that new object with the &lt;code&gt;commodity&lt;/code&gt; xts object. Remember, we imported the commodity data from Quandl in the form of an xts object, which saved us from having to do a conversion. This chunk should look very similar to the Notebook.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;  forecast_xts &amp;lt;- xts(forecast_dataframe[,-1], order.by = forecast_dataframe[,1])
  
  combined_xts &amp;lt;- cbind(commodity(), forecast_xts)
  
  # Add a nicer name for the first column.
  
  colnames(combined_xts)[1] &amp;lt;- &amp;quot;Actual&amp;quot;
  
  # This is the combined object that will be passed to dygraphs below. 
  combined_xts
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we will create a chart of the actual price history. Nothing fancy here, except again we are going extract the ‘name’ portion of a name-value pair, this time from the &lt;code&gt;dataSet&lt;/code&gt; object (the first one we created in the first code chunk). We want to label the graph with ‘WTI oil’ and not the Quandl code, so we select the name with &lt;code&gt;names(dataChoices[dataChoices==input$dataSet])&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dygraphOutput(&amp;quot;commodity&amp;quot;)

output$commodity &amp;lt;- renderDygraph({
  dygraph(commodity(),
          # We pull out the name of the selected name-value input$dataSet like so: 
          # names(dataChoices[dataChoices==input$dataSet])
          main = paste(&amp;quot;Price history of&amp;quot;, names(dataChoices[dataChoices==input$dataSet]), 
                       sep = &amp;quot; &amp;quot;)) %&amp;gt;%
    dyAxis(&amp;quot;y&amp;quot;, label = &amp;quot;$&amp;quot;) %&amp;gt;%
    dyOptions(axisLineWidth = 1.5, fillGraph = TRUE, drawGrid = TRUE)
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Last but not least, let’s graph the historical and forecasted time series together on one graph. We could have ported the code directly from the Notebook, but I couldn’t help tinkering just a bit. I wanted to focus the graph on the time period around where the actual data ends and the forecast begins, because that is probably what’s of most interest to the user. To do that, we’ll use the &lt;code&gt;dyRangeSelector()&lt;/code&gt; function and pass two values to the &lt;code&gt;dateWindow&lt;/code&gt; variable: a start date and end an date. This is pure aesthetics, but I think it’s worth the effort here.&lt;/p&gt;
&lt;p&gt;We are going to use &lt;code&gt;seq()&lt;/code&gt; and &lt;code&gt;names(frequencyChoices[frequencyChoices == input$frequency])&lt;/code&gt; once again.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dygraphOutput(&amp;quot;forecasted&amp;quot;)

output$forecasted &amp;lt;- renderDygraph({

# We want the user to be able to see the forecasted area, so let&amp;#39;s focus in on that 
# by truncating the view of the dygraph.
# We need to give the graph a start date and an end date. 
start_date &amp;lt;- tail(seq(input$dateRange[2], by = &amp;quot;-1 months&amp;quot;, length = 6), 1)
end_date &amp;lt;- tail(seq(input$dateRange[2], 
                     by = names(frequencyChoices[frequencyChoices == input$frequency]), 
                     length = input$periods), 1)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we will supply those date objects to a piped dygraphs chain, and that will be a wrap. Have a close look at the chunk below and spot where we again extract the name from the &lt;code&gt;input$dataSet&lt;/code&gt; name-value pair.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dygraph(combined_xts(), 
        # Name about to be extracted!
        main = paste(names(dataChoices[dataChoices==input$dataSet]), 
                     &amp;quot;: Historical and Forecast&amp;quot;, sep = &amp;quot;&amp;quot;)) %&amp;gt;%
  # Add the actual series.
  dySeries(&amp;quot;Actual&amp;quot;, label = &amp;quot;Actual&amp;quot;) %&amp;gt;%
  # Add the three forecasted series.
  dySeries(c(&amp;quot;Lo_95&amp;quot;, &amp;quot;Forecast&amp;quot;, &amp;quot;Hi_95&amp;quot;)) %&amp;gt;% 
  # A range selector to focus on the where historical data ends and 
  # foracated data begins.
  # Note the user can still use the range selector to zoom out if so desired.
  dyRangeSelector(dateWindow = c(start_date, end_date))
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That’s all for today! We’ve built an app that can be extended in many directions - more data set choices, an input selector so the user can choose different models, more visualizations - and in that sense it can serve as a template for ourselves and anyone that wants to build upon this work.&lt;/p&gt;
&lt;p&gt;This app also relies on and highlights one of the tremendous benefits of Quandl: the ability to import datasets from different sources and have them arrive in the IDE in a consistent format. This makes using Quandl with Shiny quite enjoyable after the initial skeleton is built. For example, if we or a colleague did want to change this app and substitute in different commodities, there would be no worry beyond the finding the right code on Quandl and adding another name-value pair to &lt;code&gt;dataChoices&lt;/code&gt;.&lt;/p&gt;

        &lt;script&gt;window.location.href=&#39;https://rviews.rstudio.com/2017/04/21/a-shiny-app-for-importing-and-forecasting-commodities-prices-from-quandl/&#39;;&lt;/script&gt;
      </description>
    </item>
    
  </channel>
</rss>
