poniedziałek, 7 listopada 2022

Wielokrotna zmiana struktury modelu - funkcja breakpoints (pakiet strucchange dla R)

Dynamika środowiska giełdowo-gospodarczego powoduje, że parametry modeli ekonometrycznych są niestabilne i nie można ich traktować jako coś pewnego. Wiadomo choćby, że występują cykle nieokresowe, tzn. powtarzające się wzrosty i spadki o zmiennej długości i amplitudzie (i stąd niełatwe do prognozowania). Nie ma więc mowy o sezonowości, ale można badać zmienne korelacje, średnie oraz lokalne trendy. W tym art. analizowałem testy na zmianę struktury modelu, ale ich ograniczeniem była pojedyncza zmiana parametru. Jeżeli w próbie występują dwie albo więcej zmian, testy tego typu mogą okazać się niewystarczające, a może nawet wprowadzające w błąd. Poniższe przykłady i cała analiza będzie wykonywana w języku R. Najlepiej używać nakładki na suche środowisko R, RStudio, które znacznie ułatwia wprowadzanie kodów. Rzeczy, które tu omawiam są kontynuacją serii artykułów: 1234. Jeżeli coś jest niejasne, to prawdopodobnie w  którymś z nich jest wyjaśnione. Jeżeli nie, należy sięgnąć do pomocy technicznej języka R. 

Zanim przejdę do przykładów nasz skrypt musi mieć wstępny kod. A właściwie przedwstępny, dlatego że w późniejszych przykładach będą kolejne wstępne kody. Dla jasności zapisów kody będę oznaczał jako: Przedwstęp, Wstęp, Pod-wstęp (o ile jest), Część główna. 

Potrzebne są nam cztery pakiety: tseries, strucchange, forecast oraz lmtest:

# Przedwstęp

if (require("tseries")==FALSE) {

  install.packages("tseries")

  library("tseries")

}

if (require("strucchange")==FALSE) {

  install.packages("strucchange")

  library("strucchange")

}

if (require("forecast")==FALSE) {

  install.packages("forecast")

  library("forecast")

}

if (require(lmtest)==FALSE) {

  install.packages("lmtest")

  library("lmtest")

}

Jedna uwaga. Raz na jakiś czas pakiety są aktualizowane, a wtedy i tak musimy je na nowo zainstalować, stąd jeśli nie zależy nam na efektywności kodu, to możemy zawsze używać po prostu:

  install.packages("tseries")

  library("tseries")

  install.packages("strucchange")

  library("strucchange")

  install.packages("lmtest")

  library("lmtest")


Przykład 1. Błądzenie losowe

Symulujemy ruch Browna z podziałem na 3 części: 50 danych ze średnią 1, 50 danych ze średnią 1.5 oraz 50 danych ze średnią 1. Połączoną próbę nazwiemy sim123:

# Wstęp

  set.seed(550)

  sim1 = arima.sim(list(order=c(0,0,0)), n=50, mean=1)

  sim2 = arima.sim(list(order=c(0,0,0)), n=50, mean=1.5) 

  sim3 = arima.sim(list(order=c(0,0,0)), n=50, mean=1)

  sim123 = c(sim1, sim2, sim3)

# Część główna

Testujemy stacjonarność (KPSS):

  # test stacjonarności

  if (length(stopa)>200) {

    kpss.test(sim123, lshort=FALSE)

  }  else {

    kpss.test(sim123)

  }

Efekt:

KPSS Test for Level Stationarity

data:  sim123

KPSS Level = 0.41947, Truncation lag parameter = 4, p-value = 0.06877


KPSS wykrył prawidłowo niestacjonarność (p < 0.1). Teraz jednak chcemy znaleźć punkty przełamań. To zastosujmy jak dotychczas QLR. Aby dobrze pokazać zmienną sim123 razem ze statystykami F, stosujemy funkcję par:

par(mfrow=c(2,1), mar=c(2,5,2,2))

plot(sim123, type="l") 

qlr = Fstats(sim123 ~ 1)

plot(qlr, alpha=0.05)


Efekt:


Graficzny test QLR pokazał tylko jeden punkt zmiany, czyli wprowadza w błąd. A wynika on właśnie z tego, że test dzieli próbę na dwie części i poszukuje istotnych zmian. Bai i Perron [1] zaproponowali procedurę uogólniającą QLR na testowanie wielu punktów zmian struktury regresji liniowej. 

Od teraz zamiast QLR będziemy stosować funkcję breakpoints(). De facto już ją stosowałem do znajdowania momentu zmiany, ale wtedy ograniczałem się do jednego punktu. Np. żeby dostać konkretny punkt zmiany w sim123, który odpowiada statystyce supF wpisuję tylko:

breakpoints(qlr)

Efekt:

Breakpoints at observation number:

107 

Corresponding to breakdates:

0.7066667 


Widzimy, że to odpowiada mniej więcej maksimum na wykresie statystyk F.

I uwaga, pokażę, jaki błąd początkowo popełniałem. Funkcja breakpoints() ma taki argument jak breaks, który oznacza maksymalną liczbę wybranych punktów "przełamań". Wydawało się, że wystarczy wpisać:  breakpoints(qlr, breaks = 2) , aby znaleźć 2 takie momenty. Ale przecież argument qlr dotyczy tylko jednego takiego punktu, dlatego to nie zmieni efektu. Co więc zrobić? Okazuje się, że te funkcje są dość elastyczne i można je zastosować na różnych funkcjach. I tak zamiast argumentu qlr, czyli zamiast statystyk F, można wpisać sam model sim123 ~ 1. Mówiąc inaczej breakpoints częściowo zastępuje funkcję Fstats. Dlaczego częściowo? Bo funkcja plot(breakpoints()) działa wtedy inaczej. 

Po kolei. Pierwsza część nowego kodu będzie wyglądać następująco. Dla ułatwienia przekształcamy szybko dane w szereg czasowy:

sim123 = ts(sim123)

Następnie stosujemy na tej zmiennej breakpoints

bai = breakpoints(sim123 ~ 1, breaks = 2)

summary(bai)


Efekt:

Breakpoints at observation number:

m = 1      107

m = 2   49 102

Corresponding to breakdates:                               

m = 1                     0.713333333333333

m = 2   0.326666666666667 0.68             

Fit:  

m   0     1     2    

RSS 148.9 136.5 124.3

BIC 434.6 431.6 427.6


Ponieważ sami wybraliśmy dwa punkty, to dostaliśmy analizę dla dwóch punktów. Najpierw wskazano jakie to punkty. Warto zwrócić uwagę, że algorytm inaczej oblicza je zależnie od ustawienia breaks, co wyraża tu indeks m. Dla m = 1 algorytm oszacował 107 (na datach - ponieważ nie ma ustawień dat - w częściach ułamkowych - 0,71), a dla m = 2 49 (0,33) i 102 (0,68). 

Najważniejsza statystyka jest na dole. Patrzymy jak zachowuje się BIC. Dla m = 2 BIC jest najmniejszy w porównaniu z m = 0 i m = 1. Zatem wnioskujemy, że algorytm prawidłowo wskazał istotne 2 przełamania. 

Co by się stało, gdybyśmy zwiększyli m do 4? Popatrzmy:

bai = breakpoints(sim123 ~ 1, breaks = 4)

summary(bai)

Efekt:

Breakpoints at observation number:

m = 1            107

m = 2      49    102

m = 3      49 75 102

m = 4   24 49 75 102

Corresponding to breakdates:  

m = 1            107

m = 2      49    102

m = 3      49 75 102

m = 4   24 49 75 102

Fit:                   

m   0     1     2     3     4    

RSS 148.9 136.5 124.3 122.7 122.5

BIC 434.6 431.6 427.6 435.7 445.4

 

Widać, że dla m >= 3 BIC wzrósł, a więc wynik się pogorszył. Wniosek: nie ma więcej niż 2 punkty zmiany modelu - prawidłowo.

Jeżeli chcemy zobaczyć to graficznie, to używamy plot:

bai = breakpoints(sim123 ~ 1, breaks = 4)

plot(bai)

Efekt:


Plot możemy jeszcze użyć do dwóch celów. 

W połączeniu z funkcją lines możemy na wykresie czasowym pokazać momenty zmian w czasie: 

par(mfrow=c(2,1), mar=c(2,5,2,2))

sim123 = ts(sim123)

plot(sim123) 

bai = breakpoints(sim123 ~ 1)

lines(bai, breaks = 2)


Efekt:



Grafika wyżej zawiera pewien błąd związany z ucięciem 15% skrajnych danych na Fstat. Wcześniej to poprawiałem dla prawdziwych danych, ale w tym wypadku to byłaby bardziej sztuka dla sztuki. 

Jeszcze ciekawszą grafikę można pokazać wykorzystując funkcję breakfactor:

sim123.model = lm(sim123 ~ breakfactor(bai)-1)

dopas = fitted(sim123.model)

plot(sim123)

lines(dopas, col=4, lwd=3)

Efekt:


Parametr lwd kalibruje grubość linii, col - kolor. 

Zwróćmy uwagę, że zapisując funkcję breakfactor usnąłem wyraz wolny poprzez odjęcie 1 na końcu. W języku R jest pewnego rodzaju umowa, że jeśli nie usuniemy sami wyrazu wolnego, to on zostanie sam dodany. Moim zdaniem to jest zbędne i trochę mylące, bo nie trudno przecież dodać 1, jeśli się chce mieć wyraz wolny, a jeśli mamy tylko wyraz wolny bez zmiennej, to tym bardziej . W każdym razie odjęcie 1 pozwoli nam tutaj wyłuskać prawidłowe parametry w postaci trzech segmentów: bez zmiany parametru, po zmianie i po drugiej zmianie. Aby wyłuskać zmienne współczynniki, używamy funkcji coef():

coef(sim123.model)

Efekt:

breakfactor(bai, breaks = 2)segment1 breakfactor(bai, breaks = 2)segment2 breakfactor(bai, breaks = 2)segment3 

                           0.9340913                            1.6430498                            0.7015123 


W sumie cały nasz nowy kod może wyglądać następująco:

#Wstęp

#symulacja procesu losowego  - tu ruchu Browna - zmienne parametry

set.seed(199)

sim1 = arima.sim(list(order=c(0,0,0)), n=50, mean=1)

sim2 = arima.sim(list(order=c(0,0,0)), n=50, mean=1.5) 

sim3 = arima.sim(list(order=c(0,0,0)), n=50, mean=1)

sim123 = c(sim1, sim2, sim3)

# Część główna

# test stacjonarności

if (length(sim123)>200) {

  kpss.test(sim123, lshort=FALSE)

}  else {

  kpss.test(sim123)

}

#ustawienie parametru graf

par(mfrow=c(3,1), mar=c(5,5,2,2))

sim123 = ts(sim123)

plot(sim123) 

#Procedura Bai-Perrona:

bai = breakpoints(sim123 ~ 1, breaks = 4)

lines(bai, breaks = 2)

summary(bai)

plot(bai)

sim123.model = lm(sim123 ~ breakfactor(bai)-1)

dopas = fitted(sim123.model)

plot(sim123)

lines(dopas, col=4, lwd=3)

coef(sim123.model)

#przywracanie parametru graf

par(mfrow=c(1,1), mar=c(5, 4, 4, 2) + 0.1)


Przykład 2.

Wykonajmy ten sam kod, ale zmieńmy jedną linię. Zamiast

sim123.model = lm(sim123 ~ breakfactor(bai)-1)

wpiszmy

sim123.model = lm(sim123 ~ breakfactor(bai, breaks = 1)-1)

Efekt:

breakfactor(bai, breaks = 1)segment1 breakfactor(bai, breaks = 1)segment2 

                            1.292695                             0.655961 



Czyli widzimy, że jeśli nie wstawimy parametru breaks do breakfactor, to algorytm automatycznie wybiera optymalną liczbę punktów. Dopisanie tego parametru wymusza taką liczbę zmian, jaką chcemy. 


Przykład 3. ARMA(1, 1)

Znów zmieniamy parametry procesu w połowie próby dwukrotnie, ale tym razem średnią zachowuję taką samą, a zmienia się część AR i MA:

#Wstęp

set.seed(1980)

sim1 = arima.sim(list(order=c(1,0,1), ar=0.6, ma=0.3), n=50, mean=1)

sim2 = arima.sim(list(order=c(1,0,1), ar=0, ma=0), n=50, mean=1) 

sim3 = arima.sim(list(order=c(1,0,1), ar=0.6, ma=0.3), n=50, mean=1)

sim123 = c(sim1, sim2, sim3)


# Część główna

# test stacjonarności

if (length(sim123)>200) {

  kpss.test(sim123, lshort=FALSE)

}  else {

  kpss.test(sim123)

}

#ustawienie parametru graf

par(mfrow=c(3,1), mar=c(5,5,2,2))

sim123 = ts(sim123)

#Procedura Bai-Perrona:

bai = breakpoints(sim123 ~ 1)

plot(bai)


Efekt:

KPSS Test for Level Stationarity

data:  sim123

KPSS Level = 0.31029, Truncation lag parameter = 4, p-value = 0.1


Tym razem dostaliśmy niespójność: dane są stacjonarne mimo wskazania punktów zmian. Ponadto test wskazał 3 punkty, choć powinien dwa.

Błąd, o którym już pisałem w art. o trzech technikach testu F wynika z tego, że sprawdziliśmy sobie samą średnią (wyraz wolny), a nie cały model, który tutaj dodatkowo (oprócz wyrazu wolnego) zawiera zmienne zależne. Poprawiamy:

# Wstęp

set.seed(1980)

sim1 = arima.sim(list(order=c(1,0,1), ar=0.6, ma=0.3), n=50, mean=1)

sim2 = arima.sim(list(order=c(1,0,1), ar=0, ma=0), n=50, mean=1) 

sim3 = arima.sim(list(order=c(1,0,1), ar=0.6, ma=0.3), n=50, mean=1)

sim123 = c(sim1, sim2, sim3)

# Część główna

# test stacjonarności

if (length(sim123)>200) {

  kpss.test(sim123, lshort=FALSE)

}  else {

  kpss.test(sim123)

}

sim123 = ts(sim123)

#tworzenie modelu arma(1,1)

sim = ts(sim123[-1])

sim_ar1 = ts(sim123[-length(sim123)])

sim_arma11 = arima(sim123, order=c(1,0,1))

sim_ma = ts(residuals(sim_arma11))

sim_ma1 = ts(sim_ma[-length(sim_ma)])

#Procedura Bai-Perrona:

bai = breakpoints(sim ~ sim_ar1 + sim_ma1)

plot(bai)


Efekt:


Tym razem jest OK.

To dokończmy kod:

plot(sim123) 

lines(bai, breaks = 2)

summary(bai)

sim.model = lm(sim ~ breakfactor(bai)-1)

dopas = fitted(sim.model)

lines(dopas, col=4, lwd=3)

coef(sim123.model)

#przywracanie parametru graf

