I denne labben skal vi bruke noen av verktøyene vi har lært for å analysere hvordan oljeprisen utvikler seg - økonometrisk-sett, og hvordan den påvirker noen aspekter av den norske økonomien.
library(ggplot2)
library(reshape2)
library(dplyr)
library(foreign)
library(dynlm)
library(zoo)
Som i labb 10 (tidsrekkregresjon 2), begynner vi med å laste ned data om oljeprisen fra FRED-webside:
oil_price_series <- read.csv("https://fred.stlouisfed.org/graph/fredgraph.csv?chart_type=line&recession_bars=on&log_scales=&bgcolor=%23e1e9f0&graph_bgcolor=%23ffffff&fo=Open+Sans&ts=12&tts=12&txtcolor=%23444444&show_legend=yes&show_axis_titles=yes&drp=0&cosd=1987-05-01&coed=2018-09-01&height=450&stacking=&range=&mode=fred&id=MCOILBRENTEU&transformation=lin&nd=1987-05-01&ost=-99999&oet=99999&lsv=&lev=&mma=0&fml=a&fgst=lin&fgsnd=2009-06-01&fq=Monthly&fam=avg&vintage_date=&revision_date=&line_color=%234572a7&line_style=solid&lw=2&scale=left&mark_type=none&mw=2&width=1168")
Og litt rengjøring…
brent <- oil_price_series
colnames(brent) <- c("date", "brentprice")
brent["date"] <- as.Date(brent$date)
ggplot(brent, aes(date, brentprice)) +
geom_line()
Vi setter den i time-series formatt:
brent_ts <- ts(brent$brentprice, start=c(1980,1), end=c(2016,8), frequency=12)
Vi kan først kjøre en regresjon av \(y_t\) på en lagged \(y_{t-1}\) for å sjekke.
I1_mod <- dynlm(brent_ts~ L(brent_ts))
summary(I1_mod)
##
## Time series regression with "ts" data:
## Start = 1980(2), End = 2016(8)
##
## Call:
## dynlm(formula = brent_ts ~ L(brent_ts))
##
## Residuals:
## Min 1Q Median 3Q Max
## -59.846 -1.345 -0.022 1.547 14.578
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.537480 0.400395 1.342 0.18
## L(brent_ts) 0.987300 0.007575 130.344 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 5.089 on 437 degrees of freedom
## Multiple R-squared: 0.9749, Adjusted R-squared: 0.9749
## F-statistic: 1.699e+04 on 1 and 437 DF, p-value: < 2.2e-16
Vi estimerer en koeffisient ganske nær 1, så det lover dårlig. Vi kan også kjøre en ADF test.
library(tseries)
adf.test(brent_ts)
##
## Augmented Dickey-Fuller Test
##
## data: brent_ts
## Dickey-Fuller = -1.6184, Lag order = 7, p-value = 0.739
## alternative hypothesis: stationary
Tolkning: I vår Augmented Dickey-Fuller testen er alternative hypotesen at serien er stasjonær. Vi får en Dickey-Fuller test-statistikk på -1.35 og p-verdi av 0,825. Det vil si at under vår null-hypotese av en ikke-stasjonær serie, ville vi fått test-stastistikk som er lavere (mer negativ) 82% av tiden. Hvis vi har en cut-off verdi av 5%, så er vi langt fra å kunne forkaste vår null-hypotese. Vi burde anta, dermed at vi har en stasjonær serie.
Men vi kan gjøre serien om til avkastninger (prosent endringer) og se om det fikser problemet.
brent_ret <- diff(log(brent_ts))
Nå, kan vi se på den nye serien
plot(brent_ret)
Denne ser mer stasjonær ut - den har en noe-lunde konstant varians og en gjennomsnittsverdi som serien beveger seg rundt, men vi kan sjekke formelt med en adf-test:
#vi kvitter oss med manglede (NA) data
brent_ret <- brent_ret[!is.na(brent_ret)]
#dickey-fuller test
adf.test(brent_ret, k=1)
## Warning in adf.test(brent_ret, k = 1): p-value smaller than printed p-value
##
## Augmented Dickey-Fuller Test
##
## data: brent_ret
## Dickey-Fuller = -13.624, Lag order = 1, p-value = 0.01
## alternative hypothesis: stationary
Her ser vi at Dickey-Fuller testen er -13.48 med p-verdi av 0,01. Det betyr at hvis null-hypotesen er riktig (ikke-stasjonær), så vil vi få en test-statistikk av mindre (mer negativ) enn -13.48 1 prosent av tiden. Hvis vi har en cut-off verdi av 5%, så kan vi forkaste vår null-hypotese. Vi tror nå at vår serie er stasjonær.
Vi kan begynne med å kjøre en dynamisk regresjon med lagger:
ac_mod <- dynlm(brent_ret ~ lag(brent_ret) + lag(brent_ret,2) + lag(brent_ret, 3))
summary(ac_mod)
##
## Time series regression with "numeric" data:
## Start = 1, End = 436
##
## Call:
## dynlm(formula = brent_ret ~ lag(brent_ret) + lag(brent_ret, 2) +
## lag(brent_ret, 3))
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.46051 -0.04991 0.00512 0.05859 0.43626
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.0001245 0.0053999 0.023 0.981621
## lag(brent_ret) 0.1682126 0.0481126 3.496 0.000521 ***
## lag(brent_ret, 2) -0.0115854 0.0487879 -0.237 0.812409
## lag(brent_ret, 3) -0.0024219 0.0481242 -0.050 0.959886
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.1128 on 432 degrees of freedom
## (3 observations deleted due to missingness)
## Multiple R-squared: 0.02778, Adjusted R-squared: 0.02103
## F-statistic: 4.115 on 3 and 432 DF, p-value: 0.006771
Ja, det ser ut som det finnes autokorrelasjon, men bare med en lag.
En måte å måle og visualisere hvor autokorrelert et datasett er er å bruke en “autocorrelation function” (acf) eller “partial autocorrlation function”.
acf(brent_ret)
pacf(brent_ret)
Fra pacf-funksjonen, ser det ut som den første laggen er signifikant (den går over streken), men autokorrelasjonen dør ut snart etter. Dette tilsvarer det vi fant i vår dynamisk regresjon.
Rent bokstavelig, autokorrelasjon betyr at en endring i oljeprisen i denne måneden sier noe om oljeprisen neste måned. Siden koefisienten var positiv, kan vi si at en økning i oljeprisen denne måneden gir en økt sansynlighet for en økning i oljeprisen neste måned.
Vi kan også knytte dette til “efficient market” teori. Hvis oljemarkedet var en “perfectly efficient market”, så ville det si at alt relevant informasjon om oljemarkedet er inkludert i dagens oljepris. Det ville også bety at det er umulig å bruke tidligere verdier av oljeprisen til å predikere dagens pris. Grunnen for det er at i en perfekt marked, ville noen ha kjøpt eller solgt kontrakter for olje og tjent penger på det. At vi klarer å delvis forutsi bevegelser i oljeprisen betyr at det er noen friksjoner i markedet - det vil si at det er begrensninger til arbitrage.
La oss prøve å analysere forholdet mellom kronekurset og oljeprisen.
Vi laster inn data om valutakurs fra Norges Bank
kronekurs <- read.csv("http://static.norges-bank.no/globalassets/marketdata/stat/valutakurser/sdv/valuta_mnd.csv", header=TRUE, sep=",")
Vi er kun interessert i NOK/USD-kurset, så vi trekker den ut:
kronekurs <- kronekurs[,c("Date", "X1.USD")]
#endrer variablenavn:
colnames(kronekurs) <- c("date", "NOK_USD")
#konvertere til dato-formatt via as.yearmon funksjonen i zoo.
dates = as.yearmon(kronekurs$date, format="%b-%y")
kronekurs["date"] <- as.Date(dates)
#få valutakurs-formatt
kronekurs["USD_NOK"] <- 1/kronekurs["NOK_USD"]
A.) Bruk merge til å sette sammen oljepris-serien og kronekurs serien i en dataframe.
B.) Konvertere begge seriene til zoo formatt.
C.) Plotte begge serien.
#bruker month og year, og funksjonen merge til å sette sammen seriene
oil_krone <- merge(brent, kronekurs, id="date")
head(oil_krone)
## date brentprice NOK_USD USD_NOK
## 1 1987-05-01 18.58 6.6506 0.1503624
## 2 1987-06-01 18.86 6.7124 0.1489780
## 3 1987-07-01 19.86 6.7549 0.1480407
## 4 1987-08-01 18.98 6.7915 0.1472429
## 5 1987-09-01 18.31 6.6442 0.1505072
## 6 1987-10-01 18.76 6.6273 0.1508910
#Klassifiserer oljeprisen og kronekurs som zoo-serie
oil_krone_zoo <- zoo(oil_krone[c("brentprice", "USD_NOK")], order.by=oil_krone$date)
plot(x=oil_krone_zoo)
Nå at vi har en datasett vi kan jobbe med, kjør en modell som analyserer forholdet mellom oljepris og kronekurs. Hvordan tolker du resultatet? Hvilken tekniske betingelser burde man sjekke?
Det første vi burde se er at våre serier er ikke stasjonære. Vi har testet dette allerede med vår oljepris data. Vi kan gjøre det samme med kronekurset
library(tseries)
adf.test(oil_krone_zoo$USD_NOK, k=1)
##
## Augmented Dickey-Fuller Test
##
## data: oil_krone_zoo$USD_NOK
## Dickey-Fuller = -2.5828, Lag order = 1, p-value = 0.331
## alternative hypothesis: stationary
Her får vi en Dickey-Fuller statistikk som er -2.57 og en p-verdi av .33. Det betyr at under vår null-hypotese (der vi antar ikke-stasjonæritet), så er det en 33 prosent sjanse at man får -2.57 eller lavere. Dette er ikke godt nok for oss å forkaste null-hypotesen. Vi må gå ut i fra at denne serien også er ikke-stasjonær.
En løsning er da å transfomere vår data til avkastninger.
oil_krone["oil_price_ret"] <- log(oil_krone$brentprice) - lag(log(oil_krone$brentprice))
oil_krone["USD_NOK_ret"] <- log(oil_krone$USD_NOK) - lag(log(oil_krone$USD_NOK))
#ta vekk første raden (NA verdier)
oil_krone = oil_krone[-1,]
Vi kan først sjekk for autokorrelasjon i våre transformerte serier.
pacf(oil_krone$oil_price_ret)
pacf(oil_krone$USD_NOK_ret)
Det ser ut som det er en eller to lagger i kronekurset og en i oljeprisen. Vi vil modellere dette direkt.
krone_mod <- dynlm(USD_NOK_ret ~ lag(USD_NOK_ret) + lag(USD_NOK_ret,2) + oil_price_ret + lag(oil_price_ret), data=oil_krone)
summary(krone_mod)
##
## Time series regression with "numeric" data:
## Start = 1, End = 374
##
## Call:
## dynlm(formula = USD_NOK_ret ~ lag(USD_NOK_ret) + lag(USD_NOK_ret,
## 2) + oil_price_ret + lag(oil_price_ret), data = oil_krone)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.085805 -0.015103 -0.000259 0.013960 0.052138
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.000710 0.001144 -0.621 0.535
## lag(USD_NOK_ret) 0.344033 0.052022 6.613 1.32e-10 ***
## lag(USD_NOK_ret, 2) -0.121730 0.049325 -2.468 0.014 *
## oil_price_ret 0.087631 0.013465 6.508 2.49e-10 ***
## lag(oil_price_ret) -0.004324 0.014188 -0.305 0.761
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.02206 on 369 degrees of freedom
## (2 observations deleted due to missingness)
## Multiple R-squared: 0.2319, Adjusted R-squared: 0.2236
## F-statistic: 27.86 on 4 and 369 DF, p-value: < 2.2e-16
*En endring i oljeprisen har en signifikant og positiv effekt på valutakurset med dollaren. Vi kan tolke det sånt: “en 10% endring (økning) i oljeprisen fører til, i gjennomsnitt, en .8% endring i valutakurset.”
*Adjusted R-squared er .23. Vi kan tolke dette med å si at vi har forklart 23% av variasjonen i valutakurset med vår enkel modell.
Vi kan til slutt sjekke at vi ikke har noe autokorrelasjon igjen i residualene.
u_hat <- resid(krone_mod)
ac_mod <- dynlm(u_hat ~ lag(u_hat))
summary(ac_mod)
##
## Time series regression with "numeric" data:
## Start = 1, End = 373
##
## Call:
## dynlm(formula = u_hat ~ lag(u_hat))
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.085649 -0.015022 -0.000438 0.014012 0.052023
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1.343e-06 1.139e-03 -0.001 0.999
## lag(u_hat) 4.415e-03 5.193e-02 0.085 0.932
##
## Residual standard error: 0.022 on 371 degrees of freedom
## (1 observation deleted due to missingness)
## Multiple R-squared: 1.948e-05, Adjusted R-squared: -0.002676
## F-statistic: 0.007226 on 1 and 371 DF, p-value: 0.9323
Ikke noe signifikant.