Código
!pip install statsforecast -U
Collecting statsforecast

  Downloading statsforecast-2.0.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.metadata (29 kB)

Requirement already satisfied: cloudpickle in /usr/local/lib/python3.12/dist-packages (from statsforecast) (3.1.2)

Collecting coreforecast>=0.0.12 (from statsforecast)

  Downloading coreforecast-0.0.16-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (3.7 kB)

Requirement already satisfied: numba>=0.55.0 in /usr/local/lib/python3.12/dist-packages (from statsforecast) (0.60.0)

Requirement already satisfied: numpy>=1.21.6 in /usr/local/lib/python3.12/dist-packages (from statsforecast) (2.0.2)

Requirement already satisfied: pandas>=1.3.5 in /usr/local/lib/python3.12/dist-packages (from statsforecast) (2.2.2)

Collecting scipy<1.16.0,>=1.7.3 (from statsforecast)

  Downloading scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (61 kB)

     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 62.0/62.0 kB 4.0 MB/s eta 0:00:00

Requirement already satisfied: statsmodels>=0.13.2 in /usr/local/lib/python3.12/dist-packages (from statsforecast) (0.14.5)

Requirement already satisfied: tqdm in /usr/local/lib/python3.12/dist-packages (from statsforecast) (4.67.1)

Collecting fugue>=0.8.1 (from statsforecast)

  Downloading fugue-0.9.2-py3-none-any.whl.metadata (18 kB)

Collecting utilsforecast>=0.1.4 (from statsforecast)

  Downloading utilsforecast-0.2.14-py3-none-any.whl.metadata (5.5 kB)

Requirement already satisfied: threadpoolctl>=3 in /usr/local/lib/python3.12/dist-packages (from statsforecast) (3.6.0)

Collecting triad>=1.0.0 (from fugue>=0.8.1->statsforecast)

  Downloading triad-1.0.0-py3-none-any.whl.metadata (6.6 kB)

Collecting adagio>=0.2.6 (from fugue>=0.8.1->statsforecast)

  Downloading adagio-0.2.6-py3-none-any.whl.metadata (1.8 kB)

Requirement already satisfied: llvmlite<0.44,>=0.43.0dev0 in /usr/local/lib/python3.12/dist-packages (from numba>=0.55.0->statsforecast) (0.43.0)

Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.12/dist-packages (from pandas>=1.3.5->statsforecast) (2.9.0.post0)

Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.12/dist-packages (from pandas>=1.3.5->statsforecast) (2025.2)

Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.12/dist-packages (from pandas>=1.3.5->statsforecast) (2025.2)

Requirement already satisfied: patsy>=0.5.6 in /usr/local/lib/python3.12/dist-packages (from statsmodels>=0.13.2->statsforecast) (1.0.2)

Requirement already satisfied: packaging>=21.3 in /usr/local/lib/python3.12/dist-packages (from statsmodels>=0.13.2->statsforecast) (25.0)

Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.12/dist-packages (from python-dateutil>=2.8.2->pandas>=1.3.5->statsforecast) (1.17.0)

Requirement already satisfied: pyarrow>=6.0.1 in /usr/local/lib/python3.12/dist-packages (from triad>=1.0.0->fugue>=0.8.1->statsforecast) (18.1.0)

Requirement already satisfied: fsspec>=2022.5.0 in /usr/local/lib/python3.12/dist-packages (from triad>=1.0.0->fugue>=0.8.1->statsforecast) (2025.3.0)

Downloading statsforecast-2.0.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (354 kB)

   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 354.6/354.6 kB 7.6 MB/s eta 0:00:00

Downloading coreforecast-0.0.16-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (287 kB)

   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 287.4/287.4 kB 14.3 MB/s eta 0:00:00

Downloading fugue-0.9.2-py3-none-any.whl (280 kB)

   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 280.5/280.5 kB 12.7 MB/s eta 0:00:00

Downloading scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (37.3 MB)

   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 37.3/37.3 MB 34.9 MB/s eta 0:00:00

Downloading utilsforecast-0.2.14-py3-none-any.whl (41 kB)

   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 41.0/41.0 kB 1.6 MB/s eta 0:00:00

Downloading adagio-0.2.6-py3-none-any.whl (19 kB)

Downloading triad-1.0.0-py3-none-any.whl (59 kB)

   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 60.0/60.0 kB 4.0 MB/s eta 0:00:00

Installing collected packages: scipy, coreforecast, utilsforecast, triad, adagio, fugue, statsforecast

  Attempting uninstall: scipy

    Found existing installation: scipy 1.16.3

    Uninstalling scipy-1.16.3:

      Successfully uninstalled scipy-1.16.3