par(mfrow=c(1,1), mar=c(5, 4, 4, 2) + 0.1)


Efekt:



Kolejne przykłady będą robione na danych rzeczywistych. Dane w formie plików najpierw ściągam z internetu. I tu pokażę jedną nową rzecz. Żeby otworzyć plik w R, musimy podać ścieżkę i tu napotykamy niekompatybilność R z Windowsem: w tym pierwszym ścieżki używają slasha, a w tym drugim backslasha. Coś, co np. w VBA jest łatwe do podmiany, w R okazuje się zadziwiająco trudne. W każdym razie jeśli mamy w miarę nową wersję R, to stosujemy następujący kod. Powiedzmy, że nasza ścieżka z plikami (folder roboczy) to C:\R\testy

# Wstęp

#zamieniam "\" na "/"
sciezka = r"(C:\R\testy)"
sciezka = gsub("\\\\", "/", sciezka)

Gdyby zdefiniować sciezka = "C:\R\testy" dostalibyśmy błąd, dlatego takie przekształcenie jest potrzebne. Funkcja gsub() jest ogólną funkcją do zamiany znaków tekstowych. Dlaczego trzeba aż 4 razy użyć backslasha? Ogólnie backslash ma znaczenie specjalne - wyłącza znaczenie znaków specjalnych, także takich jak on sam. A więc żeby program go rozumiał jako zwykły znak tekstowy, trzeba jego samego użyć - dopisać po pierwszym "\", czyli dostać "\\". Ale to znaczenie występuje na dwóch poziomach. Pierwszy poziom to sam program - interpreter R. Drugi poziom to funkcja typu regex (tutaj gsub). Oba są jakby niezależne. Stąd trzeba aż 4 razy użyć backslasha - dla samego programu oraz dla regexa. Bardziej detaliczny opis poniżej.

--------------------------------------------------------------------
 O ile np. w VBA interpreter najpierw przetwarza to co wpiszemy na dosłowne znaki, o tyle R od razu interpretuje znaki specjalne i wtedy nie wie co w konsoli wpisać (nie da się wpisać "semantycznego" znaczenia znaku specjalnego). Co by jednak się stało, gdyby w kodzie czy konsoli wpisać sam znak "\"? Błędu nie będzie, bo interpreter widzi, że po backslashu nic już nie ma, więc nie ma też specjalnego znaku. Co ciekawe, błędu nie będzie też, gdy wpiszemy po "\" cyfrę powyżej 0. Np. "\1", "\2" itp. nie wywoła błędu, ale "\0" już tak.

W sumie, aby zamienić "\" na "/" trzeba wyłączyć znak specjalny "\" poprzez zapisanie "\\". Zapiszmy taki kod:

sciezka = r"(C:\R\testy)"
sciezka

W konsoli dostaniemy napis "C:\\R\\testy". Widzimy, że program sam doda jeden backslash. Teraz funkcja gsub() ma znaleźć te znaki i zamienić na slash. Kłopot polega na tym, że mamy do czynienia z podwójną interpretacją znaku "\": najpierw w samym programie (pierwszy poziom), a następnie w funkcji gsub (drugi poziom). Pierwszy argument gsub() to poszukiwane znaki, w tym przypadku szukamy "\". Ale wiemy już, że sam interpreter R zakazuje wpisywać do kodu pojedynczy "\" i trzeba go zastąpić "\\". A więc funkcja regex  (czyli gsub) widzi tylko jeden "\". I tu zaczyna się drugi poziom problemu, bo regex nie wie jak interpretować samotny backslash: jako dosłowny tekst czy jako wyłącznik znaku specjalnego. Aby uzyskać pewność trzeba dodać kolejny "\" przed "\". W ten sposób mielibyśmy trzy backslashe. Jednakże trzy backslashe są znowu niedopuszczalne dla samego interpretera R (czyli dla poziomu pierwszego), ponieważ widzi on nowy (drugi) backslash, który jak pamiętamy był znakiem niejednoznacznym i potrzebował dodatkowego "\".  Dopiero dodanie czwartego backslasha stabilizuje sytuację. Skomplikowana sprawa, ale myślę, że w miarę logicznie wyjaśniona.

---------------------------------------------------------------------
Tak naprawdę problem ten możemy ominąć wstawiając do gsub dodatkowo opcję fixed = T:
sciezka = gsub("\\", "/", sciezka, fixed=T)

Podsumujmy część wstępną:

# Wstęp

#zamieniam "\" na "/"

sciezka = r"(C:\R\testy)"

sciezka = gsub("\\", "/", sciezka, fixed=T)

# albo

# sciezka = gsub("\\\\", "/", sciezka)

# ustawiamy folder roboczy

setwd(sciezka)


I teraz idziemy z żywymi przykładami.

Przykład 4. Ceny węgla (ICE Rotterdam Coal)

Sprawdzamy notowania węgla od 31.08.2006 do 31.10.2022 - dane miesięczne, źródło stooq.pl: kontrakty na węgiel (oznaczenie LU.F). Mam plik o nazwie coal.csv. Początek pliku wygląda tak:

 Data Otwarcie Najwyższy Najniższy Zamknięcie

31.08.2006 70 70.5 67.9 68.45

30.09.2006 67.5 67.5 63.75 66.75

31.10.2006 65 68.55 63.5 67.75

30.11.2006 68.25 68.75 66.2 68.75

31.12.2006 67 69.25 67 68


I kod:

# Pod-wstęp
nazwa = "Coal.csv"
  
  plik = read.csv(nazwa, sep=";")
  
  if (ncol(plik)==1) {
    
    plik = read.csv(nazwa, sep=",")
    
  }
  
Żeby zawsze mieć prawidłowo odczytaną datę, używamy opcji TryFormats funkcji as.Date():

  daty = as.Date(plik[,1], tryFormats = c("%d.%m.%Y", "%Y.%m.%d", "%d-%m-%Y", "%Y-%m-%d", "%d/%m/%Y", "%Y/%m/%d"))

  
Wadą danych stooq są ostatnie dane, których daty są błędnie oznaczane. Aby nie usuwać ręcznie zbędnych danych, stosujemy prosty warunek
 
  #jeżeli ostatnia data przekracza wczorajszą datę, to usuwamy ostatnią obserwację
  
  if (daty[length(daty)]>=Sys.Date()) {
    
    plik = plik[-nrow(plik),]
    
    daty = daty[-length(daty)]
  }
  
Dopasowujemy format do szeregu czasowego i tworzymy stopy zwrotu (zmienna o nazwie stopa)
  
  
  rok = as.numeric(format(daty, "%Y"))
  mc = as.numeric(format(daty, "%m"))
  dz = as.numeric(format(daty, "%d"))
  
  cena = as.numeric(plik[,5])
  cena = ts(cena, start=c(rok[1], mc[1]), frequency=12)
  
  stopa = diff(cena)/cena[-length(cena)]



Dane gotowe. Kurs prezentuje poniższa grafika (kod: plot(cena) , plot(stopa))





Badamy stacjonarność zmiennej:

# Część główna

  # test stacjonarności

  if (length(stopa)>200) {

    kpss.test(stopa, lshort=FALSE)

  }  else {

    kpss.test(stopa)

  }

  Efekt:

KPSS Test for Level Stationarity

data:  stopa

KPSS Level = 0.22501, Truncation lag parameter = 4, p-value = 0.1


Zmiany procentowe są stacjonarne. Oznacza to, że raczej nie mamy tutaj do czynienia ze zmienną średnią. Sprawdzamy autokorelację cząstkową. Możemy ją sprawdzić za pomocą funkcji pacf(). Niestety ona sama nie zawiera informacji o istotności stat. Dlatego do pacf() dodamy kod na skumulowany rozkład odwrotny. W sumie:

  pacf(stopa, plot=FALSE, lag.max=10)

  ist_pacf = qnorm((1 + 0.95)/2)/sqrt(sum(length(stopa)))

  noquote(c("Istotna autokorelacja będzie od poziomu: ", ist_pacf))


Efekt:

Partial autocorrelations of series ‘stopa’, by lag


0.0833 0.1667 0.2500 0.3333 0.4167 0.5000 0.5833 0.6667 0.7500 0.8333 

 0.242  0.089 -0.081  0.086 -0.005 -0.010  0.100 -0.004 -0.047  0.055 

Istotna autokorelacja będzie od poziomu:  0.140717213329746 


Ułamkowe rzędy mogą być mylące, bo są to po prostu kolejne części roku: 1/12 = 0.0833 = 1 miesiąc, 1/6 = 0.1667 = 2 miesiące itd.  Dla kwartałów byłoby to 0.25 = kwartał  ; 0.5 = 2 kwartał itd. Istotna korelacja występuje od poziomu 0.14, a to znaczy, że mamy do czynienia z korelacją 1 rzędu. Prawdopodobnie zastosujemy AR(1). Upewniamy się za pomocą funkcji auto.arima:

  arma_stopa = auto.arima(stopa,ic="bic", max.P=7, max.Q=7)

  arma_stopa


Efekt:

ARIMA(1,0,0) with zero mean 

Coefficients:

         ar1

      0.2612

s.e.  0.0705

sigma^2 = 0.01162:  log likelihood = 157.29

AIC=-310.59   AICc=-310.53   BIC=-304.05


Istotnie występuje AR(1), więc tworzymy ten model. Zwróćmy uwagę, że stopa zwrotu już zaczyna się od drugiej obserwacji, więc zmienna opóźniona 1 rzędu będzie zaczynać się od 3-ciej. Choć moglibyśmy użyć podobnej techniki jak przy symulacji, to użyjemy innej, w sumie prostszej techniki, używając funkcji lag. Mimo prostoty funkcja nie jest zbyt intuicyjna, więc opiszę ją nieco dokładniej. 

--------------------------------------------------------------------------------------

Zacznijmy od pytania czym jest zmienna opóźniona o 1 okres? Powiedzmy, że zmienna to nasz szereg czasowy. Wtedy opóźniona o 1 będzie to:

zmienna1 = zmienna[-length(zmienna)]

i aby porównać ją z bieżącym okresem, musieliśmy utworzyć nową bieżącą zmienną , którą definiowaliśmy jako 

zmienna0 = zmienna[-1]

Zatem zmienna1 to zmienna kończąca się na przedostatniej obserwacji, a zmienna0 to zmienna zaczynająca się od drugiej obserwacji. Jeżeli więc tworzymy model typu:

zmienna0 ~ zmienna1

to patrzymy jak pierwsza obserwacja (zmiena1) wpływa na drugą (zmiena0), druga na trzecią itd. 

I teraz najważniejsze: opisana technika wcale nie tworzy zmiennej opóźnionej sensu stricte. Czas płynie do przodu, a to znaczy, że opóźniona obserwacja to taka, która występuje później niż bieżąca. A więc w rzeczywistości tworzyliśmy tutaj nie zmienną opóźnioną, ale przyspieszoną (pospieszoną)! Zmienna0 to zmienna obserwowana w czasie teraźniejszym i patrzymy jak na nią wpływa zmienna1 z przeszłości. Skoro więc porównujemy dzisiejsze obserwacje z tym co było, to w pewnym sensie traktujemy obserwacje z przeszłości jako teraźniejsze, bo skoro mają teraz wpływ, to znaczy, że ciągle istnieją tu i teraz. Z technicznego punktu widzenia bierzemy dane z przeszłości i przesuwamy do przodu. To przesunięcie do przodu oznacza właśnie przyspieszenie, a nie opóźnienie. 

Dlaczego o tym mówię? Bo funkcja lag tworzy zmienną opóźnioną sensu stricte. Wielu tego nie rozumie i w poradnikach możemy przeczytać, że lag działa na odwrót i trzeba używać ujemnego kroku, aby dostać opóźnienie. W rzeczywistości ten ujemny lag da nam właśnie pospieszenie okresu, ale to właśnie o to nam chodzi. Dlatego do intuicyjnie rozumianych "opóźnień" używamy ujemnego kroku, a do "pospieszeń" dodatniego. W każdym razie nie ma tu żadnego błędu, a jedynie musimy pamiętać, że jeżeli wyciągamy zmienną z przeszłości do teraźniejszości, to de facto ją pospieszamy, choć w modelu nazywamy ją zmienną opóźnioną.

--------------------------------------------------------------------------------------

Tworzymy zmienną opóźnioną:

stopa1 = lag(stopa, k = -1)

To niestety nie wystarcza do stworzenia AR(1), bo przesuwa całą zmienną razem z okresem, podczas gdy my chcemy zachować stałość okresu, a jedynie przesuwać obserwacje w czasie. Żeby uzyskać żądany efekt, musimy użyć funkcji intersect (albo ts.intersect aby działać od razu na ts), która działa jak funkcja INNER JOIN w SQL. Nazwa intersect jest myląca, powinna działać jak przecięcie zakresów w VBA albo mieć nazwę np. "innerjoin". Ale nieważne, tworzymy nową zmienną:

dane = ts.intersect(stopa, stopa1)

którą wykorzystujemy do przekształcenia naszych zmiennych:

stopa0 = dane[, "stopa"]

stopa1 = dane[, "stopa1"]


I dalej już to co wcześniej:

  #test Bai-Perrona

  bai = breakpoints(stopa0 ~ stopa1, breaks = 3)

  summary(bai)

  plot(bai)


Efekt:

Breakpoints at observation number:

m = 1         164

m = 2   29    164

m = 3   29 58 164

Corresponding to breakdates:           

m = 1                   2020(5)

m = 2   2009(2)         2020(5)

m = 3   2009(2) 2011(7) 2020(5)

Fit:             

m   0        1        2        3       

RSS    2.228    2.149    2.082    2.041

BIC -297.590 -288.798 -279.130 -267.116




A więc brak zmian struktury. Z jednej strony to pozytywne, bo znaczy, że można lepiej prognozować kolejne zmiany dzięki autoregresji, która pozostaje stabilna. Z drugiej strony ostatnie lata przynoszą o wiele większe wahania, więc możliwe, że to wariancja stopy zwrotu się zmieniła, a nie średnia czy autokorelacja.

Zmianę wariancji, jak pamiętamy, wykonujemy np. za pomocą takich testów jak Goldfelda-Quandta, Breuscha-Pagana czy Harrisona-McCabe. Kod:

  czas = c(1:length(stopa))

  bptest(stopa ~ czas)

  gqtest(stopa ~ 1)

  hmctest(stopa ~ 1)

Normalnie w każdym z tych testów użyłbym wyrazu wolnego za zmienną niezależną, ale dla pierwszego nie da się - pokazuje się błąd, dlatego ustawiłem czas. Wszystkie z tych testów p-value < 0,01, zatem nie ma wątpliwości, że wariancja stopy zwrotu jest zmienna w czasie. Skoro test Bai-Perrona był niewrażliwy na jej zmianę, to znaczy, że można go spokojnie używać na danych heteroskedastycznych.

Cały kod:

# Pod-wstęp

nazwa = "Coal.csv"

plik = read.csv(nazwa, sep=";")

