Usando o pacote yfinance para capturar dados históricos

Código
# run in first lines for installing
!pip install yfinance
import pandas as pd
import yfinance as yf
import matplotlib.pyplot as plt
import numpy as np
Requirement already satisfied: yfinance in /usr/local/lib/python3.11/dist-packages (0.2.61)
Requirement already satisfied: pandas>=1.3.0 in /usr/local/lib/python3.11/dist-packages (from yfinance) (2.2.2)
Requirement already satisfied: numpy>=1.16.5 in /usr/local/lib/python3.11/dist-packages (from yfinance) (2.0.2)
Requirement already satisfied: requests>=2.31 in /usr/local/lib/python3.11/dist-packages (from yfinance) (2.32.3)
Requirement already satisfied: multitasking>=0.0.7 in /usr/local/lib/python3.11/dist-packages (from yfinance) (0.0.11)
Requirement already satisfied: platformdirs>=2.0.0 in /usr/local/lib/python3.11/dist-packages (from yfinance) (4.3.8)
Requirement already satisfied: pytz>=2022.5 in /usr/local/lib/python3.11/dist-packages (from yfinance) (2025.2)
Requirement already satisfied: frozendict>=2.3.4 in /usr/local/lib/python3.11/dist-packages (from yfinance) (2.4.6)
Requirement already satisfied: peewee>=3.16.2 in /usr/local/lib/python3.11/dist-packages (from yfinance) (3.18.1)
Requirement already satisfied: beautifulsoup4>=4.11.1 in /usr/local/lib/python3.11/dist-packages (from yfinance) (4.13.4)
Requirement already satisfied: curl_cffi>=0.7 in /usr/local/lib/python3.11/dist-packages (from yfinance) (0.10.0)
Requirement already satisfied: protobuf>=3.19.0 in /usr/local/lib/python3.11/dist-packages (from yfinance) (5.29.4)
Requirement already satisfied: websockets>=13.0 in /usr/local/lib/python3.11/dist-packages (from yfinance) (15.0.1)
Requirement already satisfied: soupsieve>1.2 in /usr/local/lib/python3.11/dist-packages (from beautifulsoup4>=4.11.1->yfinance) (2.7)
Requirement already satisfied: typing-extensions>=4.0.0 in /usr/local/lib/python3.11/dist-packages (from beautifulsoup4>=4.11.1->yfinance) (4.13.2)
Requirement already satisfied: cffi>=1.12.0 in /usr/local/lib/python3.11/dist-packages (from curl_cffi>=0.7->yfinance) (1.17.1)
Requirement already satisfied: certifi>=2024.2.2 in /usr/local/lib/python3.11/dist-packages (from curl_cffi>=0.7->yfinance) (2025.4.26)
Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.11/dist-packages (from pandas>=1.3.0->yfinance) (2.9.0.post0)
Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.11/dist-packages (from pandas>=1.3.0->yfinance) (2025.2)
Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.11/dist-packages (from requests>=2.31->yfinance) (3.4.2)
Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.11/dist-packages (from requests>=2.31->yfinance) (3.10)
Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.11/dist-packages (from requests>=2.31->yfinance) (2.4.0)
Requirement already satisfied: pycparser in /usr/local/lib/python3.11/dist-packages (from cffi>=1.12.0->curl_cffi>=0.7->yfinance) (2.22)
Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.11/dist-packages (from python-dateutil>=2.8.2->pandas>=1.3.0->yfinance) (1.17.0)
Código
# Using yfinance to get Petrobras prices
petro = yf.Ticker("PETR4.SA")

# get historical market data
# hist = petro.history(period = "5y")

