Uma série que se lembra de si mesma
Muitas séries carregam informação sobre o próprio futuro. Spreads de juros, volatilidade e a diferença entre dois preços relacionados tendem a voltar a um nível em vez de vagar livremente. Os modelos ARIMA capturam isso com três ideias: I, diferenciar a série para torná-la estacionária; AR, regredi-la sobre suas defasagens; MA, usar os erros de previsão recentes. Os retornos de ações quase não mostram essa memória, então o ARIMA cabe em séries persistentes ou com reversão à média.
import numpy as np
prices = np.array([100.0, 101.5, 103.2, 104.1, 106.0, 107.2])
print(np.diff(prices)) # first differences: the changes [1.5 1.7 0.9 1.9 1.2]
print(np.diff(prices, n=2)) # second differences: the change of the changes
print(np.diff(np.log(prices))) # the differenced log price is the log returnDiferenciação e autocorrelação
Preços vagam e não têm média estável; suas variações frequentemente têm. Tirar a primeira diferença (ordem d = 1) remove uma tendência, uma segunda (d = 2) uma tendência curva. A função de autocorrelação (ACF) mostra então a memória: seu valor na defasagem k é a correlação da série consigo mesma k passos antes, sum((x[t] - m) * (x[t+k] - m)) / sum((x[t] - m)**2). Uma ACF que decai devagar sugere um modelo AR; uma ACF perto de zero em todas as defasagens significa que não há nada a prever.
# The ACF of a persistent series decays slowly; the ACF of noise is near zero
import numpy as np
def acf(series, lags):
dev = series - series.mean()
total = np.sum(dev ** 2)
return np.array([np.sum(dev[:len(series) - k] * dev[k:]) / total for k in range(1, lags + 1)])
rng = np.random.default_rng(1)
noise = rng.normal(size=500)
persistent = np.empty(500)
persistent[0] = 0.0
for t in range(1, 500):
persistent[t] = 0.8 * persistent[t - 1] + noise[t] # an AR(1) with phi = 0.8
print(np.round(acf(persistent, 4), 3)) # decays slowly: 0.74, 0.58, 0.48, 0.39 in this sample
print(np.round(acf(noise, 4), 3)) # all near 0# Differencing a trending series makes its mean stable
import numpy as np
rng = np.random.default_rng(6)
trend = 100 + 0.5 * np.arange(200) + rng.normal(0, 1, size=200).cumsum() # a trending random walk
changes = np.diff(trend)
print(round(float(trend[:100].mean()), 1), round(float(trend[100:].mean()), 1)) # the level drifts: the halves differ a lot
print(round(float(changes[:100].mean()), 2), round(float(changes[100:].mean()), 2)) # the changes have a similar mean in both halvesAjustar um AR(1) e prever
Um AR(1) diz x[t] = c + phi * x[t-1] + ruído. É uma regressão linear de cada valor sobre o anterior: phi é a inclinação e c o intercepto, com as mesmas somas do beta do tópico CAPM. A previsão é recursiva: o primeiro passo é c + phi * last, e cada seguinte usa a previsão anterior. Para |phi| < 1 as previsões convergem à média de longo prazo c / (1 - phi), com velocidade dada por phi: uma série com reversão à média.
import numpy as np
def fit_ar1(series):
a, b = series[:-1], series[1:]
phi = np.sum((a - a.mean()) * (b - b.mean())) / np.sum((a - a.mean()) ** 2)
return float(b.mean() - phi * a.mean()), float(phi)
def forecast_ar1(last, c, phi, steps):
out, value = [], last
for _ in range(steps):
value = c + phi * value
out.append(value)
return np.array(out)
rng = np.random.default_rng(3)
x = np.empty(400)
x[0] = 2.0
for t in range(1, 400):
x[t] = 0.5 + 0.75 * x[t - 1] + rng.normal(0, 0.3) # true c = 0.5, phi = 0.75, mean 2.0
c, phi = fit_ar1(x)
print(round(c, 3), round(phi, 3))
print(np.round(forecast_ar1(4.0, c, phi, 5), 3), round(c / (1 - phi), 3))phi estatisticamente significativo num spread não garante lucro: custos, o tamanho do movimento frente ao ruído e a instabilidade da estimativa importam. Mantenha a disciplina habitual: ajustar num período, prever o seguinte e comparar com a previsão ingênua de «sem mudança». Um modelo que não a supera não achou nada.- ARIMA = diferenciação (I) + autorregressão (AR) + erros passados (MA); diferenciar transforma uma série com tendência em estacionária.
- A ACF na defasagem
ké a correlação da série consigo mesmakpassos antes; decaimento lento sugere um modelo AR. - Um ajuste AR(1) é uma regressão de
x[1:]sobrex[:-1]; as previsões se alimentam umas das outras e convergem ac / (1 - phi)se|phi| < 1; supere sempre a previsão «sem mudança».
A seguir: os modelos de volatilidade GARCH, prever não o nível dos retornos, mas a violência de seus movimentos.
Lab: o que é avaliado
- Remover a tendência com
difference25 pts - Medir a memória com
acf25 pts - Ajustar o modelo com
fit_ar125 pts - Olhar adiante com
forecast_ar125 pts