Successfully installed adagio-0.2.6 coreforecast-0.0.16 fugue-0.9.2 scipy-1.15.3 statsforecast-2.0.3 triad-1.0.0 utilsforecast-0.2.14
Código
import yfinance as yf
import pandas as pd
Código
tickers = ['SPY', 'MSFT', 'AAPL', 'GOOG', 'AMZN', 'TSLA', 'NVDA', 'META', 'NKE', 'NFLX']
df = yf.download(tickers, start = '2018-01-01', end = '2022-12-31', progress=False)
df.head()
Price Close ... Volume
Ticker AAPL AMZN GOOG META MSFT NFLX NKE NVDA SPY TSLA ... AAPL AMZN GOOG META MSFT NFLX NKE NVDA SPY TSLA
Date
2018-01-02 40.341896 59.450500 52.888073 180.308456 79.198326 20.107000 57.670403 4.928806 237.909134 21.368668 ... 102223600 53890000 24752000 18151900 22483800 109668890 6511000 355616000 86655700 65283000
2018-01-03 40.334850 60.209999 53.756130 183.538528 79.566910 20.504999 57.661312 5.253191 239.413910 21.150000 ... 118071600 62176000 28604000 16886600 26061400 85913690 6091100 914704000 90070400 67822500
2018-01-04 40.522205 60.479500 53.950802 183.200623 80.267204 20.563000 57.624992 5.280881 240.423065 20.974667 ... 89738400 60442000 20092000 13880900 21912000 60296160 5780500 583268000 80636400 149194500
2018-01-05 40.983585 61.457001 54.736919 185.705200 81.262390 20.999001 58.115486 5.325634 242.025208 21.105333 ... 94640000 70894000 25582000 13574500 23407100 70332400 11632300 580124000 83524000 68868000
2018-01-08 40.831352 62.343498 54.970818 187.126434 81.345306 21.205000 58.633255 5.488816 242.467896 22.427334 ... 82271200 85590000 20952000 17994700 22113000 55801780 11905700 881216000 57319200 147891000

5 rows × 50 columns

Código
df = df.loc[:, (['Close'], tickers)]
df.columns = df.columns.droplevel() # drop MultiIndex
df = df.reset_index()
df.head()
Ticker Date SPY MSFT AAPL GOOG AMZN TSLA NVDA META NKE NFLX
0 2018-01-02 237.909134 79.198326 40.341896 52.888073 59.450500 21.368668 4.928806 180.308456 57.670403 20.107000
1 2018-01-03 239.413910 79.566910 40.334850 53.756130 60.209999 21.150000 5.253191 183.538528 57.661312 20.504999
2 2018-01-04 240.423065 80.267204 40.522205 53.950802 60.479500 20.974667 5.280881 183.200623 57.624992 20.563000
3 2018-01-05 242.025208 81.262390 40.983585 54.736919 61.457001 21.105333 5.325634 185.705200 58.115486 20.999001
4 2018-01-08 242.467896 81.345306 40.831352 54.970818 62.343498 22.427334 5.488816 187.126434 58.633255 21.205000
Código
prices = df.melt(id_vars = 'Date')
prices = prices.rename(columns={'Date': 'ds', 'Ticker': 'unique_id', 'value': 'y'})
prices = prices[['unique_id', 'ds', 'y']]
prices
unique_id ds y
0 SPY 2018-01-02 237.909134
1 SPY 2018-01-03 239.413910
2 SPY 2018-01-04 240.423065
3 SPY 2018-01-05 242.025208
4 SPY 2018-01-08 242.467896
... ... ... ...
12585 NFLX 2022-12-23 29.496500
12586 NFLX 2022-12-27 28.417000
12587 NFLX 2022-12-28 27.688000
12588 NFLX 2022-12-29 29.112000
12589 NFLX 2022-12-30 29.488001

12590 rows × 3 columns

Código
from statsforecast import StatsForecast
StatsForecast.plot(prices)

Código
import numpy as np
prices['rt'] = prices['y'].div(prices.groupby('unique_id')['y'].shift(1))
prices['rt'] = np.log(prices['rt'])

returns = prices[['unique_id', 'ds', 'rt']]
returns = returns.rename(columns={'rt':'y'})
returns
unique_id ds y
0 SPY 2018-01-02 NaN
1 SPY 2018-01-03 0.006305
2 SPY 2018-01-04 0.004206
3 SPY 2018-01-05 0.006642
4 SPY 2018-01-08 0.001827
... ... ... ...
12585 NFLX 2022-12-23 -0.009397
12586 NFLX 2022-12-27 -0.037284
12587 NFLX 2022-12-28 -0.025988
12588 NFLX 2022-12-29 0.050151
12589 NFLX 2022-12-30 0.012833

12590 rows × 3 columns

Código
StatsForecast.plot(returns)

Código
from statsforecast.models import (
    GARCH,
    ARCH,
    Naive
)

models = [ARCH(1),
          ARCH(2),
          GARCH(1,1),
          GARCH(1,2),
          GARCH(2,2),
          GARCH(2,1),
          Naive()
]
Código
sf = StatsForecast(
    models = models,
    freq = 'D',
    n_jobs = -1
)
Código
cv_df = sf.cross_validation(
    df = returns,
    h = 3,
    step_size = 3,
    n_windows = 4
  )