# other way is determining a period
hist = petro.history(start="2007-01-01", end="2022-11-03")
Código
# get stock info: some of the features of yfinance
petro.info
{'address1': 'Avenida Henrique Valadares, 28',
 'city': 'Rio de Janeiro',
 'state': 'RJ',
 'zip': '20231-030',
 'country': 'Brazil',
 'phone': '55 21 3224 2401',
 'website': 'https://petrobras.com.br',
 'industry': 'Oil & Gas Integrated',
 'industryKey': 'oil-gas-integrated',
 'industryDisp': 'Oil & Gas Integrated',
 'sector': 'Energy',
 'sectorKey': 'energy',
 'sectorDisp': 'Energy',
 'longBusinessSummary': 'Petróleo Brasileiro S.A. - Petrobras explores, produces, and sells oil and gas in Brazil and internationally. It operates through three segments: Exploration and Production; Refining, Transportation & Marketing; and Gas & Low Carbon Energies. The Exploration and Production segment explores, develops, and produces crude oil, natural gas liquids, and natural gas primarily for supplies to the domestic refineries. The Refining, Transportation and Marketing segment engages in the refining, logistics, transport, acquisition, and export of crude oil; trading of oil products; and production of fertilizers, as well as holding interests in petrochemical companies. The Gas and Low Carbon Energies segment is involved in the logistic and trading of natural gas and electricity; transportation and trading of liquefied natural gas; generation of electricity through thermoelectric power plants; renewable energy business; low carbon business; and natural gas processing business, as well as production of biodiesel and its co-products. The company also engages in prospecting, drilling, refining, processing, trading, and transporting crude oil from producing onshore and offshore oil fields, and shale or other rocks, as well as oil products, natural gas, and other liquid hydrocarbons. In addition, it engages in the research, development, production, transportation, distribution, and trading of energy. The company was incorporated in 1953 and is headquartered in Rio de Janeiro, Brazil.',
 'fullTimeEmployees': 41778,
 'companyOfficers': [{'maxAge': 1,
   'name': 'Ms. Magda Maria de Regina Chambriard',
   'title': 'CEO & Non-Independent Director',
   'exercisedValue': 0,
   'unexercisedValue': 0},
  {'maxAge': 1,
   'name': 'Ms. Clarice  Coppetti',
   'age': 60,
   'title': 'Interim President, Chief Corporate Affairs Officer & Member of Executive Board',
   'yearBorn': 1964,
   'exercisedValue': 0,
   'unexercisedValue': 0},
  {'maxAge': 1,
   'name': 'Mr. Fernando Sabbi Melgarejo',
   'title': 'Chief Financial & Investor Relations Officer',
   'exercisedValue': 0,
   'unexercisedValue': 0},
  {'maxAge': 1,
   'name': 'Mr. Claudio Romeo Schlosser',
   'age': 60,
   'title': 'Chief Logistics, Commercialization & Markets Officer and Member of Executive Board',
   'yearBorn': 1964,
   'exercisedValue': 0,
   'unexercisedValue': 0},
  {'maxAge': 1,
   'name': 'Mr. William Franca da Silva',
   'age': 64,
   'title': 'Chief Industrial Processes & Products Officer and Member of Executive Board',
   'yearBorn': 1960,
   'exercisedValue': 0,
   'unexercisedValue': 0},
  {'maxAge': 1,
   'name': 'Mr. Mauricio Tiomno Tolmasquim',
   'age': 66,
   'title': 'Chief Energy Transition & Sustainability Officer and Member of Executive Board',
   'yearBorn': 1958,
   'exercisedValue': 0,
   'unexercisedValue': 0},
  {'maxAge': 1,
   'name': 'Mr. Ricardo Wagner de Araujo',
   'title': 'Chief Governance & Compliance Officer',
   'exercisedValue': 0,
   'unexercisedValue': 0},
  {'maxAge': 1,
   'name': 'Ms. Renata  Baruzzi',
   'title': 'Chief Engineering, Technology, & Innovation Officer',
   'exercisedValue': 0,
   'unexercisedValue': 0},
  {'maxAge': 1,
   'name': 'Mr. Hélio Siqueira Júnior',
   'title': 'Acting General Counsel',
   'exercisedValue': 0,
   'unexercisedValue': 0},
  {'maxAge': 1,
   'name': 'Mr. Bruno  Motta',
   'title': 'Executive Manager of Communication & Brands',
   'exercisedValue': 0,
   'unexercisedValue': 0}],
 'auditRisk': 2,
 'boardRisk': 2,
 'compensationRisk': 1,
 'shareHolderRightsRisk': 7,
 'overallRisk': 1,
 'governanceEpochDate': 1746057600,
 'executiveTeam': [],
 'maxAge': 86400,
 'priceHint': 2,
 'previousClose': 31.4,
 'open': 31.46,
 'dayLow': 31.14,
 'dayHigh': 31.53,
 'regularMarketPreviousClose': 31.4,
 'regularMarketOpen': 31.46,
 'regularMarketDayLow': 31.14,
 'regularMarketDayHigh': 31.53,
 'dividendRate': 5.1,
 'dividendYield': 16.25,
 'exDividendDate': 1748908800,
 'payoutRatio': 1.4075,
 'fiveYearAvgDividendYield': 20.11,
 'beta': 0.331,
 'trailingPE': 8.177546,
 'forwardPE': 3.8955224,
 'volume': 20075100,
 'regularMarketVolume': 20075100,
 'averageVolume': 45034059,
 'averageVolume10days': 37864920,
 'averageDailyVolume10Day': 37864920,
 'bid': 31.3,
 'ask': 31.32,
 'bidSize': 0,
 'askSize': 0,
 'marketCap': 419114811392,
 'fiftyTwoWeekLow': 29.66,
 'fiftyTwoWeekHigh': 40.76,
 'priceToSalesTrailing12Months': 0.84456044,
 'fiftyDayAverage': 32.949,
 'twoHundredDayAverage': 36.1443,
 'trailingAnnualDividendRate': 5.602,
 'trailingAnnualDividendYield': 0.17840765,
 'currency': 'BRL',
 'tradeable': False,
 'enterpriseValue': 732744187904,
 'profitMargins': 0.09696,
 'floatShares': 8112812836,
 'sharesOutstanding': 5446499840,
 'heldPercentInsiders': 0.0,
 'heldPercentInstitutions': 0.56811,
 'impliedSharesOutstanding': 13381699584,
 'bookValue': 30.712,
 'priceToBook': 1.0197968,
 'lastFiscalYearEnd': 1735603200,
 'nextFiscalYearEnd': 1767139200,
 'mostRecentQuarter': 1743379200,
 'earningsQuarterlyGrowth': 0.486,
 'netIncomeToCommon': 48114999296,
 'trailingEps': 3.83,
 'forwardEps': 8.04,
 'lastSplitFactor': '2:1',
 'lastSplitDate': 1209340800,
 'enterpriseToRevenue': 1.477,
 'enterpriseToEbitda': 3.734,
 '52WeekChange': -0.15158063,
 'SandP52WeekChange': 0.09362543,
 'lastDividendValue': 0.909166,
 'lastDividendDate': 1748908800,
 'quoteType': 'EQUITY',
 'currentPrice': 31.32,
 'targetHighPrice': 48.5,
 'targetLowPrice': 35.3,
 'targetMeanPrice': 43.02727,
 'targetMedianPrice': 43.0,
 'recommendationMean': 1.58333,
 'recommendationKey': 'buy',
 'numberOfAnalystOpinions': 11,
 'totalCash': 44038000640,
 'totalCashPerShare': 3.417,
 'ebitda': 196239998976,
 'totalDebt': 370313986048,
 'quickRatio': 0.408,
 'currentRatio': 0.718,
 'totalRevenue': 496251994112,
 'debtToEquity': 93.137,
 'revenuePerShare': 38.496,
 'returnOnAssets': 0.08658,
 'returnOnEquity': 0.12019,
 'grossProfits': 246470000640,
 'freeCashflow': 101453996032,
 'operatingCashflow': 206894006272,
 'earningsGrowth': 0.489,
 'revenueGrowth': 0.046,
 'grossMargins': 0.49666,
 'ebitdaMargins': 0.39543998,
 'operatingMargins': 0.35481998,
 'financialCurrency': 'BRL',
 'symbol': 'PETR4.SA',
 'language': 'en-US',
 'region': 'US',
 'typeDisp': 'Equity',
 'quoteSourceName': 'Delayed Quote',
 'triggerable': False,
 'customPriceAlertConfidence': 'LOW',
 'shortName': 'PETROBRAS   PN      N2',
 'earningsTimestamp': 1754593200,
 'earningsTimestampStart': 1754593200,
 'earningsTimestampEnd': 1754593200,
 'earningsCallTimestampStart': 1754650740,
 'earningsCallTimestampEnd': 1754650740,
 'isEarningsDateEstimate': False,
 'epsTrailingTwelveMonths': 3.83,
 'epsForward': 8.04,
 'epsCurrentYear': 7.42,
 'priceEpsCurrentYear': 4.221024,
 'fiftyDayAverageChange': -1.6290016,
 'fiftyDayAverageChangePercent': -0.04944009,
 'twoHundredDayAverageChange': -4.824299,
 'twoHundredDayAverageChangePercent': -0.1334733,
 'sourceInterval': 15,
 'exchangeDataDelayedBy': 15,
 'averageAnalystRating': '1.6 - Buy',
 'cryptoTradeable': False,
 'longName': 'Petróleo Brasileiro S.A. - Petrobras',
 'corporateActions': [{'header': 'Dividend',
   'message': 'PETR4.SA announced a cash dividend of 0.909 with an ex-date of Jun. 3, 2025',
   'meta': {'eventType': 'DIVIDEND',
    'dateEpochMs': 1748919600000,
    'amount': '0.909'}}],
 'regularMarketTime': 1748289296,
 'exchange': 'SAO',
 'messageBoardId': 'finmb_409268',
 'exchangeTimezoneName': 'America/Sao_Paulo',
 'exchangeTimezoneShortName': 'BRT',
 'gmtOffSetMilliseconds': -10800000,
 'market': 'br_market',
 'esgPopulated': False,
 'regularMarketChangePercent': -0.25477684,
 'regularMarketPrice': 31.32,
 'marketState': 'POST',
 'hasPrePostMarketData': False,
 'firstTradeDateMilliseconds': 946900800000,
 'regularMarketChange': -0.07999992,
 'regularMarketDayRange': '31.14 - 31.53',
 'fullExchangeName': 'São Paulo',
 'averageDailyVolume3Month': 45034059,
 'fiftyTwoWeekLowChange': 1.6599998,
 'fiftyTwoWeekLowChangePercent': 0.05596763,
 'fiftyTwoWeekRange': '29.66 - 40.76',
 'fiftyTwoWeekHighChange': -9.439999,
 'fiftyTwoWeekHighChangePercent': -0.23159958,
 'fiftyTwoWeekChangePercent': -15.158063,
 'trailingPegRatio': 0.2287}
