Food Crisis Analysis and, Forecasting with Neural Network Autoregression

The war between Russia and Ukraine has affected the global food supply other than many vital things. Primarily cereal crop products have been affected the most because the imports have been provided to the world mainly through Ukraine and Russia. Let’s check the situation we’ve mentioned for G20 countries.

library(tidyverse)
library(fpp3)
library(bbplot)
library(plotly) 
  

food <- read_csv("https://raw.githubusercontent.com/mesdi/wheat/main/ukraine-russia-food.csv")

#G20 countries
g20 <- c("Argentina", "Australia", "Brazil", "Canada", "China", "France", 
         "Germany", "India", "Indonesia", "Italy", "Japan", "South Korea", 
         "Mexico", "Saudi Arabia", "South Africa", "Turkey", "United Kingdom",
         "United States")

We will get a look at the 2010-2019 import shares totals of barley, maize(corn), sunflower oil, and wheat for the domestic supply. If we hoover at the chart bars, we can see the last year’s (2019) rates of imports for the interested country and product.

#Comparing the G20 Countries' Imported Crops 
#for Domestic Supply(%) from Russia or Ukraine 
p <- 
  food %>% 
  select(Entity, 
           Year, 
           `Barley imports from Ukraine + Russia (% supply)`,
           `Maize imports from Ukraine + Russia (% supply)`,
           `Sunflower oil imports from Ukraine + Russia (% supply)`,
           `Wheat imports from Ukraine + Russia (% supply)`) %>% 
    rename(Barley=`Barley imports from Ukraine + Russia (% supply)`,
           Maize=`Maize imports from Ukraine + Russia (% supply)`,
           `Sunflower oil`=`Sunflower oil imports from Ukraine + Russia (% supply)`,
           Wheat=`Wheat imports from Ukraine + Russia (% supply)`) %>% 
    mutate(across(where(is.numeric), ~replace_na(.,0))) %>% 
    filter(Entity %in% g20) %>% 
    pivot_longer(cols = -c(Entity,Year),names_to = "Crops",values_to = "n") %>% 
    group_by(Entity,Crops) %>% 
    summarise(total=sum(n),
              #tooltip text showing the last year's values for plotly chart
              percent=paste0(round(last(n),2),"%\nin 2019")) %>% 
    arrange(desc(total),.by_group = TRUE) %>% #ranking stacked fill descending
    ggplot(aes(Entity, total, group=Entity, fill= Crops, text=percent)) +
    geom_bar(stat = "identity", position = "fill")+
    bbc_style()+
    scale_y_continuous(labels = scales::percent)+
    coord_flip()+
    theme(legend.position = "top", 
          legend.justification = "center",
          panel.grid.major.y = element_blank(),
          title = element_text(size=5))
  


#Plotly Graph
ggplotly(p,tooltip = "text") %>% 
  #adjusting legend position to top and center 
  layout(legend = list(orientation = "h",
                       y =1.1,
                       x=0.25,
                       title=""),
         margin=list(r=50) #gives space to the hover information
         )

It seems that sunflower oil is the most dominant imported cereal crop; specifically, when we hover over China, we see that %86.47 of the domestic supply was acquired from those countries in 2019. And it is clear that Brazil and Argentina do not need those crops arriving from Russia and Ukraine.

We will now examine the impact of this situation on US wheat futures prices. We will predict weekly prices for the next year with the neural network autoregression model (NNAR).

wheat_future <- read_csv("https://raw.githubusercontent.com/mesdi/wheat/main/us_wheat_futures.csv")

wheat_ts <- 
  wheat_future %>% 
  #removes comma and then converts to the proper date format
  mutate(Date= parse_date(str_remove(Date,"\\,"),"%b %d %Y")) %>% 
  as_tsibble() %>% 
  fill_gaps() %>% #fills the gaps with NAs to provide regular time series
  fill(Price,.direction = "down") #replaces the NAs with the previous value

We can see from the below results that our model has 19 lagged inputs and ten nodes in the hidden layer.

set.seed(123)  

#NNAR modeling
fit_wheat <- 
  wheat_ts %>% 
  model(NNETAR(Price)) 
# A mable: 1 x 1
#  `NNETAR(Price)`
#          <model>
#1   <NNAR(19,10)>

To check our model, we have to do a residual diagnostic test. So, we can see whether there is some correlation and the distribution of residuals is similar to that normally distributed.

#Model residuals diagnostics
fit_wheat %>% 
  gg_tsresiduals()

All the lags are between the threshold lines so that there is no correlation, as seen on the ACF graph. When we look at the residual time plot, we can say that around zero mean and approximately constant variance across the historical data which means the distribution is similar to normal.

Now, we can make forecasting; in order to do that, we will do simulations with our model.

#Projection of prices of the US wheat futures 

fit_wheat %>% 
  generate(times = 100, h = 52) %>%
  autoplot(.sim) +
  autolayer(wheat_ts, Price) +
  scale_x_yearweek(date_breaks="104 week")+
  labs(title="1-Year Projection of US Wheat Futures (ZWU2) Prices",
       xlab="",
       ylab="")+
  bbc_style()+
  theme(legend.position = "none",
        axis.text.x=element_text(size=15),
        plot.title = element_text(size=20,hjust=0.5))

We clearly see that the prices were up above the 1200s because of the war, and then come back to around the 900s. But it seems for the next one-year period the prices will go down to about 600-700s.

2 thoughts on “Food Crisis Analysis and, Forecasting with Neural Network Autoregression

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: