If any issues, questions or suggestions feel free to reach me out via e-mail or Linkedin. You can also visit my Github.

if(!require(pacman)) install.packages('pacman')
pacman::p_load(PolishStock, dplyr, corrplot, lubridate, tidyr, ggplot2, stringr, ggrepel)

We will check Pearson correlation beetwen monthly log-returns of the following assets:
- WIG index
- yield of 10-years Polish bonds
- S&P500 index
- DAX index
- iShares MSCI Emerging Markets ETF
- USDPLN
- EURPLN
- Gold price (XAUUSD)
- Eurozone Manufacturing PMI.

We use PolishStock package to download the above data from the website stooq.pl. Monthly data for period June 2010 - February 2022 consists of 138 observations.

tickers <- c('WIG', '10PLY.B', '^SPX', '^DAX', 'EEM.US'
             ,'USDPLN', 'EURPLN', 'XAUUSD', 'PMMNEU.M')

# for (ticker in tickers) {
#   stooq_download(ticker
#                  ,start_date = 20100101
#                  ,end_date = 20222502
#                  ,interval = 'm'
#                  ,destination = paste0(getwd(), '/datasets/'))
# }

close_prices <- df_prices(paste0(tickers, '.csv')
                          ,source = 'datasets/')

returns <- data.frame(
  Date = close_prices$Date[-1]
  ,sapply(select(close_prices, -Date)
         ,FUN = function(x) diff(log(x), lag = 1))
)

colnames(returns) <- c('Date', 'WIG', '10Y Yield', 'S&P', 'DAX'
                       ,'EM', 'USDPLN', 'EURPLN', 'Gold', 'Euro PMI')
  

Pearson correlation coefficient shows linear relationships \(Y = aX +b\). When calculating it and making inferences, be aware of some pitfalls:
- if distribution of \(X\) and \(Y\) is far from bivariate normal then Pearson coefficient could exhibit linear relationship where in fact such relationship doesn’t exists; and remember that normality of marginal distributions don’t guarantee normality of joint distribution
- outliers in the dataset can influence interpretability of Pearson coefficient
- in the correlation context there is no sense in distiction beetwen dependent and independent variable; theoretically we don’t know if there is equation either \(Y = aX +b\) or equation \(X = a^{-1} (Y - b)\); if there really exists dependence beetwen variables, Pearson coefficient won’t tell us about it
- if there exists unknown factor \(Z\) which positively affects \(X\) and negatively affects \(Y\) then Pearson coefficient will be negative
- if \(X\) and \(Y\) are independent then Pearson coefficient is equal 0, but the reverse ain’t true
- Pearson coefficient doesn’t show proportion, e.g. we can’t say that correlation of \(0.6\) is \(2\) times higher than correlation of \(0.3\); however determination coefficient \(R^2\) which is in fact Pearson correlation squared shows us proportions.

Below we can see positive correlation beetwen WIG and DAX, S&P500, Emerging Markets. We can also see negative correlation beetwen WIG and USDPLN, EURPLN. There is no correlation beetwen WIG and 10Y Polish bonds yield and Eurozone Manufacturing PMI.

corr_matrix <- cor(select_if(returns, is.numeric)) %>%
  round(2)

corrplot(corr_matrix
         ,title = 'Pearson Correlation'
         ,mar = c(1,0,1,0)
         ,method = 'color'
         ,type = 'lower'
         ,order = 'alphabet'
         ,tl.col = 'black'
         ,tl.cex = 0.8
         ,tl.srt = 0
         ,addCoef.col = 'black'
         ,diag = FALSE
) 

However, above we calculated correlation for ~11 years time horizon. Now we calculate and visualize moving correlation for \(t = 1, \dots, 11\) years.

returns <- returns %>%
  mutate(Year = year(returns$Date))

moving_correlation <- data.frame(
  Index = names(select(returns, -Date, -Year))
)

for (i in 1:floor(nrow(returns) / 12)) {
  
  temp_corr_matrix <- returns %>%
    slice_tail(n = i * 12) %>%
    select(-Date, -Year) %>%
    cor() %>%
    round(2) %>%
    as.data.frame() %>%
    mutate(Index = row.names(.))
    
  moving_correlation <- moving_correlation %>%
    left_join(select(temp_corr_matrix, WIG, Index)
              ,by = c('Index' = 'Index'))
  
  colnames(moving_correlation)[i+1] <- paste0(i, '-years')
  
}

ggplot(moving_correlation %>%
  pivot_longer(cols = 2:ncol(moving_correlation)
               ,names_to = 'Variable'
               ,values_to = 'Value') %>%
    filter(Index != 'WIG') %>%
    mutate(Year = str_extract(Variable, '[0-9]*') %>%
             as.numeric()
           ,Label = if_else(Year == 8
                            ,as.character(Index)
                            ,NA_character_))) +
  geom_line(aes(x = reorder(Variable, -Year)
                ,y = Value
                ,group = Index
                ,color = Index)
            ,size = 1) +
  geom_label_repel(aes(x = reorder(Variable, -Year)
                       ,y = Value
                       ,label = Label
                       ,color = Index),
                  nudge_x = 1,
                  na.rm = TRUE
                  ,min.segment.length = 5) + 
  theme_bw() +
  theme(legend.position = 'none') +
  labs(x = '', y = '', title = 'Moving Correlation of WIG index')

LS0tDQp0aXRsZTogIkNvcnJlbGF0aW9uIGJlZXR3ZW4gV0lHIGluZGV4IGFuZCBvdGhlciBhc3NldHMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpJZiBhbnkgaXNzdWVzLCBxdWVzdGlvbnMgb3Igc3VnZ2VzdGlvbnMgZmVlbCBmcmVlIHRvIHJlYWNoIG1lIG91dCB2aWEgZS1tYWlsIDx3aWVjenluc2tpcGF3ZWxAZ21haWwuY29tPiBvciBbTGlua2VkaW5dKGh0dHBzOi8vd3d3LmxpbmtlZGluLmNvbS9pbi9wYXdlbC13aWVjenluc2tpLykuIFlvdSBjYW4gYWxzbyB2aXNpdCBteSBbR2l0aHViXShodHRwczovL2dpdGh1Yi5jb20vcGF3ZWwtd2llY3p5bnNraSkuDQoNCmBgYHtyIGxpYnJhcmllcywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCmlmKCFyZXF1aXJlKHBhY21hbikpIGluc3RhbGwucGFja2FnZXMoJ3BhY21hbicpDQpwYWNtYW46OnBfbG9hZChQb2xpc2hTdG9jaywgZHBseXIsIGNvcnJwbG90LCBsdWJyaWRhdGUsIHRpZHlyLCBnZ3Bsb3QyLCBzdHJpbmdyLCBnZ3JlcGVsKQ0KYGBgDQoNCldlIHdpbGwgY2hlY2sgUGVhcnNvbiBjb3JyZWxhdGlvbiBiZWV0d2VuIG1vbnRobHkgbG9nLXJldHVybnMgb2YgdGhlIGZvbGxvd2luZyBhc3NldHM6IFwNCiAtIFdJRyBpbmRleCBcDQogLSB5aWVsZCBvZiAxMC15ZWFycyBQb2xpc2ggYm9uZHMgXA0KIC0gUyZQNTAwIGluZGV4IFwNCiAtIERBWCBpbmRleCBcDQogLSBpU2hhcmVzIE1TQ0kgRW1lcmdpbmcgTWFya2V0cyBFVEYgXA0KIC0gVVNEUExOIFwNCiAtIEVVUlBMTiBcDQogLSBHb2xkIHByaWNlIChYQVVVU0QpIFwNCiAtIEV1cm96b25lIE1hbnVmYWN0dXJpbmcgUE1JLg0KDQpXZSB1c2UgW1BvbGlzaFN0b2NrIHBhY2thZ2VdKGh0dHBzOi8vZ2l0aHViLmNvbS9wYXdlbC13aWVjenluc2tpL1BvbGlzaFN0b2NrKSB0byBkb3dubG9hZCB0aGUgYWJvdmUgZGF0YSBmcm9tIHRoZSB3ZWJzaXRlIFtzdG9vcS5wbF0oaHR0cHM6Ly9zdG9vcS5wbC8pLiBNb250aGx5IGRhdGEgZm9yIHBlcmlvZCBKdW5lIDIwMTAgLSBGZWJydWFyeSAyMDIyIGNvbnNpc3RzIG9mIDEzOCBvYnNlcnZhdGlvbnMuDQpgYGB7ciBnZXRfZGF0YX0NCnRpY2tlcnMgPC0gYygnV0lHJywgJzEwUExZLkInLCAnXlNQWCcsICdeREFYJywgJ0VFTS5VUycNCiAgICAgICAgICAgICAsJ1VTRFBMTicsICdFVVJQTE4nLCAnWEFVVVNEJywgJ1BNTU5FVS5NJykNCg0KZm9yICh0aWNrZXIgaW4gdGlja2Vycykgew0KICBzdG9vcV9kb3dubG9hZCh0aWNrZXINCiAgICAgICAgICAgICAgICAgLHN0YXJ0X2RhdGUgPSAyMDEwMDEwMQ0KICAgICAgICAgICAgICAgICAsZW5kX2RhdGUgPSAyMDIyMjUwMg0KICAgICAgICAgICAgICAgICAsaW50ZXJ2YWwgPSAnbScNCiAgICAgICAgICAgICAgICAgLGRlc3RpbmF0aW9uID0gcGFzdGUwKGdldHdkKCksICcvZGF0YXNldHMvJykpDQp9DQoNCmNsb3NlX3ByaWNlcyA8LSBkZl9wcmljZXMocGFzdGUwKHRpY2tlcnMsICcuY3N2JykNCiAgICAgICAgICAgICAgICAgICAgICAgICAgLHNvdXJjZSA9ICdkYXRhc2V0cy8nKQ0KDQpyZXR1cm5zIDwtIGRhdGEuZnJhbWUoDQogIERhdGUgPSBjbG9zZV9wcmljZXMkRGF0ZVstMV0NCiAgLHNhcHBseShzZWxlY3QoY2xvc2VfcHJpY2VzLCAtRGF0ZSkNCiAgICAgICAgICxGVU4gPSBmdW5jdGlvbih4KSBkaWZmKGxvZyh4KSwgbGFnID0gMSkpDQopDQoNCmNvbG5hbWVzKHJldHVybnMpIDwtIGMoJ0RhdGUnLCAnV0lHJywgJzEwWSBZaWVsZCcsICdTJlAnLCAnREFYJw0KICAgICAgICAgICAgICAgICAgICAgICAsJ0VNJywgJ1VTRFBMTicsICdFVVJQTE4nLCAnR29sZCcsICdFdXJvIFBNSScpDQogIA0KYGBgDQoNClBlYXJzb24gY29ycmVsYXRpb24gY29lZmZpY2llbnQgc2hvd3MgbGluZWFyIHJlbGF0aW9uc2hpcHMgJFkgPSBhWCArYiQuIFdoZW4gY2FsY3VsYXRpbmcgaXQgYW5kIG1ha2luZyBpbmZlcmVuY2VzLCBiZSBhd2FyZSBvZiBzb21lIHBpdGZhbGxzOiBcDQogLSBpZiBkaXN0cmlidXRpb24gb2YgJFgkIGFuZCAkWSQgaXMgZmFyIGZyb20gYml2YXJpYXRlIG5vcm1hbCB0aGVuIFBlYXJzb24gY29lZmZpY2llbnQgY291bGQgZXhoaWJpdCBsaW5lYXIgcmVsYXRpb25zaGlwIHdoZXJlIGluIGZhY3Qgc3VjaCByZWxhdGlvbnNoaXAgZG9lc24ndCBleGlzdHM7IGFuZCByZW1lbWJlciB0aGF0IG5vcm1hbGl0eSBvZiBtYXJnaW5hbCBkaXN0cmlidXRpb25zIGRvbid0IGd1YXJhbnRlZSBub3JtYWxpdHkgb2Ygam9pbnQgZGlzdHJpYnV0aW9uIFwNCiAtIG91dGxpZXJzIGluIHRoZSBkYXRhc2V0IGNhbiBpbmZsdWVuY2UgaW50ZXJwcmV0YWJpbGl0eSBvZiBQZWFyc29uIGNvZWZmaWNpZW50IFwNCiAtIGluIHRoZSBjb3JyZWxhdGlvbiBjb250ZXh0IHRoZXJlIGlzIG5vIHNlbnNlIGluIGRpc3RpY3Rpb24gYmVldHdlbiBkZXBlbmRlbnQgYW5kIGluZGVwZW5kZW50IHZhcmlhYmxlOyB0aGVvcmV0aWNhbGx5IHdlIGRvbid0IGtub3cgaWYgdGhlcmUgaXMgZXF1YXRpb24gZWl0aGVyICRZID0gYVggK2IkIG9yIGVxdWF0aW9uICRYID0gYV57LTF9IChZIC0gYikkOyBpZiB0aGVyZSByZWFsbHkgZXhpc3RzIGRlcGVuZGVuY2UgYmVldHdlbiB2YXJpYWJsZXMsIFBlYXJzb24gY29lZmZpY2llbnQgd29uJ3QgdGVsbCB1cyBhYm91dCBpdCBcDQogLSBpZiB0aGVyZSBleGlzdHMgdW5rbm93biBmYWN0b3IgJFokIHdoaWNoIHBvc2l0aXZlbHkgYWZmZWN0cyAkWCQgYW5kIG5lZ2F0aXZlbHkgYWZmZWN0cyAkWSQgdGhlbiBQZWFyc29uIGNvZWZmaWNpZW50IHdpbGwgYmUgbmVnYXRpdmUgXA0KIC0gaWYgJFgkIGFuZCAkWSQgYXJlIGluZGVwZW5kZW50IHRoZW4gUGVhcnNvbiBjb2VmZmljaWVudCBpcyBlcXVhbCAwLCAqKmJ1dCB0aGUgcmV2ZXJzZSBhaW4ndCB0cnVlKiogXA0KIC0gUGVhcnNvbiBjb2VmZmljaWVudCBkb2Vzbid0IHNob3cgcHJvcG9ydGlvbiwgZS5nLiAgd2UgY2FuJ3Qgc2F5IHRoYXQgY29ycmVsYXRpb24gb2YgJDAuNiQgaXMgJDIkIHRpbWVzIGhpZ2hlciB0aGFuIGNvcnJlbGF0aW9uIG9mICQwLjMkOyBob3dldmVyIGRldGVybWluYXRpb24gY29lZmZpY2llbnQgJFJeMiQgd2hpY2ggaXMgaW4gZmFjdCBQZWFyc29uIGNvcnJlbGF0aW9uIHNxdWFyZWQgc2hvd3MgdXMgcHJvcG9ydGlvbnMuDQoNCkJlbG93IHdlIGNhbiBzZWUgcG9zaXRpdmUgY29ycmVsYXRpb24gYmVldHdlbiBXSUcgYW5kIERBWCwgUyZQNTAwLCBFbWVyZ2luZyBNYXJrZXRzLiBXZSBjYW4gYWxzbyBzZWUgbmVnYXRpdmUgY29ycmVsYXRpb24gYmVldHdlbiBXSUcgYW5kIFVTRFBMTiwgRVVSUExOLiBUaGVyZSBpcyBubyBjb3JyZWxhdGlvbiBiZWV0d2VuIFdJRyBhbmQgMTBZIFBvbGlzaCBib25kcyB5aWVsZCBhbmQgRXVyb3pvbmUgTWFudWZhY3R1cmluZyBQTUkuDQoNCmBgYHtyIGNvcnJlbGF0aW9uX21hdHJpeH0NCmNvcnJfbWF0cml4IDwtIGNvcihzZWxlY3RfaWYocmV0dXJucywgaXMubnVtZXJpYykpICU+JQ0KICByb3VuZCgyKQ0KDQpjb3JycGxvdChjb3JyX21hdHJpeA0KICAgICAgICAgLHRpdGxlID0gJ1BlYXJzb24gQ29ycmVsYXRpb24nDQogICAgICAgICAsbWFyID0gYygxLDAsMSwwKQ0KICAgICAgICAgLG1ldGhvZCA9ICdjb2xvcicNCiAgICAgICAgICx0eXBlID0gJ2xvd2VyJw0KICAgICAgICAgLG9yZGVyID0gJ2FscGhhYmV0Jw0KICAgICAgICAgLHRsLmNvbCA9ICdibGFjaycNCiAgICAgICAgICx0bC5jZXggPSAwLjgNCiAgICAgICAgICx0bC5zcnQgPSAwDQogICAgICAgICAsYWRkQ29lZi5jb2wgPSAnYmxhY2snDQogICAgICAgICAsZGlhZyA9IEZBTFNFDQopIA0KYGBgDQpIb3dldmVyLCBhYm92ZSB3ZSBjYWxjdWxhdGVkIGNvcnJlbGF0aW9uIGZvciB+MTEgeWVhcnMgdGltZSBob3Jpem9uLiBOb3cgd2UgY2FsY3VsYXRlIGFuZCB2aXN1YWxpemUgbW92aW5nIGNvcnJlbGF0aW9uIGZvciAkdCA9IDEsIFxkb3RzLCAxMSQgeWVhcnMuDQpgYGB7ciBtb3ZpbmdfY29ycmVsYXRpb259DQpyZXR1cm5zIDwtIHJldHVybnMgJT4lDQogIG11dGF0ZShZZWFyID0geWVhcihyZXR1cm5zJERhdGUpKQ0KDQptb3ZpbmdfY29ycmVsYXRpb24gPC0gZGF0YS5mcmFtZSgNCiAgSW5kZXggPSBuYW1lcyhzZWxlY3QocmV0dXJucywgLURhdGUsIC1ZZWFyKSkNCikNCg0KZm9yIChpIGluIDE6Zmxvb3IobnJvdyhyZXR1cm5zKSAvIDEyKSkgew0KICANCiAgdGVtcF9jb3JyX21hdHJpeCA8LSByZXR1cm5zICU+JQ0KICAgIHNsaWNlX3RhaWwobiA9IGkgKiAxMikgJT4lDQogICAgc2VsZWN0KC1EYXRlLCAtWWVhcikgJT4lDQogICAgY29yKCkgJT4lDQogICAgcm91bmQoMikgJT4lDQogICAgYXMuZGF0YS5mcmFtZSgpICU+JQ0KICAgIG11dGF0ZShJbmRleCA9IHJvdy5uYW1lcyguKSkNCiAgICANCiAgbW92aW5nX2NvcnJlbGF0aW9uIDwtIG1vdmluZ19jb3JyZWxhdGlvbiAlPiUNCiAgICBsZWZ0X2pvaW4oc2VsZWN0KHRlbXBfY29ycl9tYXRyaXgsIFdJRywgSW5kZXgpDQogICAgICAgICAgICAgICxieSA9IGMoJ0luZGV4JyA9ICdJbmRleCcpKQ0KICANCiAgY29sbmFtZXMobW92aW5nX2NvcnJlbGF0aW9uKVtpKzFdIDwtIHBhc3RlMChpLCAnLXllYXJzJykNCiAgDQp9DQoNCmdncGxvdChtb3ZpbmdfY29ycmVsYXRpb24gJT4lDQogIHBpdm90X2xvbmdlcihjb2xzID0gMjpuY29sKG1vdmluZ19jb3JyZWxhdGlvbikNCiAgICAgICAgICAgICAgICxuYW1lc190byA9ICdWYXJpYWJsZScNCiAgICAgICAgICAgICAgICx2YWx1ZXNfdG8gPSAnVmFsdWUnKSAlPiUNCiAgICBmaWx0ZXIoSW5kZXggIT0gJ1dJRycpICU+JQ0KICAgIG11dGF0ZShZZWFyID0gc3RyX2V4dHJhY3QoVmFyaWFibGUsICdbMC05XSonKSAlPiUNCiAgICAgICAgICAgICBhcy5udW1lcmljKCkNCiAgICAgICAgICAgLExhYmVsID0gaWZfZWxzZShZZWFyID09IDgNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAsYXMuY2hhcmFjdGVyKEluZGV4KQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICxOQV9jaGFyYWN0ZXJfKSkpICsNCiAgZ2VvbV9saW5lKGFlcyh4ID0gcmVvcmRlcihWYXJpYWJsZSwgLVllYXIpDQogICAgICAgICAgICAgICAgLHkgPSBWYWx1ZQ0KICAgICAgICAgICAgICAgICxncm91cCA9IEluZGV4DQogICAgICAgICAgICAgICAgLGNvbG9yID0gSW5kZXgpDQogICAgICAgICAgICAsc2l6ZSA9IDEpICsNCiAgZ2VvbV9sYWJlbF9yZXBlbChhZXMoeCA9IHJlb3JkZXIoVmFyaWFibGUsIC1ZZWFyKQ0KICAgICAgICAgICAgICAgICAgICAgICAseSA9IFZhbHVlDQogICAgICAgICAgICAgICAgICAgICAgICxsYWJlbCA9IExhYmVsDQogICAgICAgICAgICAgICAgICAgICAgICxjb2xvciA9IEluZGV4KSwNCiAgICAgICAgICAgICAgICAgIG51ZGdlX3ggPSAxLA0KICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFDQogICAgICAgICAgICAgICAgICAsbWluLnNlZ21lbnQubGVuZ3RoID0gNSkgKyANCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdub25lJykgKw0KICBsYWJzKHggPSAnJywgeSA9ICcnLCB0aXRsZSA9ICdNb3ZpbmcgQ29ycmVsYXRpb24gb2YgV0lHIGluZGV4JykNCg0KYGBg