Código
hist
Open High Low Close Volume Dividends Stock Splits
Date
2007-01-02 00:00:00-02:00 6.481254 6.539585 6.450143 6.522734 10244800 0.225 0.0
2007-01-03 00:00:00-02:00 6.501992 6.533102 6.223298 6.324406 19898600 0.000 0.0
2007-01-04 00:00:00-02:00 6.286814 6.319221 6.144227 6.183115 21060200 0.000 0.0
2007-01-05 00:00:00-02:00 6.118303 6.220707 5.846090 5.995159 24864000 0.000 0.0
2007-01-08 00:00:00-02:00 6.027566 6.110526 5.936828 6.065157 19440200 0.000 0.0
... ... ... ... ... ... ... ...
2022-10-26 00:00:00-03:00 19.465428 20.020730 19.047459 19.531109 121334800 0.000 0.0
2022-10-27 00:00:00-03:00 19.590822 20.026704 19.507226 19.680386 111008800 0.000 0.0
2022-10-28 00:00:00-03:00 19.525141 19.775921 19.023578 19.447517 129745400 0.000 0.0
2022-10-31 00:00:00-03:00 18.277200 18.868328 17.411406 17.799520 262409400 0.000 0.0
2022-11-01 00:00:00-03:00 18.253316 18.313026 17.650246 17.829376 115944200 0.000 0.0