if (ncol(plik)==1) {

  plik = read.csv(nazwa, sep=",")

}

daty = as.Date(plik[,1], tryFormats = c("%d.%m.%Y", "%Y.%m.%d", "%d-%m-%Y", "%Y-%m-%d", "%d/%m/%Y", "%Y/%m/%d"))

#jeżeli ostatnia data przekracza wczorajszą datę, to usuwamy ostatnią obserwację

if (daty[length(daty)]>=Sys.Date()) {

  plik = plik[-nrow(plik),]

  daty = daty[-length(daty)]

}

rok = as.numeric(format(daty, "%Y"))

mc = as.numeric(format(daty, "%m"))

dz = as.numeric(format(daty, "%d"))

cena = as.numeric(plik[,5])

cena = ts(cena, start=c(rok[1], mc[1]), frequency=12)

stopa = diff(cena)/cena[-length(cena)]


# Część główna

#test stacjonarności

if (length(stopa)>200) {

  kpss.test(stopa, lshort=FALSE)

}  else {

  kpss.test(stopa)

}

pacf(stopa, plot=FALSE, lag.max=10)

ist_pacf = qnorm((1 + 0.95)/2)/sqrt(sum(length(stopa)))

noquote(c("Istotna autokorelacja będzie od poziomu: ", ist_pacf))

arma_stopa = auto.arima(stopa,ic="bic", max.P=7, max.Q=7)

arma_stopa

stopa1 = lag(stopa, k = -1)

dane = ts.intersect(stopa, stopa1)

stopa0 = dane[, "stopa"]

stopa1 = dane[, "stopa1"]

#test Bai-Perrona

bai = breakpoints(stopa0 ~ stopa1, breaks = 3)

summary(bai)

plot(bai)

czas = c(1:length(stopa))

bptest(stopa ~ czas)

gqtest(stopa ~ 1)

hmctest(stopa ~ 1)


Przykład 5. Inflacja USA

Inflacja roczna USA w latach 1775-2021 (247 obs), średnioroczna. Źródło: https://www.measuringworth.com/

Zanim przejdę do części głównej, zmodyfikuję nieco część pod-wstępną, tak aby uwzględniała zarówno roczne, jak i miesięczne, a także aby można było łatwo przełączać się między danymi pierwotnymi a przekształconymi. W tym ostatnim chodzi o to, czy nasza zmienna już jest gotowa (stopa inflacji jest podana), czy może musimy ją uzyskać (przekształcić ceny w stopy zwrotu). Oprócz tego do read.csv dodam opcję dec , aby prawidłowo czytać ułamki dziesiętne (w moim pliku używam przecinków).  Dzięki temu nie muszę tworzyć dwóch różnych skryptów:

# Pod-wstęp

nazwa = "inflation US.csv"

plik = read.csv(nazwa, sep=";", dec=",")

if (ncol(plik)==1) {

  plik = read.csv(nazwa, sep=",", dec=".")

}

if (is.numeric(plik[1,1])) {

  daty = paste("01.01.", plik[,1], sep="")

} else { 

  daty = plik[,1] 

}

  daty = as.Date(daty, tryFormats = c("%d.%m.%Y", "%Y.%m.%d", "%d-%m-%Y", "%Y-%m-%d", "%d/%m/%Y", "%Y/%m/%d"))

#jeżeli ostatnia data przekracza wczorajszą datę, to usuwamy ostatnią obserwację

  if (daty[length(daty)]>=Sys.Date()) {

    plik = plik[-nrow(plik),]

    daty = daty[-length(daty)]

  }

fr = 1

kol = 2

st = FALSE

rok = as.numeric(format(daty, "%Y"))

mc = as.numeric(format(daty, "%m"))

dz = as.numeric(format(daty, "%d"))

data_startowa = c(rok[1], mc[1])

cena = as.numeric(plik[,kol])

cena = ts(cena, start = data_startowa, frequency = fr)

if (st == TRUE) {

  stopa = diff(cena)/cena[-length(cena)]

} else {

  stopa = cena

}


Jak widać, mimo, że okres pierwotnie podany jest w latach, to przekształcam je w pełne daty od pierwszego stycznia i z tego już wyciągam lata. Nowością są też 3 nowe zmienne: fr, kol oraz st, gdzie odpowiednio oznaczają częstość (tu roczna, czyli 1), nr kolumny szeregu czasowego (tu 2, wcześniej na danych stooq.pl było to 5) i zmienna logiczna typu TRUE / FALSE , gdzie TRUE oznacza, że zamieniamy pierwotny szereg w stopy oraz FALSE przeciwnie (tu FALSE).

W części głównej kodu jest bardzo podobnie jak w poprzednim przykładzie:

# Część główna

# test stacjonarności

if (length(stopa)>200) {

  kpss.test(stopa, lshort=FALSE)

}  else {

  kpss.test(stopa)

}

# sprawdzanie autokorelacji

pacf(stopa, plot=FALSE, lag.max=10)

ist_pacf = qnorm((1 + 0.95)/2)/sqrt(sum(length(stopa)))

noquote(c("Istotna autokorelacja będzie od poziomu: ", ist_pacf))

# optymalne arima

arma_stopa = auto.arima(stopa,ic="bic", max.P=7, max.Q=7)

arma_stopa


Efekt:

KPSS Test for Level Stationarity


data:  stopa

KPSS Level = 0.43043, Truncation lag parameter = 15, p-value = 0.06404


Partial autocorrelations of series ‘stopa’, by lag


     1      2      3      4      5      6      7      8      9     10 

 0.390  0.158 -0.153  0.048  0.063 -0.063 -0.040  0.116  0.009 -0.049 

[1] Istotna autokorelacja będzie od poziomu:  0.124709521934413  

                      

ARIMA(1,1,1) 


Coefficients:

         ar1      ma1

      0.3758  -0.9817

s.e.  0.0614   0.0143


sigma^2 = 34.33:  log likelihood = -784.25

AIC=1574.5   AICc=1574.6   BIC=1585.02


Inflacja USA okazuje się procesem niestacjonarnym, co podpowiada nam już, że dostaniemy model niestabilny. Najlepszym ARIMA okazał się jednak model bez wyrazu wolnego, ale jest to proces zintegrowany stopnia 1 z AR(1) i MA(1) - w sumie ARIMA(1,1,1). KPSS i ARIMA świetnie się tutaj uzupełniają.

Nie tworzymy w tym momencie modelu ARIMA, tylko zwyczajny ARMA(1,1), co pozwoli nam zobaczyć niejako, jak ta średnia się zmienia w czasie. Ale żeby to było możliwe, musimy dodać wyraz wolny. Następnie testujemy stabilność tego modelu:

# tworzenie optymalnego arma

stopa_ar1 = lag(stopa, k = -1)

stopa_ma = arma_stopa$residuals

stopa_ma1 = lag(stopa_ma, k = -1)

dane = ts.intersect(stopa, stopa_ar1, stopa_ma1)

stopa0 = dane[, "stopa"]

stopa_ar1 = dane[, "stopa_ar1"]

stopa_ma1 = dane[, "stopa_ma1"]

#test Bai-Perrona

bai = breakpoints(stopa0 ~ stopa_ar1 + stopa_ma1 + 1, breaks = 3)

summary(bai)

if (st ==TRUE) {

  par(mfrow=c(3,1), mar=c(2,5,2,2))

  plot(cena)

} else {

  par(mfrow=c(2,1), mar=c(2,5,2,2))

}

plot(bai)

nowy_model = lm(stopa0 ~ breakfactor(bai)-1)

rok0 = as.numeric(format(as.yearmon(time(stopa0)[1]), "%Y"))

mc0 = as.numeric(format(as.yearmon(time(stopa0)[1]), "%m"))

dopas = ts(fitted(nowy_model), start=c(rok0, mc0), frequency = fr)

coef(nowy_model)

plot(stopa0, ylab=colnames(plik)[kol])

lines(dopas, col=4, lwd=3)

par(mfrow=c(1,1), mar=c(5, 4, 4, 2) + 0.1)


Efekt:

Breakpoints at observation number:

m = 1      85    

m = 2   39 85    

m = 3   39 85 145

Corresponding to breakdates:          

m = 1        1860     

m = 2   1814 1860     

m = 3   1814 1860 1920

Fit:            

m   0    1    2    3   

RSS 8250 7141 6729 6577

BIC 1584 1571 1578 1595

breakfactor(bai)segment1 breakfactor(bai)segment2 

               0.3842353                2.3413665 





Zwracam uwagę, że w linii 

bai = breakpoints(stopa0 ~ stopa_ar1 + stopa_ma1 + 1, breaks = 3)

jest dodany wyraz wolny, a w linii

nowy_model = lm(stopa0 ~ breakfactor(bai)-1)

odjęty. W tym ostatnim tworzymy nowy model, więc tworzony byłby nowy wyraz wolny - a tego już nie chcemy.


Istotna zmiana modelu nastąpiła w 1860 r. Problem z jego interpretacją polega na tym, że nie widzimy w ogóle, czy niestabilność dotyczy wyrazu wolnego, części AR, MA, a może wszystkich na raz. To jest ograniczenie tego testu. Są ścisłe sposoby na jego rozwiązanie, ale na razie oprę się jedynie na KPSS. To znaczy wiem, że KPSS wskazał na niestacjonarność, czyli niestabilność właśnie wyrazu wolnego. Dlatego przetestujmy sam wyraz wolny. Kod będzie prawie ten sam, jedynie zmieni się od testu Bai-Perrona:

#test Bai-Perrona

stopa0 = stopa

bai = breakpoints(stopa0 ~ 1, breaks = 3)

summary(bai)

if (st ==TRUE) {

  par(mfrow=c(3,1), mar=c(2,5,2,2))

  plot(cena)

} else {

  par(mfrow=c(2,1), mar=c(2,5,2,2))

}

plot(bai)

nowy_model = lm(stopa0 ~ breakfactor(bai) - 1)

rok0 = as.numeric(format(as.yearmon(time(stopa0)[1]), "%Y"))

mc0 = as.numeric(format(as.yearmon(time(stopa0)[1]), "%m"))

dopas = ts(fitted(nowy_model), start=c(rok0, mc0), frequency = fr)

coef(nowy_model)

plot(stopa0, ylab=colnames(plik)[kol])

lines(dopas, col=4, lwd=3)

par(mfrow=c(1,1), mar=c(5, 4, 4, 2) + 0.1)


Efekt:

Breakpoints at observation number:

m = 1         166

m = 2   40    135

m = 3   40 77 166

Corresponding to breakdates:               

m = 1             1940

m = 2   1814      1909

m = 3   1814 1851 1940

Fit:              

m   0    1    2    3   

RSS 9864 9317 9110 8906

BIC 1623 1620 1625 1631

breakfactor(bai)segment1 breakfactor(bai)segment2 

               0.5975301                3.7677778 



Teraz już dostaliśmy jasną interpretację, choć zmieniła się data breakpoint: do 1939 r. inflacja w USA wynosiła średnio ok. 0.6%, a po tym roku 3.77%. Data jest nieprzypadkowa z trzech powodów:

1) między 1933 a 1939 wprowadzono szereg programów i reform, zwanych New Deal. Program był tak głęboki, że prawdopodobnie wpłynął na trwały wzrost cen,

2) druga wojna św. wprowadziła poważne zmiany w polityce fiskalno-pieniężnej w wielu krajach. Np. na Wikipedii ang. czytamy, że po 2 wojnie św. idee Keynesa zostały powszechnie przyjęte w krajach zachodnich (aż do lat 70-tych, gdy pojawiła się stagflacja),

3) Bank centralny USA - FED - powstał formalnie w 1913, a zaczął działać w 1914 r. Chociaż jego celem była m.in. kontrola inflacji, to de facto stał się maszyną do jej tworzenia. Jak czytamy w "Tajnikach bankowości" system bankowy zmieniono w ten sposób, że tylko Banki Rezerwy Federalnej mogły drukować banknoty [2]. Pierwszej poważnej ekspansji monetarnej dokonano podczas I wojny św., a drugiej podczas Wielkiego Kryzysu od 1929 do 1933 r. 

Na koniec możemy wykonać test homoskedastyczności:

# test homoskedastyczności składnika losowego 

czas = c(1:length(stopa))

bptest(stopa ~ czas)

gqtest(stopa ~ 1)

hmctest(stopa ~ 1)


Efekt:

studentized Breusch-Pagan test

data:  stopa ~ czas

BP = 18.209, df = 1, p-value = 1.98e-05

Goldfeld-Quandt test

data:  stopa ~ 1

GQ = 0.37915, df1 = 123, df2 = 122, p-value = 1

alternative hypothesis: variance increases from segment 1 to 2

Harrison-McCabe test

data:  stopa ~ 1

HMC = 0.71341, p-value = 1


Jedynie BP wskazał na zmienność wariancji - zakładam, że wynika to z występowania warunkowej heteroskedastyczności, być może ARCH. Na razie jeszcze tym efektem się nie zajmuję. 

Zupełnie z boku: analizę dla tego przykładu warto porównać z artykułem FED do likwidacji?! Wówczas porównałem okres inflacji przed powstaniem FEDu z okresem po jego powstaniu. Chociaż dostajemy różnicę ponad 25 lat, to należy pamiętać, że test Bai-Perrona znajduje punkt zmiany struktury. W przypadku inflacji taki punkt naprawdę nie istnieje, bo przecież ten wpływ FEDu był stopniowy. Test uśrednił więc ten proces do punktu. 


Przykład 6. NewConnect

Miesięczne stopy zwrotu od 01.2012 do 10.2022 (źródło: stooq.pl)

Wbrew pozorom nie jest wcale takie proste znaleźć dane finansowe, które mają więcej niż jedną zmianę struktury. Jednak takim przykładem okazuje się osławiony indeks NewConnect. Kod generalnie jest ten sam co dla inflacji, choć zmieniają się założenia (fr, kol, st) i pojawia się nazwa_zmiennej (znaczenie tylko dla wykresu):

# Pod-wstęp

nazwa = "ncindex_m.csv"

plik = read.csv(nazwa, sep=";", dec=",")

if (ncol(plik)==1) {

  plik = read.csv(nazwa, sep=",", dec=".")

}