Código
cv_df.rename(columns = {'y' : 'actual'}, inplace = True)
cv_df.head()
unique_id ds cutoff actual ARCH(1) ARCH(2) GARCH(1,1) GARCH(1,2) GARCH(2,2) GARCH(2,1) Naive
0 AAPL 2022-12-14 2022-12-13 -0.015658 0.030564 0.158725 0.100231 0.031850 0.027510 0.144168 0.006760
1 AAPL 2022-12-15 2022-12-13 -0.047987 -0.014314 -0.060318 -0.037749 -0.014094 -0.012205 -0.054296 0.006760
2 AAPL 2022-12-16 2022-12-13 -0.014686 -0.010413 -0.052143 -0.032591 -0.011226 -0.010470 -0.046878 0.006760
3 AAPL 2022-12-19 2022-12-16 -0.016038 0.152584 0.046799 0.074569 0.035231 0.044523 0.044545 -0.014686
4 AAPL 2022-12-20 2022-12-16 -0.000528 -0.057466 -0.016061 -0.028084 -0.014461 -0.016310 -0.015667 -0.014686
Código
StatsForecast.plot(returns, cv_df.drop(['cutoff', 'actual'], axis=1))

Código
from utilsforecast.losses import mae
models = cv_df.columns.drop(['unique_id', 'ds', 'cutoff', 'actual'])
mae_cv = mae(cv_df, models=models, target_col='actual').set_index('unique_id')
mae_cv
ARCH(1) ARCH(2) GARCH(1,1) GARCH(1,2) GARCH(2,2) GARCH(2,1) Naive
unique_id
AAPL 0.077975 0.048595 0.041995 0.036358 0.032013 0.048181 0.028275
AMZN 0.054866 0.036183 0.049781 0.087932 0.034641 0.053740 0.030549
GOOG 0.064014 0.077783 0.034871 0.044885 0.069139 0.046962 0.025107
META 0.066190 0.054184 0.097462 0.062310 0.054716 0.055127 0.031542
MSFT 0.061414 0.048830 0.042613 0.045284 0.035957 0.036360 0.021308
NFLX 0.083756 0.049517 0.074574 0.070817 0.068258 0.063737 0.040425
NKE 0.049535 0.043981 0.052295 0.047702 0.041208 0.082685 0.053186
NVDA 0.054699 0.055230 0.075036 0.059946 0.086545 0.048740 0.060827
SPY 0.021160 0.045874 0.051711 0.029024 0.039172 0.024214 0.016481
TSLA 0.103263 0.080432 0.063288 0.110919 0.069790 0.088152 0.075786
Código
mae_cv.idxmin(axis=1)
0
unique_id
AAPL Naive
AMZN Naive
GOOG Naive
META Naive
MSFT Naive
NFLX Naive
NKE GARCH(2,2)
NVDA GARCH(2,1)
SPY Naive
TSLA GARCH(1,1)

Código
levels = [80, 95] # confidence levels for the prediction intervals

forecasts = sf.forecast(df=returns, h=3, level=levels)
forecasts.head()
unique_id ds ARCH(1) ARCH(1)-lo-95 ARCH(1)-lo-80 ARCH(1)-hi-80 ARCH(1)-hi-95 ARCH(2) ARCH(2)-lo-95 ARCH(2)-lo-80 ... GARCH(2,1) GARCH(2,1)-lo-95 GARCH(2,1)-lo-80 GARCH(2,1)-hi-80 GARCH(2,1)-hi-95 Naive Naive-lo-80 Naive-lo-95 Naive-hi-80 Naive-hi-95
0 AAPL 2022-12-31 0.131845 0.118932 0.123402 0.140288 0.144757 0.099994 0.092567 0.095138 ... 0.033592 0.032754 0.033044 0.034140 0.034430 0.002466 -0.037841 -0.059178 0.042773 0.064110
1 AAPL 2023-01-01 -0.049655 -0.062568 -0.058098 -0.041212 -0.036742 -0.037660 -0.045087 -0.042516 ... -0.013519 -0.014477 -0.014145 -0.012894 -0.012562 0.002466 -0.054536 -0.084711 0.059468 0.089643
2 AAPL 2023-01-02 -0.042871 -0.055783 -0.051314 -0.034427 -0.029958 -0.032514 -0.039942 -0.037371 ... -0.011435 -0.012353 -0.012035 -0.010834 -0.010516 0.002466 -0.067347 -0.104304 0.072279 0.109236
3 AMZN 2022-12-31 0.095811 0.088992 0.091352 0.100269 0.102630 0.166521 0.145923 0.153052 ... 0.123382 0.112073 0.115988 0.130776 0.134690 -0.002141 -0.043633 -0.065598 0.039352 0.061317
4 AMZN 2023-01-01 -0.036194 -0.043055 -0.040680 -0.031708 -0.029333 -0.063325 -0.084326 -0.077057 ... -0.046468 -0.057776 -0.053862 -0.039074 -0.035160 -0.002141 -0.060820 -0.091883 0.056539 0.087602

5 rows × 37 columns

De volta ao topo