3927 rows × 7 columns

Código
# creating log returns
log_prices = np.log(hist["Close"])
log_returns = log_prices.diff().dropna()

# another way without using first differences and log
log_returns2 = hist["Close"].pct_change().dropna()
Código
log_prices
Close
Date
2007-01-02 00:00:00-02:00 1.875294
2007-01-03 00:00:00-02:00 1.844416
2007-01-04 00:00:00-02:00 1.821822
2007-01-05 00:00:00-02:00 1.790952
2007-01-08 00:00:00-02:00 1.802560
... ...
2022-10-26 00:00:00-03:00 2.972009
2022-10-27 00:00:00-03:00 2.979622
2022-10-28 00:00:00-03:00 2.967719
2022-10-31 00:00:00-03:00 2.879172
2022-11-01 00:00:00-03:00 2.880847

3927 rows × 1 columns


Código
log_returns
Close
Date
2007-01-03 00:00:00-02:00 -0.030878
2007-01-04 00:00:00-02:00 -0.022594
2007-01-05 00:00:00-02:00 -0.030870
2007-01-08 00:00:00-02:00 0.011608
2007-01-09 00:00:00-02:00 -0.031039
... ...
2022-10-26 00:00:00-03:00 -0.024760
2022-10-27 00:00:00-03:00 0.007614
2022-10-28 00:00:00-03:00 -0.011903
2022-10-31 00:00:00-03:00 -0.088548
2022-11-01 00:00:00-03:00 0.001676

3926 rows × 1 columns


Código
log_returns2
Close
Date
2007-01-03 00:00:00-02:00 -0.030406
2007-01-04 00:00:00-02:00 -0.022341
2007-01-05 00:00:00-02:00 -0.030398
2007-01-08 00:00:00-02:00 0.011676
2007-01-09 00:00:00-02:00 -0.030562
... ...
2022-10-26 00:00:00-03:00 -0.024456
2022-10-27 00:00:00-03:00 0.007643
2022-10-28 00:00:00-03:00 -0.011833
2022-10-31 00:00:00-03:00 -0.084741
2022-11-01 00:00:00-03:00 0.001677