if (is.numeric(plik[1,1])) {

  daty = paste("01.01.", plik[,1], sep="")

} else { 

  daty = plik[,1] 

  daty = as.Date(daty, tryFormats = c("%d.%m.%Y", "%Y.%m.%d", "%d-%m-%Y", "%Y-%m-%d", "%d/%m/%Y", "%Y/%m/%d"))

#jeżeli ostatnia data przekracza wczorajszą datę, to usuwamy ostatnią obserwację

  if (daty[length(daty)]>=Sys.Date()) {

    plik = plik[-nrow(plik),]

    daty = daty[-length(daty)]

  }

#początkowe założenia i ustawienia

fr = 12

st = TRUE

kol = 5

if (st ==TRUE) {

  par(mfrow=c(3,1), mar=c(2,5,2,2))

  plot(cena, ylab= paste("cena", substr(nazwa, 1, nchar(nazwa)-4)))

  nazwa_zmiennej = paste("stopa zwrotu", substr(nazwa, 1, nchar(nazwa)-4))

} else {

  par(mfrow=c(2,1), mar=c(2,5,2,2))

  nazwa_zmiennej = paste(dimnames(plik[kol])[2], substr(nazwa, 1, nchar(nazwa)-4))

}

rok = as.numeric(format(daty, "%Y"))

mc = as.numeric(format(daty, "%m"))

dz = as.numeric(format(daty, "%d"))

data_startowa = c(rok[1], mc[1])

cena = as.numeric(plik[,kol])

cena = ts(cena, start = data_startowa, frequency = fr)

if (st == TRUE) {

  stopa = diff(cena)/cena[-length(cena)]

} else {

  stopa = cena

}


# Część główna

# test stacjonarności

if (length(stopa)>200) {

  kpss.test(stopa, lshort=FALSE)

}  else {

  kpss.test(stopa)

}

# sprawdzanie autokorelacji

pacf(stopa, plot=FALSE, lag.max=10)

ist_pacf = qnorm((1 + 0.95)/2)/sqrt(sum(length(stopa)))

noquote(c("Istotna autokorelacja będzie od poziomu: ", ist_pacf))

# optymalne arima

arma_stopa = auto.arima(stopa,ic="bic", max.P=3, max.Q=3)

arma_stopa


# ODTĄD ZBĘDNE

# tworzenie optymalnego arma

stopa_ar1 = lag(stopa, k = -1)

stopa_ar2 = lag(stopa, k = -2)

stopa_ma = arma_stopa$residuals

stopa_ma1 = lag(stopa_ma, k = -1)

stopa_ma2 = lag(stopa_ma, k = -2)

dane = ts.intersect(stopa, stopa_ar1, stopa_ar2, stopa_ma1, stopa_ma2)

stopa0 = dane[, "stopa"]

stopa_ar1 = dane[, "stopa_ar1"]

#stopa_ar2 = dane[, "stopa_ar2"]

stopa_ma1 = dane[, "stopa_ma1"]

#stopa_ma2 = dane[, "stopa_ma2"]

# DOTĄD ZBĘDNE


stopa0 = stopa

#test Bai-Perrona

#bai = breakpoints(stopa0 ~ stopa_ar1 + stopa_ar2 + stopa_ma1 + stopa_ma2, breaks = 4)

bai = breakpoints(stopa0 ~ 1, breaks = 4)

summary(bai)

plot(bai)

nowy_model = lm(stopa0 ~ breakfactor(bai) - 1)

rok0 = as.numeric(format(as.yearmon(time(stopa0)[1]), "%Y"))

mc0 = as.numeric(format(as.yearmon(time(stopa0)[1]), "%m"))

dopas = ts(fitted(nowy_model), start=c(rok0, mc0), frequency = fr)

coef(nowy_model)

plot(stopa0, ylab= paste(nazwa_zmiennej, substr(nazwa, 1, nchar(nazwa)-4)))

lines(dopas, col=4, lwd=3)

par(mfrow=c(1,1), mar=c(5, 4, 4, 2) + 0.1)

#test homoskedastyczności składnika losowego 

czas = c(1:length(stopa))

bptest(stopa ~ czas)

gqtest(stopa ~ 1)

hmctest(stopa ~ 1)


Efekt:

KPSS Test for Level Stationarity

data:  stopa

KPSS Level = 0.12962, Truncation lag parameter = 4, p-value = 0.1

Warning message:

In kpss.test(stopa) : p-value greater than printed p-value

Partial autocorrelations of series ‘stopa’, by lag

0.0833 0.1667 0.2500 0.3333 0.4167 0.5000 0.5833 0.6667 0.7500 0.8333 

 0.189  0.028  0.043 -0.024  0.104  0.189  0.088 -0.240 -0.074  0.117 

[1] Istotna autokorelacja będzie od poziomu:  0.172565206655387     

                   

Series: stopa 

ARIMA(0,0,0) with zero mean 

sigma^2 = 0.004339:  log likelihood = 167.85

AIC=-333.7   AICc=-333.67   BIC=-330.84


Breakpoints at observation number:

m = 1            102

m = 2         83 102

m = 3      62 83 102

m = 4   41 62 83 102

Corresponding to breakdates:

m = 1                            2020(7)

m = 2                   2018(12) 2020(7)

m = 3           2017(3) 2018(12) 2020(7)

m = 4   2015(6) 2017(3) 2018(12) 2020(7)

Fit:               

m   0         1         2         3         4        

RSS    0.5597    0.5440    0.4640    0.4562    0.4514

BIC -325.9824 -319.9147 -330.7315 -323.1976 -314.8319


breakfactor(bai)segment1 breakfactor(bai)segment2 breakfactor(bai)segment3 

            -0.008154642              0.063809295             -0.021800546 


studentized Breusch-Pagan test

data:  stopa ~ czas

BP = 7.701, df = 1, p-value = 0.005519

Goldfeld-Quandt test

data:  stopa ~ 1

GQ = 6.0217, df1 = 64, df2 = 63, p-value = 1.005e-11

alternative hypothesis: variance increases from segment 1 to 2

Harrison-McCabe test

data:  stopa ~ 1

HMC = 0.14108, p-value < 2.2e-16




Kwestia techniczna: zaznaczyłem pewną część kodu jako zbędną, którą można usunąć. Nie usunąłem, aby pokazać w miarę ogólny kod, który może służyć do modelowania ARMA(p, q). Ponieważ w tym przypadku zmienna nie jest ograniczona przez zmienne opóźnione, to stopa stanowi zmienną bezpośrednio użytą do modelu. Jednak, żeby zachować ogólność zapisu, zachowuję zmienną stopa0 i to na niej działam. Stąd tutaj wyjątkowo przypisuję stopa0 = stopa. Jeśli model zawierałby części AR lub MA, to po prostu usuwam to przypisanie. 

Przykład NewConnect jest o tyle wyjątkowy, że KPSS wskazuje na stacjonarność stóp zwrotu, optymalny jest ARMA(0,0,0) z zerową średnią, a jednocześnie wyraz wolny jest niestabilny: 

* do końca 2018 r. wynosił -0,8%, 

* do lipca 2020 +6,4% 

* do dziś -2,2%. 

Tak się zmieniała się średnia miesięczna stopa zwrotu. Dlaczego więc KPSS nie potwierdza tego? Odpowiedź już była podana przy badaniu inflacji - nie wiemy czy przypadkiem między 2018 a 2020 nie powstał proces ARMA, który następnie znowu zanikł tak że sumarycznie BIC wskazuje optimum przy zerowych autoregresjach. Można by jeszcze pomyśleć o wpływie zmian wariancji na stabilność - wszystkie testy na wariancję dowodzą jej zmienności w czasie. Jednakże zarówno KPSS jak i test Bai-Perrona są odporne na heteroskedastyczność. Stąd KPSS nie wykrył zmian w rozkładzie stóp, natomiast Bai-Perron wykrył, bo jest wrażliwy na budowę modelu, który w dodatku musi być liniowy.

 

Analiza, którą przedstawiłem ma szczególne znaczenie przy prognozowaniu, gdyż widzimy, że niektóre procesy są niestabilne na poziomie zarówno średniej, jak i wariancji. W przypadku inflacji USA powinniśmy po pierwsze ustawić "uczenie się" parametrów przez program od roku 1941, a po drugie rozważyć model klasy (G)ARCH zamiast ARMA. Te pierwszy obejmuje drugi i czasem niepotrzebnie nazywany jest ARMA-GARCH. Z kolei poświęcanie czasu na NewConnect wydaje się złym pomysłem dopóki średnia jest ujemna - i to nie do końca z powodu bessy, bo to giełda, która od początku swojej historii spadła o 70% (od 2012 o ok. 30%).


Literatura:

[1] Bai J., Perron P. (2003), Computation and Analysis of Multiple Structural Change Models, Journal of Applied Econometrics, 18, 1-22 ;

[2] Rothbard, M. N.., Tajniki bankowości, Warszawa 2007, s. 254.

wtorek, 18 października 2022

Nobel dla badacza kryzysów, który nie przewidział ostatniego kryzysu

Zastanawiałem się dlaczego Bernanke dostał Nobla za "badania nad bankami i kryzysami finansowymi", skoro będąc szefem FEDu w latach 2006-2014 nie przewidział kryzysu 2007-2009. Dopiero jak przejrzałem niektóre jego publikacje, zrozumiałem, że prawdopodobnie są to tylko oficjalne powody. Bo Bernanke zajmował się także teorią inflacji i mógł ją zastosować w praktyce. Ocenić jego kadencję można dopiero po roku od jej rozpoczęcia - on sam napisał kiedyś, że reakcja inflacji na bodźce polityki monetarnej jest zawsze opóźniona o co najmniej rok [1]. I tak w latach 2007-2014 inflacja w USA wyniosła niemal dokładnie 2%, czyli tyle ile wynosił cel inflacyjny FEDu.

Bernanke napisał też ostatnio książkę  21st Century Monetary Policy: The Federal Reserve from the Great Inflation to COVID-19. Portal npr.org w maju tego roku poświęcił jej artykuł, Ben Bernanke's Lessons From 'The Great Inflation' Pozycja ta okazuje się szokująco aktualna i zaczyna się od przestrogi z amerykańskiej historii znanej jako "Wielka Inflacja". Dalej przetłumaczony fragment tego artykułu:

Według Bernanke historia Wielkiej Inflacji zaczyna się od wydatków na deficyt. John F. Kennedy ubiegał się o urząd prezydenta w czasie recesji i obiecał, że "rozrusza Amerykę na nowo". Jako prezydent Kennedy zaproponował dużą obniżkę podatków, aby pobudzić gospodarkę i obniżyć bezrobocie, które w momencie objęcia urzędu wynosiło prawie 7 procent. Po zamachu na Kennedy'ego jego następca, Lyndon B. Johnson, kontynuował obniżkę podatków, co pomogło obniżyć bezrobocie do 4 procent do końca 1965 roku. Był to poziom bezrobocia, który według ówczesnych makroekonomistów oznaczał pełne zatrudnienie, czyli teoretyczny próg, kiedy rynek pracy zaczyna być tak ciasny, że płace i ceny zaczynają eksplodować. "Z punktu widzenia polityki makroekonomicznej byłby to logiczny moment, by złagodzić działanie akceleratora, ale polityka zagraniczna i cele społeczne wzięły górę nad stabilnością gospodarczą" - pisze Bernanke.

Kiedy prezydent Johnson w 1965 roku jeszcze bardziej pogrążył Amerykę w wojnie w Wietnamie, otworzył remizę z federalnymi wydatkami. Wydatki na obronę wzrosły o 44 procent w latach 1965-1968. Ameryka wyda na wojnę prawie 850 miliardów dolarów (w dzisiejszych dolarach). Jak pisze Bernanke, ponieważ wojna już wtedy była niepopularna, Johnson niechętnie popierał podwyżki podatków, aby ją opłacić, co oznaczało, że był to zastrzyk nowych pieniędzy dla gospodarki.

W tym samym czasie Johnson rozpoczął swoją Wojnę z Ubóstwem i programy Wielkiego Społeczeństwa. Obejmowały one stworzenie rządowych programów opieki zdrowotnej Medicare (dla starszych Amerykanów) i Medicaid (dla Amerykanów o niskich dochodach), które rozpoczęły się w 1965 roku. "Wiele programów Great Society ostatecznie przyniosłoby ważne korzyści" - pisze Bernanke - "ale ich skutkiem było również dalsze zwiększanie wydatków rządowych".

Wszystkie te deficytowe wydatki rozgrzewały gospodarkę, która już i tak była gorąca. Wykonawcy wojskowi wykorzystywali rządowe pieniądze do budowy broni, bomb, samolotów i helikopterów. Dostawcy usług medycznych wykorzystywali rządowe pieniądze na zabiegi, badania, rozbudowę szpitali i tak dalej. Zwiększyło to zapotrzebowanie na siłę roboczą i materiały, których i tak już brakowało, podnosząc ceny wszystkiego.

Kiedy w 1969 roku prezydent Nixon objął urząd, inflacja gwałtownie wzrosła. Nixon kontynuował inflacyjną ucztę za pomocą takich polityk, jak intensyfikacja wojny wietnamskiej, wydatki na deficyt oraz, jak zobaczymy, wtykanie nosa tam, gdzie go nie ma: w politykę monetarną.


Dlaczego Fed zawiódł podczas Wielkiej Inflacji

Na początku swojej prezydentury Richard Nixon mianował na szefa Rezerwy Federalnej bliskiego sojusznika: Arthura Burnsa. Często przedstawiany jako palący fajkę Burns był ekonomistą z Uniwersytetu Columbia, który służył jako doradca ekonomiczny w kampanii prezydenckiej Nixona w 1968 roku.

"Kiedy Burns został zaprzęgnięty przez Fed, Nixon nie miał żadnych zastrzeżeń co do wykorzystania ich relacji do swoich politycznych korzyści" - pisze Bernanke. "Wobec wzrostu bezrobocia podczas recesji w 1970 roku, prezydent chciał mieć silną gospodarkę przed wyborami w 1972 roku". Wyciekły nagrania z Białego Domu Nixona - tzw. taśmy Nixona - dostarczają palących dowodów na to, że Nixon bezpośrednio naciskał na Burnsa, by ten stymulował gospodarkę luźniejszą polityką monetarną (nawet jeśli tymczasowe pobudzenie wzrostu gospodarczego nie służyło długoterminowemu interesowi gospodarki czy społeczeństwa).

Nie wiemy dokładnie, dlaczego Burns ostatecznie zgodził się na żądania Nixona. Bernanke rozważa możliwość, że Burns działał z jakiegoś osobistego przekonania. Burns najwyraźniej wierzył, że Kongres i prezydent powinni walczyć z inflacją za pomocą bardziej chirurgicznej kontroli cen, a nie za pomocą brutalnej siły wyższych stóp procentowych. Administracja Nixona rzeczywiście wprowadziła w różnych okresach kontrolę cen, w tym gazu.

W 1973 roku, kiedy szok podażowy związany z gwałtownie rosnącymi cenami ropy uderzył w gospodarkę, inflacja się pogorszyła, podobnie jak wzrost gospodarczy. Inflacja przekształciła się w stagflację, czyli inflację połączoną ze stagnacją wzrostu, co zdaniem wielu ówczesnych ekonomistów nie było nawet możliwe. Odpowiedzią Nixona była próba ograniczenia ceny ropy. Bernanke i większość innych ekonomistów obwinia tę politykę o spowodowanie niedoborów i niesławnych kolejek na stacjach benzynowych - a jednocześnie nie udało się opanować inflacji.

Niezależnie od przyczyn, Burnsowi nie udało się wykorzystać uprawnień Fedu, by położyć kres wysokiej inflacji. Nawet po tym, jak stało się jasne, że kontrola cen zawiodła - i nawet po rezygnacji Nixona - Burns nadal wzbraniał się przed podniesieniem stóp procentowych do poziomu potrzebnego do powstrzymania inflacji, obawiając się, że spowoduje to głęboką recesję. Zamiast tego pozwolił, by inflacja utrzymywała się przez całe lata siedemdziesiąte, co - jak pisze Bernanke - przekonało opinię publiczną, że inflacja jest tu na stałe. Firmy i pracownicy prowadzili swoje interesy i negocjowali kontrakty zgodnie z tym. Te "oczekiwania inflacyjne", jak ekonomiści określają psychologiczny składnik inflacji, sprawiły, że wzrost cen był jeszcze gorszy.

W 1979 roku prezydent Jimmy Carter mianował nowego prezesa Fedu, Paula Volckera, aby Fed zmienił kurs. "Fed stracił wiarygodność jako obrońca inflacji, a wyzwaniem dla nowego przewodniczącego było jej przywrócenie" - pisze Bernanke. Volcker, zaciekle niezależny i często działający wbrew krótkoterminowym interesom wyborczym prezydenta, prowadził epicką wojnę z inflacją. W końcu podniósł główną stopę procentową Fedu, stopę funduszy federalnych, do prawie 20 procent - najwyższego poziomu w historii. W ten sposób pogrążył naród w głębokiej, choć przejściowej recesji. Ale, jak pisze Bernanke, przygotował również scenę dla dekad stabilnych cen i wzrostu gospodarczego.


Wtedy a teraz

Obecnie Ameryka musi liczyć się z wysoką inflacją po raz pierwszy od czasów Wielkiej Inflacji. Bernanke uważa, że to historyczne doświadczenie dostarcza ważnych lekcji dla Fedu.

Po pierwsze, Fed musi przejąć inicjatywę w sprawie inflacji. Burns wierzył, że Kongres i prezydent mogą zastosować politykę kontroli cen, co tylko pogorszyło sytuację gospodarczą.

Po drugie, Fed powinien poważnie potraktować oczekiwania inflacyjne. Musi w sposób wiarygodny pracować nad utrzymaniem inflacji w ryzach od samego początku. Zrzucanie winy na karb tego, co się dzieje, pozwala tylko na to, by psychologia inflacji utrwaliła się w umysłach społeczeństwa, zmuszając przyszłych przewodniczących Fedu do podjęcia jeszcze bardziej drakońskich środków, by ją opanować (tak jak musiał to zrobić Paul Volcker).

Wreszcie, polityczna ingerencja w kształtowanie polityki Fedu może być niebezpieczna. Prezydenci, tacy jak Richard Nixon, mają osobisty interes w tym, by pobudzić gospodarkę przed wyborami. Ten interes może być sprzeczny z długofalowym interesem gospodarki i społeczeństwa. 

            Przełumaczone przez deepL z małymi poprawkami. 


Wydaje mi się więc, że ekonomiści wysłali do rządzących i banków centralnych z całego świata komunikat: ogarnijcie się.


Źródło:

[1] Bernanke, Ben, and Michael Woodford. Ination Forecasts and Monetary Policy." Working paper, October 1996, s. 1.

wtorek, 4 października 2022

Kaczyński jak Erdogan, czyli Turcja grozi Polsce

 A więc szef szefów zapowiada "powolną metodę" walki z inflacją. To zupełnie jak Erdogan, który zapowiada dalsze cięcia stóp przy inflacji 83%. Jeszcze w 2018 r., gdy inflacja w Turcji wynosiła 16%, czyli prawie tyle co dziś u nas, ich prezydent nauczał inwestorów - cytuję - "że niskie stopy procentowe powodują niską inflację" (źródło).  

Zamiast się wyśmiewać, powinniśmy spojrzeć na tę wypowiedź z szerszej perspektywy. Właściwie są dwie. Po pierwsze to nie jest tak, że on wyszedł sobie, nie mając pojęcia o czym mówi. Jak spojrzymy np. na Europę i USA, to one utrzymywały zerowe stopy jeszcze w 2021 r. mimo dużej inflacji. Chyba największą konsternację wzbudzać powinno USA, których bank centralny oficjalnie się chwali na swoim bogu, jak odchyla swoją politykę od reguły Taylora:


Tak dużego odchylenia jeszcze nie było. 

Dlaczego oni to robią? Wydaje się, że spory wpływ na ich decyzję mają tzw. neofisherianie. Klasyczny Fisher pokazał jedynie, że nominalna stopa stanowi sumę realnej stopy oraz stopy inflacji. Jeżeli stopa nominalna nie zmienia się, a inflacja spada, to znaczy, że realna musi wzrosnąć... Ale neofisherianie odwrócili ten pomysł i uznali, że jeżeli obniżymy stopę nominalną, a realną uznamy za stałą, to inflacja musi spaść... A dlaczego zakładają, że realna jest stała? Prawdopodobnie utożsamiają realną z naturalną stopą procentową. A naturalna stopa rzeczywiście może pozostać stabilna. 

Ale o ile pamiętam, już nawet Wicksell twierdził, że realna stopa nie jest tożsama z naturalną. Naturalna reprezentuje potencjalną produktywność gospodarki, czyli wzrost potencjalnego realnego PKB. Podczas gdy realny PKB krąży wokół tego naturalnego poziomu. Chociaż produkcja nie może przekroczyć swojego maksimum, to w sensie praktycznym uznamy, że naturalny poziom oznacza taki, który nie pobudza wzrostu cen - popyt nie przekracza podaży albo że inwestycje nie przekraczają oszczędności.

Poza tym nie mówimy o gospodarkach socjalistycznych, którym nakazuje się utrzymywanie jednego i takiego samego poziomu stóp. Ludzie kupują od banku centralnego obligacje skarbowe, a banki komercyjne dodatkowo prowadzą z nim operacje krótkoterminowe, zatem stopa referencyjna będzie miała znaczący wpływ na ich własne stopy, ale to nie znaczy, że jak bank centralny ustawi zerową, to banki też tak zrobią - po prostu obniżą swoje. Dobrze to widać po oprocentowaniu lokat i samych kredytów. 

Oprócz wymiaru czysto rynkowego, bank centralny także wysyła sygnały do przedsiębiorców. W zależności od różnych czynników, w tym reputacji banku centralnego, przedsiębiorcy mogą różnie potraktować taki sygnał. Mogą uznać wzrost stopy za sygnał pozytywny, bo to znaczy, że gospodarka weszła w ożywienie (produktywność wyznaczona przez naturalną stopę poprawiła się), a więc mogą teraz podnieść ceny swoich towarów...  A więc będą sytuacje, że neofisherianie będą mieć rację. Tylko że warunkiem do tego musiałoby być podążanie stóp za naturalną stopą procentową. A nie próba oszukiwania praw ekonomii, tworząc własną rzeczywistość.

Kończąc ten wątek, przyszła mi taka myśl, że po 15 latach wyszydzania neoliberałów, nadchodzi  pewnego rodzaju zemsta i kontrakcja. Neokeynesiści (którzy chętnie uznają się za neofisherian, a w każdym razie ci ostatni się z nich wywodzą) mogą być teraz na cenzurowanym przez kolejne 15 lat.

Chociaż jest jeszcze druga perspektywa, może nawet ważniejsza. Możliwe, że głównym problemem Turcji nie jest stopa, która i tak jest wysoka (i w tym sensie Erdogan ma rację, że wielu nie byłoby stać na spłatę kredytów, a inwestycje kompletnie by się załamały), ale o kurs walutowy. Popatrzmy na USD/TRY:


Rzeczywiście, już rok temu naukowcy badający sytuację tego kraju zarekomendowali tureckiemu bankowi centralnemu skupienie się na wzmocnieniu liry tureckiej, ponieważ drożejące towary z importu stanowią główną przyczynę inflacji [1].

To dla przypomnienia USD/PLN:


Może NBP powinien zacząć wyciągać jakieś wnioski z Turcji, choć raz być mądrzejszym przed szkodą.  


Literatura:

[1]  Kantur, Z., i Özcan, G., (2021), Dissecting Turkish inflation: theory, fact, and illusion, Economic Change and Restructuring (2022) 55:1543–1553.

sobota, 1 października 2022

Fundusz Odbudowy obniżyłby czy podniósłby inflację?

W dzisiejszym programie 6. Dzień Tygodnia w Radiu Zet posłanka PO, I. Leszczyna na pytanie co by zrobiła, by obniżyć inflację, odpowiedziała, że "natychmiast trzeba zrobić wszystko by euro z Krajowego Planu Odbudowy popłynęło szerokim strumieniem do Polski, wtedy wzmocnimy złotego". R. Winnicki wtrącił, że więcej pieniądza na rynku to jest większa inflacja. Leszczyna natychmiast zripostowała: "Nie ma pan racji, nie mówimy o pieniądzu konsumpcyjnym, tylko o pieniądzu, który zainwestujemy".

Fundusz Odbudowy (uzyskany z KPO) nie jest pustym rozdawnictwem, a celowanymi dotacjami (ponad 100 mld zł) i pożyczkami (ponad 50 mld zł) (źródło). Są to pieniądze, które wprost działają na podaż dóbr i usług, a dopiero pośrednio na popyt. 

Przypomnijmy, że ogólna cena może być zapisana w postaci prostego wzoru:


gdzie:

P - średnioważony poziom cen,

M - podaż pieniądza,

V - szybkość obiegu pieniądza,

Q - ilość dóbr i usług (realny PKB).


Zasadą zdrowej gospodarki jest, aby M i Q rosły w tym samym tempie. Z V już jest więcej kontrowersji, choć klasycznie pozostaje stałe. Zastanówmy się, co się stanie, gdy gospodarka dostanie zastrzyk pieniędzy z KPO/FO. Z pewnością rośnie M, ale i rośnie Q. Nie wiemy jednak, czy M rośnie silniej od Q, czy na odwrót, a może wzrosną w równym stopniu. Jeżeli M rośnie silniej, to Winnicki ma rację, a jeżeli Q rośnie silniej, to Leszczyna ma rację. Powiedzmy, że za Q wstawimy ilość sprzedawanej energii/surowców. Energię można samemu produkować albo kupić. Z tego co wiem, to środki mają iść m.in. na większą produkcję "zielonej energii". Ale przecież zbudowanie infrastruktury energetycznej nie odbędzie się w ciągu pół roku. Np. wg OKO.Press Litwa dostała już KPO ponad rok temu, a jej inflacja wynosi dziś 22,5% (źródło). Inaczej wygląda sytuacja krajów, które inwestowały wiele lat wcześniej i już są samowystarczalne energetycznie. Przykładem jest Francja, która dzięki elektrowniom atomowym, ma "zaledwie" 6% inflacji.

Aby obniżyć inflację, pieniądze z FO musiałyby zostać przeznaczone na obniżanie cen energii i surowców. UE zamiast wymyślać socjalistyczne podatki od nadwyżkowych zysków, powinna natychmiast dostosować pierwotne cele funduszy do bieżących warunków (no chyba że rzeczywiście mamy do czynienia z oligopolami, które wykorzystują swoją pozycję - wtedy faktycznie trzeba regulować). Można by np. zapłacić producentom i dystrybutorom energii, aby nie podnosiły cen, bo w tym momencie efektywniej jest wydać te pieniądze w ten sposób. Skoro nie możemy tanio produkować, to powinniśmy tanio kupować. Kogo dziś w Polsce obchodzi zielona energia, jeśli mamy problemy kosztowo-podażowe z tą nieodnawialną? 

Jeszcze jedna uwaga co do tej propozycji Leszczyny. Stwierdza ona w tym samym zdaniu, że chodzi o zwiększenie kursu złotego do euro. Wyższy kurs złotego rzeczywiście obniża inflację, bo ceny importowanych towarów w euro by spadły. I obecnie historycznie wysoki kurs euro i kurs dolara do złotego przyspiesza inflację. Ale jak się ma to do twierdzenia, że pieniądze mają być przeznaczone na inwestycje? W ogóle myślenie tego rodzaju przypomina leczenie skutków choroby zamiast przyczyny: spadek wartości waluty nie jest spowodowany czynnikami technicznymi czy jakimiś ograniczeniami gotówkowymi, że należy walucie pomóc, a rynkowymi, tzn. kapitał ucieka; nie chce tu inwestować. Popatrzmy znowu na Litwę - ich walutą jest euro, a jednak nie pomogło to w utrzymaniu niskiej inflacji (aczkolwiek nie pomaga im też zerowa stopa procentowa...).

Na tytułowe pytanie odpowiedziałbym, że prawdopodobnie obniżyłby, ponieważ te dotacje koncentrują się na zwiększaniu strony podażowej, a nie popytowej, tak że kapitał pracuje, a nie jest konsumowany. Jednak przykład krajów, które już dostały pieniądze wskazuje, że nie stałoby się to szybko i nie wiadomo w jakim stopniu. Dlatego taką strategię PO należy traktować w ramach propagandy.

piątek, 9 września 2022

WIG - najgorszy indeks na świecie. Regresja do średniej nie zadziała?

Ostatnio media doniosły, że, jak dotąd, w 2022 roku polska giełda zachowuje się najgorzej na świecie. Z ciekawości sprawdziłem ostatnie 7 lat, a dokładniej porównałem WIG z 9-cioma indeksami europejskimi: DAX (Niemcy), CAC40 (Francja), PX (Czechy), OMX (Szwecja), BUX (Węgry), OMXV (Litwa), OMXR (Łotwa), RTS (Rosja) i FTSE250 (Wielka Brytania), okres 10.2015-08.2022 (miesięczne skumulowane stopy zwrotu):



Dwa zastrzeżenia: (1) indeksy nie do końca są porównywalne, bo występują w różnych walutach; (2) nie sprawdziłem czy wszystkie uwzględniają dywidendy, tak jak WIG. Niemniej stopy zwrotu zazwyczaj korelują ze sobą powyżej 50%, najsłabiej z WIGiem koreluje Łotwa (35%). 

Na czerwono - WIG, który praktycznie wyszedł na zero (+0,7%) i rzeczywiście okazuje się najgorszym indeksem ze wszystkich. Na czarno - Rosja. Z rysunku wydawałoby się, że blisko nas jest UK (kolor granatowy), ale różnica wynosi ponad 13 pkt proc.

Oczywiście zakres dat jest nieprzypadkowy, bo w pewnym sensie odzwierciedla osiągnięcia rządów PIS.

Powstają dwa pytania. Czy zadziała prawo regresji do średniej i polski indeks dogoni np. Węgry albo Litwę? To wydaje się niewiarygodne, ale BUX wzrósł o 100%, a Litwa o 91%. Dalej, czy gdyby za rok PO wygrało wybory, to byłby to pozytywny sygnał dla giełdy? 

Zanim odpowiem na to pytanie, warto dopowiedzieć, że APP Funds na swoim blogu pokazał jeszcze szerszą perspektywę, od 2007 r. , która jednoznacznie wskazuje, że za PO wcale nie było lepiej. Zakładam, że główną przyczyną był "zamach" na OFE.

Gdyby PO przejęło znów władzę, gospodarka byłaby nadal pokiereszowana złymi rządami poprzedników, ale giełda mogłaby już odbijać. Tylko czy są racjonalne przesłanki ku temu?
PO przestała być partią centrum, a stała się de facto lewicą. I nie chodzi tu tylko o kwestie światopoglądowe, ale także - albo głównie - gospodarcze. Jedną z dewastacji gospodarczych, jaką spowodował PIS, było wprowadzenie zakazu niedziel handlowych. Początkowo PO bardzo  krytykowała ten pomysł i zapewniała, że zlikwiduje ów zakaz, jak tylko zdobędą władzę. Minęło kilka lat i co się stało? Nie tylko przestali cokolwiek mówić na ten temat, ale dodatkowo zaproponowali 4-dniowy tydzień pracy. Tak jakby nie można było pozwolić rynkowi, by sam ustalił optymalny czas. Pracodawca i pracownik mogą w umowie ustalić warunki i nie rozumiem, dlaczego państwo ma się znowu do tego mieszać. Teoria ekonomii mówi, że tam gdzie rynek sam dobrze nie działa, tam powinno wkraczać państwo. Firma z założenia zazwyczaj ma silniejszą pozycję od pracownika; to do firm zgłaszają się kandydaci, a nie na odwrót. Ale jeżeli ci sami politycy przekonają przedsiębiorców, że 4-dniowy tydzień nie obniży produktywności firmy, to przedsiębiorcom powinno wręcz zależeć na tym, żeby go wprowadzić, bo obniżą w ten sposób koszty. 

Kiedy dziennikarze pytają, dlaczego PO tak zależy na tym lewicowym programie, ich reprezentanci odpowiadają, że "ludzie tego chcą". Ludzie chcą też więcej zarabiać, więc należy ustawowo podnosić im pensję. Albo też chcą niższej inflacji, to należy administracyjnie ustalić limit cen. 

I rzeczywiście, ostatnio jeden z polityków PO (który w dodatku wg wikipedii ma wykształcenie ekonomiczne), w programie tv twierdził, że PKN Orlen powinien mieć zerowe zyski! Pracować dla dobra obywateli i nie mieć żadnych zysków! Zacytuję większy fragment z tego artykułu (Piotra Rosika):

Tak, jest to szokujące. Platforma Obywatelska do niedawna była znana raczej z liberalnych ekonomicznie poglądów, ale jak widać – to się szybko zmienia. Zaczęło się chyba od akceptacji programu 500+ i deklaracji, że nawet jeśli PO wygra wybory, to program ten nie zostanie zlikwidowany.

Tu trzeba dodać, że populizm Platformy poszedł dalej, bo zaczęli postulować waloryzację tego świadczenia o inflację. W ramach tej logiki dziwne, że nikt ich nie zapytał czy w recesji albo deflacji, będą postulować dewaloryzację? Tak jak wynagrodzeń minimalnych nie zmniejszają, to i tego nie zmniejszą. To jest oczywista hipokryzja.

Jak widać, ten trend przechodzenia PO na lewo jest kontynuowany. Przeczytajmy raz jeszcze słowa Andrzeja Halickiego:

“Polacy są dzisiaj okradani. Jeżeli spółki Skarbu Państwa – te energetyczne, paliwowe, Orlen – mają po 12, 13 miliardów zysku […] to te spółki powinny być na zero i służyć społeczeństwu i gospodarce”.

Poseł PO określa zysk spółek Skarbu mianem kradzieży. Pieniądze, które te spółki zarobiły, zostały ukradzione społeczeństwu – jego zdaniem. Zapomniał chyba, że są to spółki prawa handlowego, które mają być w założeniu zarządzane tak, by wykazywały zysk. Podstawową zasadą kapitalizmu jest to, że podmioty gospodarujące działają po to, by mieć zysk.

Poseł Halicki mówi wprost, że te spółki nie powinny mieć zysku, tylko „służyć społeczeństwu i gospodarce”. Czyli, jak się domyślamy, chodzi o to, by Orlen ustawił cenę 1 litra benzyny na 4,25 zł, czyli by sprzedawał paliwo po kosztach. I tak dalej, ta sama zasada miałaby obowiązywać w odniesieniu do wszystkich spółek Skarbu Państwa…

Jak zareagowaliby na to akcjonariusze tych spółek? Warto obserwować ich zachowanie podczas dzisiejszej sesji. Ale chyba nie będzie wielkim odkryciem, że generalnie większość inwestorów, i to zdecydowana, nie chce mieć akcji spółek, które nie generują zysków…

Co ciekawe, wypowiedzią Halickiego pochwalił się oficjalnie klub Koalicji Obywatelskiej (...)

Po pierwsze Skarb Państwa ma teraz ok. 36% udziałów, więc nawet gdyby pominąć sprawy prawnicze i skupić się na ekonomii, to spółka nie jest kontrolowana przez państwo (to się zmieni po połączeniu z PGNiG). Mamy więc pierwsze przekłamanie. Po drugie politycy PO nie zwracają uwagi, że zysk księgowy nie jest równoznaczny zyskowi pieniężnemu. Problem ten omówiłem w art. Oczyszczanie zysku netto z niepewnych pozycji i wskazałem, że faktyczny, pieniężny zysk wyniósł w 2021 r. zaledwie 17% księgowego. Głównie wynika to z tego, że niemal 90% zysku księgowego przeznaczone jest na inwestycje. Stąd też dywidenda wyniosła ok. 15% zysku na akcję bez odpisów aktualizujących.
Oznacza to, że cały albo prawie cały zysk pieniężny został przeznaczony na dywidendę. Po trzecie prawie 40% tej dywidendy otrzyma Skarb Państwa. Po czwarte, rekordowe zyski księgowe oznaczają także rekordowy CIT. Zakładam, że dzięki tym nadwyżkom z dywidend i podatków rząd był w stanie obniżyć VAT na paliwo i zredukować akcyzę. 
  
Po tej nieodpowiedzialnej i zwyczajnie głupiej opinii największej partii opozycyjnej (partia pochwaliła się tymi mądrościami na twitterze) akcje Orlenu znowu tąpnęły. Są to krótkoterminowe ruchy, ale w ten sposób daje się bardzo zły sygnał akcjonariuszom: waszą spółkę znacjonalizujemy.

Trzeba dopowiedzieć, że obecnie udział PKN w WIG jest największy ze wszystkich podmiotów (prawie 9%), stąd teza, że opozycja przyczyniła się do ogłoszenia polskiej giełdy najgorszą na świecie, jest uzasadniony.

Link do danych (w tym macierz korelacji między indeksami): Indeksy Europy 10.2015-08.2022

czwartek, 1 września 2022

Czy inflacja jest ukrytym podatkiem?

 Chociaż jestem zwolennikiem zerowej inflacji (albo nawet deflacji), to trudno mi przejść obok tego co się dzieje obecnie, gdy wszyscy dziennikarze i politycy stali się jej znawcami. Jednym z najczęściej pojawiających się nieporozumień, jest twierdzenie, że inflacja to ukryty podatek. Brzmi to mądrze, ale takie nie jest, a przynajmniej jest bardziej skomplikowane niż się wydaje. Może bym przeszedł obok tego zagadnienia bez komentarza, ale gdy czytam to samo na portalu ekonomicznym mises.pl, to trudno mi pozostać obojętnym. 

W artykule pt. Inflacja czyni ludzi uboższymi (i jest to wina państwa) z 28.08.2022 czytamy, że "inflacja (czyli ekspansja podaży pieniądza) i idący za nią wzrost cen są ukrytą formą podatku." Inflacja nie jest ekspansją podaży pieniądza, ponieważ miewa różne przyczyny. Żeby zrozumieć gdzie leży błąd, wystarczy przeanalizować równanie wymiany (który wyprowadziłem w art. Równanie wymiany Fishera, czyli pieniężne spojrzenie na gospodarkę):


gdzie:

M - podaż pieniądza,

V - szybkość obiegu pieniądza,

P - średnioważony poziom cen,

Q - ilość dóbr i usług (realny PKB).


Z równania wynika, że ogólna cena jest proporcjonalna do podaży pieniądza, szybkości jego obiegu i odwrotnie proporcjonalna do realnego PKB:


Czyli widzimy, że oprócz podaży pieniądza, inflację wywoła zarówno recesja podażowa (wtedy mamy stagflację), jak i wzrost liczby transakcji między podmiotami. 

Recesja podażowa

Recesja podażowa to recesja spowodowana blokadą podaży przy zachowaniu globalnego popytu. Recesję podażową mieliśmy w PRL (ceny administracyjne; brak dostępu do rynków zewn.), potem przez chwilę podczas pandemii koronowirusa, kiedy zostały przerwane łańcuchy dostaw mimo że popyt się nie zmienił. W efekcie rzeczywiście pojawiła się podwyższona inflacja. Podobny problem występuje obecnie, gdy borykamy się z brakami surowców energetycznych z powodu zaprzestania handlu z Rosją. 

No dobrze, ale to jest przejściowa inflacja, którą można nazwać losową i która po czasie może nawet być skompensowana deflacją. Wielu liberałom i prawicowym publicystom wydaje się więc niemożliwe, żeby utrzymywała się długoterminowa inflacja bez zaangażowania banków centralnych. Na dowód mogą przedstawić nawet statystyki przed utworzeniem się tych instytucji w USA i po - bo rzeczywiście przed FEDem średni wzrost cen był zerowy (zob. art. FED do likwidacji?!). Zapominają jednak o tym, że przez cały ten okres istniał postęp technologiczny, który ograniczał rosnące koszty np. wydobycia surowców energetycznych. Wydobywanie surowców wymaga dostania się do coraz głębszych warstw Ziemi, co oczywiście rodzi wyższe koszty, a postęp techniczny redukował je.

Wyobraźmy sobie, że postęp techniczny nie występuje oraz M nie zmienia się. Wydobywanie surowców staje się coraz droższe. Skoro nie mamy więcej pieniędzy, aby ponieść te koszty, podaż surowców staje w miejscu. Spadek podaży podnosi ceny.

Wzrost szybkości obiegu pieniądza

Teoretycznie jest też możliwość, że M i P pozostaną stałe, a V się zmieni. Dobrym przykładem jest giełda. Spekulanci mogą dokonać zmowy, że będą przez określony czas kupować i sprzedawać od siebie nawzajem, aby wywindować cenę waloru, aby naiwnym sprzedać na górce. Wzrasta ilość transakcji wraz z którymi rośnie cena, chociaż ani liczba dóbr się nie zmieniła (jedna i ta sama firma, której sytuacja się nie zmieniła), ani ilość pieniędzy (cała akcja była od początku zaplanowana, czyli pieniądze musiały być przygotowane). Nawet gdyby traderzy nie sprzedali na końcu komuś naiwnemu, to wynieśli kurs w górę, tylko wykorzystując swoje pieniądze na koncie, które potem do nich wracają. Jeżeli ich plan by się powiódł, to należy dodatkowo założyć, że ostatni naiwny też musi wykorzystać pieniądze, które trzymał wcześniej na koncie.

Żeby giełdy przełożyć na sferę makro, trzeba uznać, że skłonność do konsumpcji i inwestycji w społeczeństwie nagle wzrasta. Ale ciągle zakładamy, że ilość dóbr i usług pozostaje bez zmian, tak że wzrasta jedynie liczba zawartych transakcji, tj. V. Jak to możliwe, że ludzie więcej inwestują, a Q nie wzrośnie? Dokładnie na tej samej zasadzie jak powyższy przykład z giełdą. Ludzie mogą kupować akcje lub certyfikaty na surowce (może nawet kryptowaluty), podnosząc ich ceny. Realnie nic się nie zmieniło, a ilość pieniędzy została ta sama. Ale to można rozszerzyć na całą gospodarkę: zgodnie z podstawowym modelem popytu, jeśli podaż pozostaje ta sama, a popyt rośnie, to cena rośnie. A więc ludzie wydają na to samo więcej pieniędzy, ponieważ nie chcą ich trzymać w portfelu czy "skarpecie", w wyniku czego ceny musza się dostosować. 

Z czego może wynikać większa skłonność do konsumpcji lub inwestycji? Pośrednie wytłumaczenie możemy znaleźć u M. Keynesa, który przedstawił różne pobudki trzymania pieniądza i wymienił m.in. powód spekulacyjny. Jeżeli przewidujemy, że cena towaru będzie rosła, będziemy szybciej, czasem więcej go kupować. 

Wzrost podaży pieniądza

Jeżeli Q i V pozostają stałe, to jedynym czynnikiem inflacyjnym będzie podaż pieniądza. Mogą tu działać dwa mechanizmy. Pierwszy to tzw. rozdawnictwo, którego nie trzeba wyjaśniać. Drugi jest nieco bardziej złożony. Najłatwiej pomyśleć o pieniądzu jako towarze. Im większa podaż, tym niższa cena - tu stopa procentowa. banki mają nadpłynność, więc aby się jej pozbyć, oferują tanie kredyty. Ludzie zaciągają więcej kredytów na wydatki, co generuje inflację.

Pierwsze dwa czynniki dowodzą, że inflacja nie musi być żadnym podatkiem, bo może być niezależna od władzy. Ale co z podażą pieniądza? Ponieważ jest ona kontrolowana przez banki centralne, które z kolei są kontrolowane de facto przez rządy, czy nie jest słusznym przyznać rację tym, którzy twierdzą, iż rząd wywołuje inflację, aby podnieść nominalnie podatki i inne opłaty? A tym samym inflacja stanowi ukryty podatek?

Problem polega na tym, że taka inflacja nie tworzy się sama z siebie albo przez rząd, tylko przedsiębiorców, którzy NA POCZĄTKU podnoszą ceny - BO MOGĄ. Dopiero potem już nie mogą, ale muszą, ponieważ rosną koszty wytworzenia. To znaczy, że firmy rekompensują sobie wyższe koszty i łańcuch inflacyjny w gospodarce się rozpędza. 

Kiedy słyszymy albo czytamy, że przez inflację wszyscy tracimy (no bo przecież to podatek), to mamy do czynienia z propagandą, ewentualnie z niewiedzą. Sumarycznie w sensie księgowym nic się nie zmieniło: ludzie dostają więcej pieniędzy i o tyle więcej płacą za towary i usługi. To że dystrybucja może być niesprawiedliwa, to zupełnie inna sprawa. Czasami za koszty inflacji uznaje się tzw. koszt zdartych zelówek (kiedyś ludzie musieli często chodzić do banków, by odebrać pieniądze) czy tzw. koszty zmian jadłospisu (częsta zmiana cen na etykietach), ale w dzisiejszych czasach mają nikłe znaczenie.

Problem powstaje dopiero, gdy zaczynamy doliczać koszty ekonomiczne. Wyższa inflacja to wyższa niepewność co do przyszłości, co blokuje inwestycje długoterminowe. Maleje skłonność do inwestowania w projekty dalekiego zasięgu, a ludzie skupiają się na poprawie swojej bieżącej sytuacji. Dopiero ten koszt można nazwać ukrytym podatkiem, ponieważ dla bieżącej władzy jest lepiej, jeśli ludzie mają większe nominalne przychody tu i teraz (gdyż może je wykorzystać na swoje cele), a nie za 5 czy 10 lat, gdy nie wiadomo, kto będzie u władzy.

Jeżeli nadmierna w stosunku do PKB podaż pieniądza kreuje inflację, to i tak pojawienie się kosztu niepewności (inflacji w kolejnych okresach) utożsamimy z rodzajem podatku dopiero tylko wtedy, gdy rząd celowo ten koszt wykreował (po to aby ludzie skupili się na teraźniejszych wydatkach). To również oznacza, że moglibyśmy popatrzeć na inflację przez pryzmat krzywej Laffera. Jak wiadomo krzywa ta wskazuje, że wzrost podatków tylko do pewnego stopnia zwiększa przychody dla państwa, a potem firmy albo unikają płacenia podatków (szara strefa), albo uciekają za granicę, albo ogłaszają upadłość czy likwidują się. Przykładowo poniższy rysunek prezentuje estymację krzywej Laffera dla podatku od dochodów osobistych dla strefy euro [1]:



[1] Źródło: Espanhol, R. J. F. (2014). The Laffer Curve – An Empirical Estimation For Eurozone Member Countries. Lisboa. ISCTE Business School. Instituto Universitário de Lisboa. Master in Economics. 11.

piątek, 12 sierpnia 2022

Oczyszczanie zysku netto z niepewnych pozycji

Ostatni wpis skłonił mnie do stworzenia formuły na oczyszczony zysk netto z niepewnych lub uznaniowych elementów, jak zmiany w aktywach rzeczowych. Owszem, mają one jakąś wartość, ale realne korzyści są odłożone w niepewną przyszłość, a w dodatku jeżeli ich wycena została dokonana przez samą firmę, to istnieje ryzyko, że nie odzwierciedla ona faktycznej wartości wewnętrznej tego aktywa. W sprawozdaniu finansowym PKN Orlen można znaleźć metodologię wyceny odpisów aktualizujących wpływającą na wynik finansowy, jednak po pobieżnym przeczytaniu dostrzegłem kilka założeń za nią stojących. Nie chcę ich tu przywoływać, ale żeby sprawdzić ich poprawność, trzeba by dokładnie je prześledzić. W dodatku powstawanie różnicy między sumą zysków z 4 kwartałów a zyskiem za cały rok przez kilka lat rzędu pozwala powątpiewać w słuszność uznawania zmian w aktywach trwałych za coś realnego.

Przypomnę teraz wzór, jaki pokazałem w tym art. (był to wzór nr 5):

(1)

Czyli zmiana stanu gotówki (w ogólnym sensie) = zysk netto + amortyzacja - zmiana stanu zapasów - zmiana należności + zmiana zobowiązań (krótkoterminowych i długoterminowych) - zmiana aktywów trwałych (wraz ze zmianą ich amortyzacji)  - wypłacone dywidendy + emisja akcji.

Przedstawione równanie wskazuje relację między zyskiem księgowym a pieniężnym. Aby zysk netto stał się gotówką, trzeba odjąć lub dodać  wymienione pozycje.

Na wiele z tych pozycji możemy spojrzeć przez pryzmat ryzyka. Po prawej stronie leżą środki pieniężne, których ryzyko otrzymania jest zerowe, bo mamy je na koncie. Ryzyko bliskie zera dotyczy amortyzacji, która odzwierciedla zużywanie się środków trwałych. Ich zakup odbył się w przeszłości i ten koszt został rozbity na wiele okresów do przodu. 

Omówimy teraz po kolei te elementy.

Amortyzacja

W momencie zakupu środków trwałych ponosimy na nie wydatki, ale ponieważ środki te nie są w całości wykorzystane do produkcji, ale stopniowo, to nie stanowią kosztu uzyskania przychodów. Dlatego owe wydatki są rozpisane w formie kosztu poprzez podział na wiele okresów do przodu - stąd powstaje amortyzacja w kolejnych miesiącach czy latach. 

W tym momencie można zauważyć różnicę między spojrzeniem księgowego a inwestora: księgowego interesuje średni zysk firmy ze wszystkich okresów, z kolei inwestora zysk firmy z ostatniego okresu. Inaczej mówiąc księgowego interesują wartości średnie, inwestora - wartości krańcowe. Wynika to z faktu, że księgowy zajmuje się przeszłą oraz teraźniejszą sytuacją finansową, natomiast inwestor przyszłą i korzysta do tego z bieżących danych.

Mimo tej różnicy obie perspektywy się zazębiają. Zakupiony środek trwały pracuje przez lata, ale też fizycznie i ekonomicznie się amortyzuje, co właśnie odzwierciedla księgowa amortyzacja. Jeżeli maszyna zaczyna się np. zacinać, to jest to element tego kosztu. Co więcej, jeśli można by ją zastąpić nowocześniejszą wersją, to także mamy do czynienia z tym kosztem (zob. np. art. 32, p. 2 Ustawy o Rachunkowości) Jeżeli przestaje być ona zdatna do użytku i trzeba ją wymienić, to środek zostaje fizycznie zamortyzowany. Jeżeli firma jest zmuszona do zakupu nowej maszyny, to znowu nie zobaczymy tego wydatku w obniżonym zysku, ale jednak gotówka się zmniejszyła. Zatem amortyzację można traktować dwojako: 

(a) jako koszt fizycznego i ekonomicznego zużycia lub

(b) jako rodzaj kosztu rezerwy albo średni wydatek ważony ryzykiem nowych wydatków.

Powyższe dowodzi, że powszechne twierdzenie, iż firma może wypłacić dywidendę nie tylko z zysku netto, ale też z amortyzacji, jest fałszywe. Chociaż w pewnych okresach będzie prawdziwe, to nie raz się zdarzy, że firma nie będzie mogła wypłacić (dużej) dywidendy, bo albo musiała wydać pieniądze na inwestycje w środki trwałe, albo przewiduje, że za chwilę będzie musiała je wydać. 

Niemniej problemem pozostaje ustalenie okresu amortyzacji i stawek amortyzacyjnych, które mogą rozmijać się z rzeczywistą użytecznością aktywów. To tutaj leży element niepewności, który inwestor powinien rozważyć, tzn. czy dodać do zysku amortyzację, jeśli tak, czy całą, czy tylko część i jaką. 

Możemy przyjąć założenie, że jeśli wartość środków trwałych rośnie o więcej niż zobowiązania finansowe oraz emisja akcji, to nie dodajemy w ogóle amortyzacji, a jeśli o mniej - to dodajemy w zależności od naszego poziomu precyzji - albo całą amortyzację w uproszczeniu, albo taką część, która pozostanie jeszcze po zapłacie za nowe środki trwałe. W tym drugim przypadku dodamy kwotę równą:

amortyzacja - min(amortyzacja, x), 

gdzie x to różnica między wzrostem wartości środków trwałych a wzrostem zobowiązań finansowych i nowych emisji akcji. 

W tym miejscu dość istotna uwaga. We wzorze (1) występuje określenie gross fixed assets oznaczające aktywa trwałe brutto, czyli aktywa trwałe netto powiększone o ich amortyzację. Ta amortyzacja występuje właśnie dlatego, że może finansować owe środki. Ale jest ona odejmowana, wraz ze zmianą środków trwałych, więc całkowita amortyzacja ulega pomniejszeniu. Możemy tę trudność ominąć. Mamy do czynienia ze zmianą tych środków, czyli:

środki netto z okresu 1 + amortyzacja tych środków z okresu 1 - środki netto z okresu 0 - amortyzacja tych środków z okresu 0.

Stąd:

(środki netto z okresu 1 - środki netto z okresu 0) + (amortyzacja środków brutto z okresu 1 - amortyzacja środków brutto z okresu 0).

Inaczej:

zmiana środków trwałych netto + zmiana amortyzacji środków trwałych brutto.

Jeżeli amortyzacja w okresie bieżącym jest zbliżona do amortyzacji z okresu poprzedniego, to zmiana jest zerowa. Przyjmiemy to założenie, które wyeliminuje konieczność korygowania amortyzacji. Innymi słowy będziemy posługiwać się aktywami trwałymi netto, zamiast brutto.

Zmiana stanu zapasów

Często niezrozumiałe jest dla wielu, dlaczego nowe zapasy są ujmowane jako część przychodów, skoro są... no właśnie tylko zapasami - nie zostały sprzedane. Wydaje się to bez sensu. Aby zrozumieć ten mechanizm, trzeba poznać zasady księgowości, jak kontynuacja działalności oraz współmierność kosztów do przychodów. Jeżeli w danym okresie firma kupuje zapasy, zwiększa poziom aktywów, które posłużą do produkcji, ale produkty gotowe będą sprzedane w przyszłości. Z powodu zasady współmierności kosztów i przychodów trzeba więc odjąć te wydatki z kosztów. Czyli koszty się zmniejszają. Ale zmniejszenie kosztów jest równoznaczne ze zwiększeniem przychodów o tyle samo. Stąd zysk netto zawiera sztucznie zmianę stanu zapasów na plus. Ze względu na zasadę kontynuacji działalności, przewidujemy, że w niedalekiej przyszłości (skoro to aktywa krótkoterminowe, to znaczy, że do 1 roku) zapasy przekształcą się w produkty gotowe i faktycznie zostaną sprzedane, generując realny cash.

Jak by nie patrzeć, to zmiana zapasów stanowi czynnik niepewności wyniku. Są branże bardziej pewne i mniej pewne, są firmy, które mają już ugruntowaną pozycję rynkową, ale też takie, które dopiero wchodzą na rynek. W księgach tego nie ujrzymy. Jeżeli mamy pewność, że firma sprzeda towary, to możemy pominąć zmianę zapasów, a jeśli nie mamy pewności, to lepiej odjąć. Analiza ta może być ciekawym zadaniem intelektualnym.

Jeżeli przyjmujemy brak pewności, to odejmujemy zapasy od zysku, czyli zostawiamy je po lewej stronie równania (1). Jeżeli wierzymy, że za chwilę wygenerują zysk, zostawiamy zapasy w zysku netto - wtedy przenosimy na prawą stronę.

Oczywiście możemy przyjąć rozwiązanie pośrednie i wybrać pewne prawdopodobieństwo przejścia zapasów z produkcji w realną sprzedaż. W ogólności wartość oczekiwana sprzedanych nowych zapasów byłaby równa:

(1-p1)*zmiana stanu zapasów , 

gdzie p1 - prawdopodobieństwo przejścia zapasów z produkcji w realną sprzedaż.

Do obliczeń można wspomóc się cyklem zapasów lub jego odwrotnością, tj. rotacją zapasów. O tym więcej przy omawianiu przykładów.

Zmiana należności

Należności w przeciwieństwie do zapasów są pozycją w pewną w tym sensie, że nasz kontrahent musi nam zapłacić za już sprzedane towary lub usługi. Oczywiście zawsze jest ryzyko, że nie zapłaci, ale dużo mniejsze niż to, że nie sprzedamy towarów, jak to było z zapasami. 

Dlatego należności zawsze przenosimy na prawą stronę.

Zmiana zobowiązań

To samo co z należnościami, tylko że to nasza firma musi zapłacić kontrahentowi. Czyli przenosimy zobowiązania na prawą stronę.

Zmiana aktywów trwałych

Aktywa trwałe mają na celu przynieść korzyści finansowe, jednak po pierwsze nie jest pewne ani to, że przyniosą, ani to, kiedy przyniosą, ani to, jak dużo przyniosą. Dlatego nie będziemy mieć oporów, aby pozostawić aktywa trwałe po lewej stronie (zostaną więc odjęte od zysku). Są jednak branże, w których aktywa trwałe mają szczególne znaczenie - budownictwo i nieruchomości. W ich przypadku aktywa trwałe stanowią dużą część wartości firmy, stąd odejmowanie całej tej pozycji jest niesprawiedliwe. Dla uproszczenia w przypadku takich branż potraktujemy aktywa trwałe jak zapasy, a więc przemnożymy zmianę aktywów trwałych przez (1-p1). 

Wypłata dywidend

Dywidendy są nagrodą dla akcjonariuszy, ale dotyczą poprzedniego okresu. Ich wypłata to formalna operacja, która nie ma znaczenia dla działalności tu i teraz. Co więcej, nawet gdyby dywidendy dotyczyły bieżącego okresu, to nie ma to dla nas znaczenia, dlatego że oczyszczanie, jakiego dokonujemy ma na celu właśnie ocenić, czy spółka jest w ogóle w stanie wypłacić dywidendę z zysku. Gdyby po oczyszczeniu miała stratę, to mogłaby wypłacić dywidendę najwyżej z kapitału własnego, a to nas nie interesuje. Dlatego dywidendy przenosimy na prawą stronę, aby nie odejmować ich od zysku.

Emisja akcji

Analogiczna sytuacja jak w przypadku zobowiązań - nowy kapitał akcyjny jest to forma zobowiązań dla akcjonariuszy, a więc przenosimy na prawą stronę.


Oczyszczony zysk netto

Aby zachować równanie (1) dodamy i odejmiemy wszystkie dodatkowe elementy, o których było wyżej, a także przeniesiemy na prawą stronę te elementy, o których byłą mowa:

Zysk netto + amortyzacja - min(amortyzacja, x) + min(amortyzacja, x) - (1-p1)*(zmiana stanu zapasów) - p1*(zmiana stanu zapasów)  - (1-p2)*zmiana aktywów trwałych netto - p2*(zmiana aktywów trwałych netto) 

środki pieniężne + zmiana należności - zmiana zobowiązań (krótkoterminowych i długoterminowych) + wypłacone dywidendy – emisja akcji

Czyli:

(2)

Zysk netto + amortyzacja - min(amortyzacja, x) - (1-p1)*(zmiana stanu zapasów) – (1-p2)*(zmiana aktywów trwałych netto) = środki pieniężne + zmiana należności - zmiana zobowiązań (krótkoterminowych i długoterminowych) + wypłacone dywidendy – emisja akcji - min(amortyzacja, x) + p1*(zmiana stanu zapasów) + p2*(zmiana aktywów trwałych netto)   

Lewa strona (2) będzie stanowić oczyszczony zysk netto:

Oczyszczony zysk netto = Zysk netto + amortyzacja - min(amortyzacja, x) - (1-p1)*(zmiana stanu zapasów) – (1-p2)*(zmiana aktywów trwałych netto)

gdzie 
p1 = min(oczekiwane przychody  ze sprzedaży produktów * wskaźnik operacyjności / (średnie) zapasy ; 1)

gdzie
wskaźnik operacyjności = koszty wytwarzania / przychody ze sprzedaży produktów.
Jeżeli za oczekiwane przychody przyjmiemy bieżące przychody, wtedy
p1 = min(rotacja zapasów ; 1)
gdzie:
rotacja zapasów = koszty wytwarzania / zapasy

Definicji rotacji zapasów nie traktujmy zupełnie ściśle. Generalnie "wskazuje" ile razy zapasy są na nowo odtwarzane w ciągu danego okresu. Wynika to z faktu, że zapasy są aktywami krótkoterminowymi, więc są wykorzystywane do roku czasu i stąd mogą być porównywane z rocznymi kosztami firmy. Koszty wytwarzania będą prawie zawsze większe niż wartość zapasów (która stanowi koszt ich nabycia), ponieważ oprócz części zapasów zawierają m.in. koszty robocizny (pełna definicja tych kosztów znajduje się w art. 28, p. 3 Ustawy o rachunkowości). Są jednak wyjątki, jak branża deweloperska, gdzie rotacja zapasów jest zawsze mniejsza od 1. Od 1 kw 2016 do 1 kw 2022 rotacja wahała się od 0,5 do 1. Budynki buduje się zwykle kilka lat, a że to droga inwestycja, to nie sprzedaje się z dnia na dzień.
Często też spotykana jest rotacja zapasów w postaci:

rotacja zapasów = koszty wytwarzania / średnia zapasów z 4 ostatnich kwartałów.

x = zmiana aktywów trwałych netto - zmiana zobowiązań finansowych - emisja nowych akcji ;

p2 = p1 dla branży budowlanej lub nieruchomości, a dla pozostałych 0 lub inna subiektywna wartość.

Przykłady

a) PKN Orlen. Założenia: p1 = 1, p2 = 0. 
Wyniki 2021: źródło: link
Zysk netto = 11 188
amortyzacja = 5 341
aktywa trwałe netto 2021 = 68 706
aktywa trwałe netto 2020 = 59 433
zmiana aktywów trwałych =  68 706 - 59 433 = 9 273
zobowiązania finansowe 2021:
    długoterminowe: kredyty, pożyczki, leasing i obligacje = 18 618
    krótkoterminowe: kredyty, pożyczki, leasing i obligacje = 2 108