3926 rows × 1 columns


Código
# ploting the log returns
plt.plot(log_returns);
plt.title("Plot of Daily log-Returns of PETR4");
plt.ylabel("Percentage (%)");

Código
# ploting the prices
plt.plot(log_prices);
plt.title("Plot of Daily log-Prices of PETR4");
plt.ylabel("Log");

Volatility modeling in Python

Vamos usar o pacote arch para estimar os modelos. Também podemos encontrar algumas postagens em que os modelos GARCH são estimados usando otimização (estilo solver), dado que são modelos determinísticos da volatilidade. Para mais detalhes do pacote: https://arch.readthedocs.io/en/latest/univariate/introduction.html

Código
# analyzing the ACF of returns and quadratic returns
# !pip install statsmodels
from statsmodels.tsa.stattools import adfuller
from statsmodels.tsa.seasonal import seasonal_decompose
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf

# ADF test: unit root
adf = adfuller(log_prices)
print('ADF Statistic: {}'.format(adf[0]))
print('p-value: {}'.format(adf[1]))
print('Critical Values:')
for key, value in adf[4].items():
    print('\t{}: {}'.format(key, value))
ADF Statistic: -1.62842494696922
p-value: 0.46831526608825136
Critical Values:
    1%: -3.432019708703093
    5%: -2.8622777859108606
    10%: -2.567162732014412
Código
# ACF of log_prices
plot_acf(log_prices, lags=60);

Código
# ACF of log_returns
plot_acf(log_returns, lags=60);

Código
# ACF of quadratic returns: see the conditional homoscedasticity
plot_acf(log_returns**2, lags=60);

Código
# run first line for installing the library
!pip install -q arch
from arch import arch_model
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/985.3 kB ? eta -:--:--
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 143.4/985.3 kB 4.0 MB/s eta 0:00:01
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 983.0/985.3 kB 15.4 MB/s eta 0:00:01
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 985.3/985.3 kB 12.1 MB/s eta 0:00:00

Código
# creating a ARCH(12) model with constant mean
garch = arch_model(log_returns, vol='ARCH', p=12, rescale=False).fit(disp='off')
print(garch.summary())
                      Constant Mean - ARCH Model Results                      
==============================================================================
Dep. Variable:                  Close   R-squared:                       0.000
Mean Model:             Constant Mean   Adj. R-squared:                  0.000
Vol Model:                       ARCH   Log-Likelihood:                8798.22
Distribution:                  Normal   AIC:                          -17568.4
Method:            Maximum Likelihood   BIC:                          -17480.6
                                        No. Observations:                 3926
Date:                Mon, May 26 2025   Df Residuals:                     3925
Time:                        20:16:52   Df Model:                            1
                                 Mean Model                                 
============================================================================
                 coef    std err          t      P>|t|      95.0% Conf. Int.
----------------------------------------------------------------------------
mu         8.0039e-04  3.917e-04      2.044  4.100e-02 [3.272e-05,1.568e-03]
                               Volatility Model                              
=============================================================================
                 coef    std err          t      P>|t|       95.0% Conf. Int.
-----------------------------------------------------------------------------
omega      2.3896e-04  3.730e-05      6.406  1.496e-10  [1.658e-04,3.121e-04]
alpha[1]       0.1333  5.601e-02      2.381  1.728e-02    [2.357e-02,  0.243]
alpha[2]       0.0870  2.515e-02      3.460  5.396e-04    [3.774e-02,  0.136]
alpha[3]       0.0622  2.741e-02      2.271  2.316e-02    [8.520e-03,  0.116]
alpha[4]       0.0945  2.799e-02      3.378  7.304e-04    [3.969e-02,  0.149]
alpha[5]       0.0748  2.494e-02      3.000  2.697e-03    [2.594e-02,  0.124]
alpha[6]       0.0732  2.989e-02      2.450  1.428e-02    [1.465e-02,  0.132]
alpha[7]       0.0610  2.351e-02      2.594  9.482e-03    [1.491e-02,  0.107]
alpha[8]       0.0277  3.094e-02      0.896      0.370 [-3.290e-02,8.836e-02]
alpha[9]       0.0214  3.071e-02      0.698      0.485 [-3.875e-02,8.165e-02]
alpha[10]      0.0427  2.613e-02      1.633      0.103 [-8.553e-03,9.386e-02]
alpha[11]      0.0144  1.838e-02      0.781      0.435 [-2.168e-02,5.038e-02]
alpha[12]      0.0295  2.484e-02      1.189      0.234 [-1.915e-02,7.823e-02]
=============================================================================

Covariance estimator: robust
Código
# creating a GARCH(1,1) model with constant mean
garch = arch_model(log_returns, vol='GARCH', p=1, q=1, rescale=False).fit(disp='off')
print(garch.summary())
                     Constant Mean - GARCH Model Results                      
==============================================================================
Dep. Variable:                  Close   R-squared:                       0.000
Mean Model:             Constant Mean   Adj. R-squared:                  0.000
Vol Model:                      GARCH   Log-Likelihood:                8804.70
Distribution:                  Normal   AIC:                          -17601.4
Method:            Maximum Likelihood   BIC:                          -17576.3
                                        No. Observations:                 3926
Date:                Mon, May 26 2025   Df Residuals:                     3925
Time:                        20:16:56   Df Model:                            1
                                  Mean Model                                 
=============================================================================
                 coef    std err          t      P>|t|       95.0% Conf. Int.
-----------------------------------------------------------------------------
mu         6.4826e-04  4.117e-04      1.574      0.115 [-1.587e-04,1.455e-03]
                              Volatility Model                              
============================================================================
                 coef    std err          t      P>|t|      95.0% Conf. Int.
----------------------------------------------------------------------------
omega      1.7367e-05  6.608e-12  2.628e+06      0.000 [1.737e-05,1.737e-05]
alpha[1]       0.1000  2.150e-02      4.651  3.307e-06   [5.786e-02,  0.142]
beta[1]        0.8800  1.788e-02     49.226      0.000     [  0.845,  0.915]
============================================================================

Covariance estimator: robust
Código
# creating a GARCH(1,1) model with AR(1) mean
garch = arch_model(log_returns,mean='ARX', lags=1, vol='GARCH', p=1, q=1, rescale=False).fit(disp='off')
print(garch.summary())
                           AR - GARCH Model Results                           
==============================================================================
Dep. Variable:                  Close   R-squared:                       0.001
Mean Model:                        AR   Adj. R-squared:                  0.000
Vol Model:                      GARCH   Log-Likelihood:                8803.73
Distribution:                  Normal   AIC:                          -17597.5
Method:            Maximum Likelihood   BIC:                          -17566.1
                                        No. Observations:                 3925
Date:                Mon, May 26 2025   Df Residuals:                     3923
Time:                        20:16:58   Df Model:                            2
                                  Mean Model                                 
=============================================================================
                 coef    std err          t      P>|t|       95.0% Conf. Int.
-----------------------------------------------------------------------------
Const      6.6950e-04  4.151e-04      1.613      0.107 [-1.441e-04,1.483e-03]
Close[1]      -0.0284  1.720e-02     -1.649  9.922e-02 [-6.208e-02,5.356e-03]
                              Volatility Model                              
============================================================================
                 coef    std err          t      P>|t|      95.0% Conf. Int.
----------------------------------------------------------------------------
omega      1.7390e-05  6.543e-12  2.658e+06      0.000 [1.739e-05,1.739e-05]
alpha[1]       0.1000  2.164e-02      4.622  3.802e-06   [5.759e-02,  0.142]
beta[1]        0.8800  1.796e-02     49.004      0.000     [  0.845,  0.915]
============================================================================

Covariance estimator: robust
Código
# creating a GARCH(1,1) model zero mean
garch = arch_model(log_returns,mean='Zero', vol='GARCH', p=1, q=1, rescale=False, dist='StudentsT').fit(disp='off')
print(garch.summary())
                          Zero Mean - GARCH Model Results                           
====================================================================================
Dep. Variable:                        Close   R-squared:                       0.000
Mean Model:                       Zero Mean   Adj. R-squared:                  0.000
Vol Model:                            GARCH   Log-Likelihood:                8969.36
Distribution:      Standardized Student's t   AIC:                          -17930.7
Method:                  Maximum Likelihood   BIC:                          -17905.6
                                              No. Observations:                 3926
Date:                      Mon, May 26 2025   Df Residuals:                     3926
Time:                              20:17:00   Df Model:                            0
                              Volatility Model                              
============================================================================
                 coef    std err          t      P>|t|      95.0% Conf. Int.
----------------------------------------------------------------------------
omega      1.2150e-05  1.010e-07    120.283      0.000 [1.195e-05,1.235e-05]
alpha[1]       0.0832  1.119e-02      7.440  1.009e-13   [6.130e-02,  0.105]
beta[1]        0.9050  8.850e-03    102.262      0.000     [  0.888,  0.922]
                              Distribution                              