zobowiązania finansowe 2020:
    długoterminowe: kredyty, pożyczki i obligacje = 13 931
    krótkoterminowe: kredyty, pożyczki i obligacje = 5 643

zmiana zobowiązań fin = (18 618 + 2 108) - (13 931 + 5 643) = 1 152

x = 9 273 - 1 152 = 8 121

Oczyszczony zysk = 11 188 + 5 341 - min(5 341; 8 121) – 9 273 = 1915

O ile księgowy zysk netto wynosił ponad 11 mld zł, o tyle "faktyczny", oczyszczony ze zmian aktywów trwałych zysk wyniósł 1,9 mld zł, czyli tylko 17% pierwotnego. Okazuje się więc, że niewielka dywidenda 3,5 zł stanowi prawie 80% całego zysku (3,5 / 26 = 13,5% => 13,5 / 17 = 79%). Zwróćmy jeszcze uwagę, że cena / oczyszczony zysk dawałoby 15-16.


b) Kolejnym przykładem będzie Cavatina, spółka deweloperska. Podobnie jak PKN ma niskie C/Z oraz C/WK, obecnie odpowiednio 3,35 i 0,5, co oznacza ROE = 15% , a więc powyżej średniego kosztu kapitału własnego. Podobnie jak w przypadku PKN wydawałoby się, że jest niedowartościowana. Aby to ocenić, oczyśćmy zysk netto.
 
Źródło: biznesradar.pl (link).
Wyniki 2021:
Założenia: spróbujmy oszacować p1 przyjmując wzór:

p1 = min(rotacja zapasów ; 1)
rotacja zapasów = koszty wytwarzania / zapasy
koszty wytwarzania = 18 201
zapasy 2021 = 64 203
p1 = 18 201 / 64 203 = 0,28

p2 = p1

zapasy 2020 = 32 954
zmiana stanu zapasów = 64 203 - 32 954 = 31 249

Zysk netto = 189 620

amortyzacja = 3 733

aktywa trwałe netto 2021 = 2 150 469
aktywa trwałe netto 2020 = 1 292 025
zmiana aktywów trwałych = 858 444

zobowiązania finansowe 2021:
długoterminowe: kredyty, pożyczki, leasing i obligacje = 1 001 651
krótkoterminowe: kredyty, pożyczki, leasing i obligacje = 180 345
zobowiązania finansowe 2020:
długoterminowe: kredyty, pożyczki, leasing i obligacje = 490 949
krótkoterminowe: kredyty, pożyczki, leasing i obligacje = 74 614
zmiana zobowiązań fin = 616 433

x = 858 444 - 616 433 = 242 011

Oczyszczony zysk = 189 620 + 3 733 - min(3 733; 242 011) - (1-0,28)*31 249 - (1-0,28)*858 444 = -450 959