========================================================================
                 coef    std err          t      P>|t|  95.0% Conf. Int.
------------------------------------------------------------------------
nu             5.4672      0.489     11.184  4.873e-29 [  4.509,  6.425]
========================================================================

Covariance estimator: robust
Código
 # creating a GARCH(1,1) model with constant mean and t-Student errors
garch = arch_model(log_returns,
                   vol='GARCH',
                   power=1.0,
                   dist='StudentsT',
                   rescale='False').fit(disp='off')
print(garch.summary())
                       Constant Mean - AVGARCH Model Results                        
====================================================================================
Dep. Variable:                        Close   R-squared:                       0.000
Mean Model:                   Constant Mean   Adj. R-squared:                  0.000
Vol Model:                          AVGARCH   Log-Likelihood:                8960.20
Distribution:      Standardized Student's t   AIC:                          -17910.4
Method:                  Maximum Likelihood   BIC:                          -17879.0
                                              No. Observations:                 3926
Date:                      Mon, May 26 2025   Df Residuals:                     3925
Time:                              20:17:02   Df Model:                            1
                                 Mean Model                                 
============================================================================
                 coef    std err          t      P>|t|      95.0% Conf. Int.
----------------------------------------------------------------------------
mu         7.2159e-04  3.563e-04      2.025  4.284e-02 [2.328e-05,1.420e-03]
                               Volatility Model                              
=============================================================================
                 coef    std err          t      P>|t|       95.0% Conf. Int.
-----------------------------------------------------------------------------
omega      1.4891e-03  5.312e-03      0.280      0.779 [-8.921e-03,1.190e-02]
alpha[1]       0.1119      0.146      0.766      0.444      [ -0.174,  0.398]
beta[1]        0.8591      0.310      2.768  5.634e-03      [  0.251,  1.467]
                              Distribution                              
========================================================================
                 coef    std err          t      P>|t|  95.0% Conf. Int.
------------------------------------------------------------------------
nu             5.4950      0.947      5.801  6.575e-09 [  3.639,  7.351]
========================================================================

Covariance estimator: robust
Código
 # creating a GARCH(1,1) model with constant mean, t-Student errors and asymmetric shocks (GJR-GARCH)
garch = arch_model(log_returns,
                   vol='GARCH',
                   p=1,
                   o=1,
                   q=1,
                   power=1.0,
                   dist='StudentsT',
                   rescale='False').fit(disp='off')
print(garch.summary())
                     Constant Mean - TARCH/ZARCH Model Results                      
====================================================================================
Dep. Variable:                        Close   R-squared:                       0.000
Mean Model:                   Constant Mean   Adj. R-squared:                  0.000
Vol Model:                      TARCH/ZARCH   Log-Likelihood:               -174551.
Distribution:      Standardized Student's t   AIC:                           349114.
Method:                  Maximum Likelihood   BIC:                           349152.
                                              No. Observations:                 3926
Date:                      Mon, May 26 2025   Df Residuals:                     3925
Time:                              20:17:05   Df Model:                            1
                                 Mean Model                                 
============================================================================
                 coef    std err          t      P>|t|      95.0% Conf. Int.
----------------------------------------------------------------------------
mu         7.4767e+06    549.386  1.361e+04      0.000 [7.476e+06,7.478e+06]
                            Volatility Model                            
========================================================================
                 coef    std err          t      P>|t|  95.0% Conf. Int.
------------------------------------------------------------------------
omega          0.2019      0.216      0.935      0.350 [ -0.221,  0.625]
alpha[1]   1.4089e-10      0.193  7.287e-10      1.000 [ -0.379,  0.379]
gamma[1]       2.0000      0.194     10.318  5.856e-25 [  1.620,  2.380]
beta[1]    1.0649e-12  5.526e-02  1.927e-11      1.000 [ -0.108,  0.108]
                              Distribution                              
========================================================================
                 coef    std err          t      P>|t|  95.0% Conf. Int.
------------------------------------------------------------------------
nu             2.0790  2.661e-05  7.813e+04      0.000 [  2.079,  2.079]
========================================================================

Covariance estimator: robust

Forecasting volatility

https://arch.readthedocs.io/en/latest/univariate/forecasting.html

Código
forecast = garch.forecast(horizon=1)
forecast.variance
h.1
Date
2022-11-01 00:00:00-03:00 2.236021e+14

Value at Risk

https://arch.readthedocs.io/en/latest/univariate/univariate_volatility_forecasting.html#Parametric-VaR