Komentarz:
Księgowy zysk netto Cavatiny wyniósł w 2021 prawie 190 mln zł, jednak po oczyszczeniu z pozycji niepewnych dostaliśmy stratę w tym sensie, że spółka nie jest w stanie wypłacić dywidendy z zysku. Potwierdzają to też przepływy z działalności oper., które są ujemne.

Dwie modyfikacje:
Biorąc pod uwagę, że w działalności deweloperskiej zapasy wolno schodzą, moglibyśmy posłużyć się wcześniej wspomnianym wzorem na rotację zapasów:

rotacja zapasów = koszty wytwarzania / średnia zapasów z 4 ostatnich kwartałów.

Taki wskaźnik oblicza biznesradar.pl , więc nie musimy się trudzić i to wykorzystamy. Wskaźnik na 2021 rok wyniósł 0,36, więc taki wstawiamy za p1 i p2:

Oczyszczony zysk = 189 620 + 3 733 - min(3 733; 242 011) - (1-0,36)*31 249 - (1-0,36)*858 444 = -379 784

Bardzo sympatyczne ze strony portalu, że podaje od razu wartości wskaźników w sektorze. Dla 2021 sektor miał rotację ponad 2 razy wyższą, bo 0,8. Co ciekawe, gdyby podstawić ten wskaźnik pod p1 i p2, oczyszczony zysk stałby się lekko dodatni. W dotychczasowej historii spółka osiągnęła raz taki poziom w 2020 r. Jeżeli wierzymy, że nastąpi regresja do średniej, to możemy wstawić średnią historyczną, która wynosi 0,72, wtedy zbliżymy się prawie do zera. 

Na 2021 C/Z wyniosło 2,9, a C/WK 0,52, co w tym momencie przestaje być niezrozumiałe czy nieracjonalne. Podobnie dziś nie ma sensu inwestować w takie akcje. Generalnie inwestorzy powinni rozważyć prędzej inwestowanie w jej obligacje, których rentowność znacznie przekracza 10% (zdaje się, że obecnie daje ok. 13%).  

środa, 3 sierpnia 2022

Kreatywna księgowość czy cudotwórca? Może ktoś wie?

Przed chwilą porównałem wyniki finansowe PKN Orlen w różnych okresach i zauważyłem dziwny błąd w sprawozdaniach w latach 2018-2021. Wchodzę najpierw na rok 2021:

https://www.orlen.pl/pl/relacje-inwestorskie/raporty-i-publikacje/sprawozdania/2021

i otwieram plik "Dane liczbowe ze sprawozdania" za cały rok. i wybieram dane skonsolidowane. W kom. D20 jest podany zysk netto  11 188

Następnie otwieram plik za 4 kwartał i w kom. D26 (12 MIESIĘCY ZAKOŃCZONE 31/12/2021) podano zysk netto 10 241. 

Skąd różnica 947 mln ? Normalnie roczny wynik powinien sumować się do kwartalnych.

Dalej, robię to samo dla roku 2020. Analogicznie widzę kwoty:  2 825 oraz  3 383 . Różnica: -558

Sprawdźmy dalej po kolei: 

2019:  4 298 vs 4 487 . Różnica =  -189

2018:  5 604 vs  5 511 . Różnica = 93

2017:  7 173  vs 7 173 . Różnica = 0

2016:   5 740 vs 5 740 . Różnica = 0

2015:   3 233 vs  3 233 . Różnica = 0

2014: (5 828) vs (5 828) . Różnica = 0


Aktualizacja:
Sprawdziłem sprawozdanie roczne. Wygląda na to, że mamy tu do czynienia z odwróceniem odpisów aktualizujących. No tak, miliard w te czy wewte, co za różnica? To przykład, jak bardzo należy być krytycznym w stosunku do zysku netto. Bez tego odwrócenia zysk na akcję wyniesie niecałe 24 zł. Warto też zauważyć, że Orlen ma niedużo środków pieniężnych na akcję, bo niecałe 7 zł. To też jest przyczyna, dlaczego dywidendy są tak niewielkie.

poniedziałek, 1 sierpnia 2022

Czy opłaca się kupować PKN Orlen?

 Ostatnio głośno o rekordowych wynikach PKN Orlen. W 2021 zwiększył zysk netto dla akcjonariuszy o ponad 300%, a w 1 kw 2022 o 50% r/r. Mimo to kurs wcale nie urósł, jak można by się tego spodziewać. Ale czy na pewno? Zauważmy, że zysk na akcję wyniósł na 2021 26 zł, a wypłacona dywidenda w 2022 to zaledwie 3,5 zł. Większość zysku przeznaczono na inwestycje. 

Problemem przy wycenie PKN jest duża zmienność jego wyników. Łatwiej podejść do ich prognozy od strony rentowności, która jest bardziej stabilna - ok. 11-11,5%. Jest to poziom długoterminowego kosztu kapitału własnego dla WIGu i powiedzmy, że mniej więcej też na PKN. Spółka przeznacza ostatnio coraz mniej na dywidendę, poniżej 25%. Powiedzmy, że za rok będzie to 20%. W takim razie oczekiwana stopa wzrostu wynosi 80%*11% = 8,8%. W takim razie dywidenda wzrosłaby za rok do ok. 3,8 zł. W optymistycznym wariancie, gdyby spółka potrafiła utrzymać taki wzrost, wartość akcji wyniosłaby 3,8/(0,11-0,088) = 173 zł. Jak widać jednak inwestorzy nie są tak optymistyczni. Długoterminowy nominalny wzrost gosp. Polski to ok. 6% i gdyby go użyć wtedy 3,8/(0,11-0,06) = 76 zł. Czyli tyle, ile obecnie wynosi kurs. Jednak poprawniejsza wycena powinna uwzględnić wyższy krótkoterminowy koszt kapitału. W dużej mierze wyższa cena ropy poprawiła wyniki PKN (wyższe przychody minus wyższe koszty o tyle samo daje ciągle wyższe zyski dzięki różnicy procentowej), ta przyczyniła się do wyższej inflacji (chociaż nie przesadzajmy z jej efektem, bo kosztuje tyle co 10 lat temu), rządy przestraszyły się inflacji (opóźniona reakcja o 2 lata - normalka) i zaczęły podnosić stopy. Wyższa stopa procentowa to wyższa rentowność obligacji, a więc i akcji, gdyż inwestorzy wymagają co najmniej takiego samego wzrostu na ryzykownych aktywach. To zatrzymuje wzrost kursów. Dodatkowo pojawiają się sygnały o nadchodzącej recesji. W sumie krótkoterminowy koszt kapitału wynosi obecnie co najmniej 15%, co można ustawić na kilka lat wprzód. Wtedy wycena wyjdzie na poziomie ok. 75-75,5 zł, tyle co dziś w środku sesji.

Możemy spróbować wyznaczyć 3-wartościowy quasi-kanał, w jakim kurs powinien obecnie oscylować. Wykorzystam do tego swoje wzory na wycenę inwestora krótkoterminowego i długoterminowego. 

Dla krótkoterminowego (zob. ten artykuł):

Dla długoterminowego (zob. ten artykuł):


Dla dywidendowego (zwykły wzór Gordona):

gdzie:

P - wartość wewnętrzna akcji

D - oczekiwana dywidenda brutto w kolejnym okresie

x - koszt transakcji od wartości akcji

k - koszt kapitału własnego (bez odejmowania podatków)

g - oczekiwana stopa wzrostu dywidendy brutto


Krótkoterminowy inwestor trzyma akcje rok i sprzedaje innemu krótkoterminowemu inwestorowi. Długoterminowy inwestor trzyma akcje wiele lat i sprzedaje innemu długoterminowemu. Inwestor dywidendowy nie sprzedaje nigdy akcji - stąd nie wliczamy kosztów transakcyjnych (od zakupu pomijamy).

Wycena dla krótkoterminowego:

P = 3.8 / (0.11 - (0.06 - 2*0.0039*(1+0.06)/(1+0.0039))) = 65 zł

Wycena dla długoterminowego:

P = 3.8/(0.11-(0.06*(1-0.0039)-0.0039)) = 70

Wycena dla dywidendowego:

P = 3.8/(0.11-0.06) = 76

Dla pierwszych lat koszt kapitału wyniesie 15-17%, ale jest to kompensowane wyższą oczekiwaną stopą wzrostu, stąd można od razu posługiwać się długoterminowymi parametrami. Dlatego kanał między 65 a 76 jest jak najbardziej racjonalny.

Oczywiście to powierzchowna analiza i wielu rzeczy nie uwzględnia, ale na ten moment ja nie widzę sensu kupowania akcji. 


P. S. Co do fuzji PKN Orlen i PGNiG ( (źródło)

- analityk Trigon uważa, że "dziś trudno oczekiwać istotnych efektów synergii wynikających z przeprowadzonego połączenia. Już przy fuzji Orlenu z Lotosem były one mgliste, a w przypadku fuzji z PGNiG są tym bardziej wątpliwe – twierdzi Kozak. Zauważa, że Orlen i PGNiG działają w nieco innych obszarach rynku, a to mocno utrudnia uzyskanie prostych synergii."

- analityk mbanku potwierdza: "połączenie Orlenu z PGNiG prawdopodobnie nie przyniesie istotnych synergii. Trudno będzie o nie w sytuacji, gdy obie grupy koncentrują swoją działalność w innych obszarach rynku".

Analitycy widzą też plusy w postaci większych aktywów, w tym większych możliwości regulowania zobowiązań. To jednak nie ma dużego znaczenia, a jedynie synergia przeniesie się na wartość akcji. Warto przypomnieć, że nieuzasadniona dywersyfikacja obniża cenę akcji (zob. art. Czy firma powinna dywersyfikować produkt? ). To przecież miało miejsce w przypadku kupna Polska Press przez Orlen. Wydano pieniądze, a żadna z tego poprawna inwestycja. Była ta jedynie polityczna inwestycja, niekorzystna dla inwestorów (zob. np. art. Wyborczej Orlen kupił wydmuszkę. Grupa Polska Press od dawna pozbywała się majątku). Biorąc pod uwagę te polityczne wydatki, należy się dwa razy zastanowić czy prezes Obajtek bardziej nie dba o interesy swojej partii niż firmy.