Código
am = arch_model(log_returns, vol="Garch", p=1, o=0, q=1, dist="skewt", rescale=False)
res = am.fit(last_obs="2021-12-31")
forecasts = res.forecast(start="2022-01-01", reindex=False)
cond_mean = forecasts.mean["2022":]
cond_var = forecasts.variance["2022":]
q = am.distribution.ppf([0.01, 0.05], res.params[-2:])
print(q)
Iteration:      1,   Func. Count:      8,   Neg. LLF: 390658.38455198176
Iteration:      2,   Func. Count:     25,   Neg. LLF: 2034024.2284916663
Iteration:      3,   Func. Count:     42,   Neg. LLF: 16498.978725178757
Iteration:      4,   Func. Count:     50,   Neg. LLF: 10573.706961983578
Iteration:      5,   Func. Count:     57,   Neg. LLF: 32414.19603278839
Iteration:      6,   Func. Count:     68,   Neg. LLF: 112992.94144688276
Iteration:      7,   Func. Count:     82,   Neg. LLF: 298402.49523688585
Iteration:      8,   Func. Count:     99,   Neg. LLF: 45317.94184255569
Iteration:      9,   Func. Count:    107,   Neg. LLF: 24093.969671964063
Iteration:     10,   Func. Count:    115,   Neg. LLF: 639752.9960794718
Iteration:     11,   Func. Count:    132,   Neg. LLF: 5296.4436541080495
Iteration:     12,   Func. Count:    139,   Neg. LLF: 1298916.2356498886
Iteration:     13,   Func. Count:    155,   Neg. LLF: 70671.20098488516
Iteration:     14,   Func. Count:    172,   Neg. LLF: 75000.91650616596
Iteration:     15,   Func. Count:    189,   Neg. LLF: 15932.571624307933
Iteration:     16,   Func. Count:    197,   Neg. LLF: 103958.72545870309
Iteration:     17,   Func. Count:    205,   Neg. LLF: 87203.09357116537
Iteration:     18,   Func. Count:    213,   Neg. LLF: 1075.6010042818489
Iteration:     19,   Func. Count:    220,   Neg. LLF: 86427.4585183924
Iteration:     20,   Func. Count:    229,   Neg. LLF: 96470.45294558411
Iteration:     21,   Func. Count:    246,   Neg. LLF: 13809.65099206184
Iteration:     22,   Func. Count:    257,   Neg. LLF: 445482.5913334888
Iteration:     23,   Func. Count:    265,   Neg. LLF: 216461.23297600297
Iteration:     24,   Func. Count:    278,   Neg. LLF: 2460.614347998372
Iteration:     25,   Func. Count:    286,   Neg. LLF: 5759.802064512188
Iteration:     26,   Func. Count:    296,   Neg. LLF: 1648382.8845535477
Iteration:     27,   Func. Count:    304,   Neg. LLF: 192289.94299340903
Iteration:     28,   Func. Count:    314,   Neg. LLF: -4995.750635278489
Optimization terminated successfully    (Exit mode 0)
            Current function value: -4995.750635030736
            Iterations: 32
            Function evaluations: 314
            Gradient evaluations: 28
[-2.28167218 -1.59717959]
Código
value_at_risk = -cond_mean.values - np.sqrt(cond_var).values * q[None, :]
value_at_risk = pd.DataFrame(value_at_risk, columns=["1%", "5%"], index=cond_var.index)
ax = value_at_risk.plot(legend=False)
xl = ax.set_xlim(value_at_risk.index[0], value_at_risk.index[-1])
rets_2022 = log_returns["2022":].copy()
rets_2022.name = "Log Return"
c = []
for idx in value_at_risk.index:
    if rets_2022[idx] > -value_at_risk.loc[idx, "5%"]:
        c.append("#000000")
    elif rets_2022[idx] < -value_at_risk.loc[idx, "1%"]:
        c.append("#BB0000")
    else:
        c.append("#BB00BB")
c = np.array(c, dtype="object")
labels = {
    "#BB0000": "1% Exceedence",
    "#BB00BB": "5% Exceedence",
    "#000000": "No Exceedence",
}
markers = {"#BB0000": "x", "#BB00BB": "s", "#000000": "o"}
for color in np.unique(c):
    sel = c == color
    ax.scatter(
        rets_2022.index[sel],
        -rets_2022.loc[sel],
        marker=markers[color],
        c=c[sel],
        label=labels[color],
    )
ax.set_title("Parametric VaR")
leg = ax.legend(frameon=False, ncol=3)

De volta ao topo