import yfinance as yf
import pandas as pd
from scipy import stats
import numpy as np
import pingouin
def merge_time_series(df_1, df_2, how='outer'):
df = df_1.merge(df_2, how=how, left_index=True, right_index=True)
return df
def normalize(df):
df = df.dropna()
return (df / df.iloc[0]) * 100
def download_yahoo_data(tickers, normalize_quotes=True,
start='1970-01-01', end='2030-12-31'):
quotes=pd.DataFrame()
for ticker in tickers:
df = yf.download(ticker, start=start, end=end, progress=False)
df = df[['Adj Close']]
df.columns=[ticker]
quotes = merge_time_series(quotes, df)
quotes = quotes.ffill()
if normalize_quotes:
quotes = normalize(quotes)
return quotes
def compute_z_critical_region(alpha):
return stats.norm.ppf(alpha), stats.norm.ppf(1-alpha)
def compute_t_critical_region(alpha, df):
return stats.t.ppf(alpha,df), stats.t.ppf(1-alpha,df)
Capitulo 6 - Testes de Hipótese#
Quando conseguimos formular uma idea ou opinião de uma forma precisa sobre o valor de quantidades a idea torna-se estatísticamente testável e passa a ser uma hipótese.
Como analista podemos querer explorar questões como:
A rentabilidade média de um fundo é realmente diferente da reantabilidade média do seuu benchmark? (para provarmos se o gestor é bom ou bateu o benchmark por sorte);
A volatilidade dos retornos de uma acção alterou-se depois da acção ter sido adicionada ao S&P 500?
O aumento de market makers em impacto no bid-ask spread de uma acção?
Uma hipótese é definida como uma declaração sobre uma ou mais populações.
Passos num teste de hipóteses:
Declararmos a nossa hipótese;
Identificar o teste estatístico apropriado;
Especificar o nível de significância;
Declarar as regras para a nossa decisão;
Obter os dados relevante e calcular os respectivos testes estatísticos;
Tomar a decisão económica ou de investimento;
Passo 1: Definição da nossa hipótese#
Parece algo trivial mas como vamos ver mais à frente, nos casos práticos, nem sempre o é.
Devemos definir uma hipótese nula \(h_0\) e uma hipótese alternativa \(h_a\).
Hipótese Nula: A hipótese nula é a hipótese a ser testada. É a hipótese que assumimos verdadeira a menos que os nossos testes no levem a ter provas suficientes para a rejeitar.
Hipótese alternativa: A hipótese alternativa é a nossa ideia, aquilo que temos “esperança” em provar. É uma alteração do Status Quo.
Formulação da nossa da nossa hipótese: Podemos formular a nossa hipótese de 3 formas diferentes:
1.
\(h_0\): \(\theta\) = \(\theta_0\)
\(h_a\): \(\theta \neq \theta_0\)
(versão “diferente de”)
2.
\(h_0\): \(\theta \leq \theta_0\)
\(h_a\): \(\theta > \theta_0\)
(versão “maior que”)
3
\(h_0\): \(\theta \geq \theta_0\)
\(h_a\): \(\theta < \theta_0\)
(versão “menor que”)
A primeira hipótese é um teste de hipótese de duas caudas ou lados (two sided or two tailed);
A formulação 2 e 3 são testes de uma cauda (one sided ou one-tailed).
Uma analista suspeita que, no ano mais recente, os retornos excessivos das ações foram inferiores a 5%. Ela quer então testar se os retornos em excesso são, de facto, inferiores a 5%. Designando a média da população como μ, quais hipóteses são mais apropriadas para sua análise?
a) \(H_0: µ\) = 5 e \(H_a\): µ ≠ 5
b) \(H_0: µ\) = 5 e \(H_a\): µ < 5
c) \(H_0: µ\) < 5 e \(H_a\): µ > 5
Show code cell source
# Resposta correcta é a b) uma vez que a analista pretende testar se os retornos em excesso são menores.
Passo 2: Identificar a estatística de teste relevante#
Um ponto fulcral da nossa decisão será o valor da estatística de teste. A estatística de teste vai depender do que queremos testar.
Quadro resumo:
Não se preocupem muito entretanto que quando entrarmos nos exemplos vamos perceber.
def compute_t_single_mean(sample_mean, expected_mean, std, n):
'''
sample_mean, expected_mean, std, n
'''
return ((sample_mean-expected_mean)/(std/np.sqrt(n)))
Passo 3: Especificar um nível de significância#
Ao fazermos um teste de hipóteses temos de definir um nível de significância. Os níveis mais comuns são 10%, 5% ou 1%.
Diferentes níveis de significâcia influenciam a possibilidade de rejeitarmos ou não a hipotese nula. Infelizmente não podemos também aumentar indiscriminadamente o nível de confiança pois estamos a aumentar a probabilidade de não rejeitarmos a hipótese nula falsa e eventualmente podemos estar a cair naquilo que se chama de erro II (falha em rejeitar uma hipótese nula falsa).
Conceitos
Nível de significância (\(α\))
Nível de confiança (\(1 - α\))
Tipos de erro#
Rejeitamos uma hipótese nula falsa. Decisão correcta;
Rejeitamos uma hipótese nula verdadeira. Erro tipo I;
Não rejeitamos uma hipótese nula falsa. Erro tipo II;
Não rejeitamos uma hipótese nula verdadeira. Decisão correcta.
Questões escolha multipla para testar o conhecimento de erros tipo I e tipo II na Khan Academy
Passo 4: Declarar as regras para a nossa decisão#
Tendo em consideração a distribuição, e depois de decidirmos a o nível de significância podemos analisar os nossos pontos de rejeição. A nossa estatística de teste (que vamos calcular no passo 5) vai ou estar dentro de uma região de aceitação onde não podemos rejeitar a hipótese nula ou vai estar nas regiões de rejeição, onde rejeitamos a hipótese nula.
Passo 5: Obter os dados relevante e calcular os respectivos testes estatísticos#
O quinto passo no teste de hipóteses é obter os dados e calcular a estatística de teste.
A qualidade de nossas conclusões depende não apenas da adequação do modelo estatístico, mas também a qualidade dos dados que usamos na realização do teste. Primeiro, precisamos garantir que o procedimento de amostragem não inclua enviesamentos. Em segundo lugar, precisamos limpar os dados, verificando imprecisões e outros erros de medição nos dados. Uma vez assegurado que a amostra é imparcial e preciso, as informações da amostra são usadas para calcular a estatística de teste apropriada.
EXEMPLO 3 : Usando um Intervalo de Confiança em Testes de Hipóteses
Ao fazermos o nosso teste de hipóteses fizemos definimos hipóteses que dão origem a um teste de duas caudas. Optamos por um nível de significância de 5%.
Com base na nossa amostra calculamos um Z = 1.05. A decisão mais apropriada será:
a) Rejeitar a hipótese nula.
b) Aceita a hipótese nula.
c) Falha em rejeitar a hipótese nula.
Passo 5: Obter os dados relevante e calcular os respectivos testes estatísticos#
O quinto passo no teste de hipóteses é obter os dados e calcular a estatística de teste.
A qualidade de nossas conclusões depende não apenas da adequação do modelo estatístico, mas também a qualidade dos dados que usamos na realização do teste. Primeiro, precisamos garantir que o procedimento de amostragem não inclua enviesamentos. Em segundo lugar, precisamos limpar os dados, verificando imprecisões e outros erros de medição nos dados. Uma vez assegurado que a amostra é imparcial e preciso, as informações da amostra são usadas para calcular a estatística de teste apropriada.
EXEMPLO 3 : Usando um Intervalo de Confiança em Testes de Hipóteses
Ao fazermos o nosso teste de hipóteses fizemos definimos hipóteses que dão origem a um teste de duas caudas. Optamos por um nível de significância de 5%.
Com base na nossa amostra calculamos um Z = 1.05. A decisão mais apropriada será:
a) Rejeitar a hipótese nula.
b) Aceita a hipótese nula.
c) Falha em rejeitar a hipótese nula.
Passo 6: Tomar uma decisão#
Exercício 6.2#
Um analista pretende testar se os retornos ajustados ao risco de uma estratégia de trading (que são positivos) são estatísticamente positivos. Na amostra a média do excesso nos retornos ajustados ao risco face ao mercado é de 0.7% ao mês. A amostra é de 20 anos com dados mensais.
A estatística T calculada é de 2.5. O nível de significância é de 1%.
1) Quais são as hipóteses nula e alternativa?
Show code cell source
# A hipótese nula é o sistema de trading não ter retornos em excesso face ao mercado portanto H_0 menor ou igual que 0% e
# a hipótese alternativa, o que o trader tem "esperança" em provar, é a hipótese complementar, ou seja h_a > 0%
2) Ao nível de significância de 1% quais são os pontos críticos?
A analisar se com uma ou duas caudas.
compute_t_critical_region(0.01, df=239)
(-2.342051322860583, 2.3420513228605824)
3) Rejeitamos a hipótese nula?
A analisar para que lado é a cauda.
Show code cell source
# Uma vez que a estística T calculada está fora da região de aceitação rejeitamos a hipótese nula
p-value#
O p-value é o menor nível de significância no qual a hipótese nula pode ser rejeitada.
Quanto mais pequeno o p-value mais forte é a evidência contra a hipótese nula e mais a favor da hipótese alternativa. Em muitos testes temos como output do python um p-value de 0, o que representa que rejeitamos a hipótese nula. Por outro lado algumas vezes também temos um p-value maior que 0.1 o que nos leva a não rejeitar a hipótese nula para os casos mais comuns (\(\alpha\) de 1%, 5% ou 10%).
Quando fizermos os testes directamente em python vamo-nos guiar pelo p-value, que é logo dado como output.
Uma analista pretende testar as hipóteses \(H_0\): \(σ^2\) = 0,01 versus \(H_a\): \(σ_2\) ≠ 0,01. Usando software, ela determina que o valor-p para a estatística de teste é 0,03 ou 3%. Quais das seguintes afirmações são corretas?
a) Rejeite a hipótese nula nos níveis de significância de 1% e 5%.
b) Rejeitar a hipótese nula ao nível de 5%, mas não ao nível de 1% de significado.
c) Deixar de rejeitar a hipótese nula nos níveis de 1% e 5% de significado.
Show code cell source
# b) está correto. A rejeição da hipótese nula requer que o p-value seja menor que
# o nível de significância. Com base neste requisito, a hipótese é rejeitada a um
# nível de significância de 5%, mas não no nível de significância de 1%.
Teste de uma só média#
Exemplo (pág. 382)#
Características de risco e retorno de um fundo de ações
Suponhamos que estamos a analisar o Sendar Equity Fund, um fundo de crescimento midcap que existe há 24 meses. Nesse período, alcançou uma média de retorno mensal de 1,50%, com desvio padrão amostral dos retornos mensais de 3,60%. Dado o seu nível de risco de mercado e de acordo com um modelo CAPM de esperava-se que o fundo obtivesse um retorno mensal médio de 1,10% durante esse período de tempo. Assumindo que os retornos são normalmente distribuídos, os resultados reais são consistente com um retorno mensal esperado de 1,10%?
Passo 1: Formular a hipótese nula
\(H_0\): μ = 1.1%
\(H_a\): μ ≠ 1.1%
Passo 2: Identificar a estatística de teste apropriada
Teste de uma média só. Ver função matemática no quadro acima. Para nós é a função compute_t_single_mean()
Passo 3: Especificar o nível de significância
\(\alpha\) = 5%
Passo 4: Declarar as regras para a nossa decisão
Ver quais os valores críticos:
compute_t_critical_region(0.025, 23)
(-2.068657610419041, 2.0686576104190406)
Porquê 23? A distribuição T funciona, como já vimos com graus de liberdade (df or degrees of freedom). Os graus de liberdade são iguais a n menos os números de parâmetros a serem avaliados (neste caso 1 porque é sobre um só média).
Se a estatística T que vamos calcular no ponto 5 estiver entre -2.069 e 2.69 não rejeitamos a hipótese nula. Se estiver fora desse range rejeitamos a hipótese nula.
Passo 5: Calcular a estatística de teste
Função python da fórmula matemática acima para testes t de uma só média#
compute_t_single_mean(sample_mean=1.5, expected_mean=1.1, std=3.6, n=24)
0.5443310539518171
Alternativa \(z\)#
Para amostras grandes, os profissionais às vezes usam um teste z em vez de um teste t para testes relativos a uma média. A justificação para usar o teste z neste contexto são duas.
Primeiro, em amostras grandes, a média amostral deve seguir a distribuição normal pelo menos aproximadamente, como já dissemos, cumprindo o pressuposto de normalidade do z-teste.
Em segundo lugar, a diferença entre os pontos de rejeição para o teste t e o teste z torna-se muito pequeno quando o tamanho da amostra é grande.
Num número muito limitado de casos, podemos conhecer a variância da população; Nesses casos o uso a estatística z é teoricamente correta
Exemplo (pág.384)#
Iremos só fazer a questão 2 uma vez que a questão 1 é igual à anterior.
Suponhamos que queremos testar se o retorno diário no ACE High Yield Total Index é diferente de zero. Obtendo uma amostra de 1.304 retornos diários, encontramos um retorno médio diário de 0.0157%, com desvio padrão de 0.3157%.
2. Usando a estatística de teste z-distribuída como uma aproximação, teste se o retorno médio diário é diferente de zero ao nível de 5% de significância.
Passo 1: Formular a hipótese nula
\(H_0\): μ = 0%
\(H_a\): μ ≠ 0%
(duas caudas)
Passo 2: Identificar a estatística de teste apropriada
Teste de uma média só. Iremos usar a alternativa z.
Para nós é a função compute_z_single_mean()
Passo 3: Especificar o nível de significância
\(\alpha\) = 5%
(duas caudas)
Passo 4: Declarar as regras para a nossa decisão
Ver quais os valores críticos:
compute_z_critical_region(0.025)
(-1.9599639845400545, 1.959963984540054)
A fórmula compute_z_critical_region() já não tem qualquer necessidade de DF. Apenas usa o \(\alpha\) (uma cauda) ou o \(\alpha/2\) (duas caudas).
Passo 5: Calcular a estatística de teste
def compute_z_single_mean(sample_mean, expected_mean, std, n):
'''
sample_mean, expected_mean, std, n
'''
return ((sample_mean-expected_mean)/(std/np.sqrt(n)))
compute_z_single_mean(sample_mean=0.0157, expected_mean=0, std=0.3157, n=1304)
1.7958243923896375
Passo 6: Tomar uma decisão
Exemplo (pág.386/387)#
Continuando o exemplo dos retornos no ACE High Yield Total Return Index, suponhamos que queremos testar se esses retornos são diferentes para dois períodos de tempo diferentes, Período 1 e Período 2.
Passo 1: Formular a hipótese nula
\(H_0\): μ_periodo_1 = μ_periodo_2
\(H_a\): μ_periodo_1 \(\neq\) μ_periodo_2
(duas caudas)
Passo 2: Identificar a estatística de teste apropriada
Teste de diferenças em médias.
Para nós é a função compute_t_diference_in_means() mas um pouco mais complicado pois inclui o cálculo de variância médio:
ou com a nossa fórmula compute_std_p_from_t_diference_in_means()
Passo 3: Especificar o nível de significância
\(\alpha\) = 5%
(duas caudas)
Passo 4: Declarar as regras para a nossa decisão
Ver quais os valores críticos:
compute_t_critical_region(0.025, 445+859)
(-1.96178487198399, 1.9617848719839897)
Passo 5: Calcular a estatística de teste
def compute_t_diference_in_means(mean_1, mean_2, std_p, n_1, n_2):
a = (mean_1-mean_2) - 0
b = np.sqrt((std_p/n_1) + (std_p/n_2))
return a/b
def compute_std_p_from_t_diference_in_means(n_1, n_2, std_1, std_2):
a = (n_1-1) * std_1
b= (n_2-1) * std_2
c = (n_1 + n_2 - 2)
return (a + b) / c
A Função compute_std_p_from_t_diference_in_means está a combinar o desvio padrão de duas amostras quando se supõe que é idêntico, como neste caso ser o mesmo activo. Isso serve para podermos calcular o compute_t_diference_in_means para analisarmos se a média entre as amostras é diferente.
compute_std_p_from_t_diference_in_means(n_1=445, n_2=859, std_1=0.31580, std_2=0.38760)
0.36311520737327185
compute_t_diference_in_means(mean_1=0.01775, mean_2=0.01134, std_p=0.363, n_1=445, n_2=859)
0.18215559221262695
Passo 6: Tomar uma decisão
Exemplo (pág.389)#
Ao analisar os retornos trimestrais para um período de três anos para dois carteiras geridas activamente especializadas em metais preciosos. As duas carteiras são semelhantes em risco e tinham custos de gestão quase idênticos.
Um grande investimento empresa de serviços avaliou o Portfólio B como sendo melhor que Portfólio A.
Ao investigar desempenho relativo das carteiras, suponhamos que queremos testar a hipótese de que o retorno trimestral médio da Carteira A é igual ao retorno trimestral médio na Carteira B durante o período de três anos. Uma vez que as duas carteiras compartilham essencialmente o mesmo conjunto de fatores de risco, seus retornos não são independentes, então teste de comparações em par é apropriado. Vamos usar um nível de significância de 10%.
Passo 1: Formular a hipótese nula
\(H_0\): μ = 0%
\(H_a\): μ ≠ 0%
(duas caudas)
Passo 2: Identificar a estatística de teste apropriada
Para nós é a função compute_t_mean_of_differences()
Passo 3: Especificar o nível de significância
\(\alpha\) = 5%
(duas caudas)
Passo 4: Declarar as regras para a nossa decisão
Ver quais os valores críticos:
compute_t_critical_region(0.05, 11)
(-1.7958848187036696, 1.7958848187036691)
Porquê 11? A distribuição \(t\) funciona, como já vimos, com graus de liberdade (df or degrees of freedom). Os graus de liberdade são iguais a n menos os números de parâmetros a serem avaliados (neste caso 1 porque é uma só diferença de médias).
DICA: Onde se podem enganar.
Teste de duas caudas ou uma só cauda tem influência no \(\alpha\) a colocar na fórmula.
df nunca é igual a n, ou é n-1 ou n-2 etc etc
def compute_t_mean_of_differences(mean_dif, std_dif):
return (mean_dif-0) / (std_dif/np.sqrt(12))
compute_t_mean_of_differences(mean_dif=4.40083, std_dif=5.47434)
2.7847963975468613
Passo 6: Tomar uma decisão
S&P 500 vs MSCI World - Médias das diferenças (Exemplo real com output python)#
tickers = ['VT', 'SPY']
nomes = tickers
ret = download_yahoo_data(tickers, nomes).resample('BM').last().pct_change().dropna()
# ret = ret['2020-04':]
ret = ret['2013-08':'2018-07']
from pingouin import ttest
ttest(ret['VT'], ret['SPY'], alternative='two-sided', paired=True)
/tmp/ipykernel_158773/1900226107.py:3: FutureWarning: 'BM' is deprecated and will be removed in a future version, please use 'BME' instead.
ret = download_yahoo_data(tickers, nomes).resample('BM').last().pct_change().dropna()
T | dof | alternative | p-val | CI95% | cohen-d | BF10 | power | |
---|---|---|---|---|---|---|---|---|
T-test | -2.076727 | 59 | two-sided | 0.042191 | [-0.01, -0.0] | 0.093692 | 1.04 | 0.110133 |
Outros testes#
Teste de uma variância - Quando queremos por exemplo ver se a variância de um determinado fundo foi abaixo do valor pretendido (exemplo 12 pag. 394)
Testes de diferenças entre variâncias - Quando queremos por exemplo ver se a variância de uma acção se alterou depois de entrada de regulação (exemplo 13 pag. 398)
Testes de correlação - Em muitos contextos de investimentos, queremos avaliar a força da relação linear entre duas variáveis; ou seja, queremos avaliar a correlação entre elas. Um teste de significância de um coeficiente de correlação permite-nos avaliar se o relação entre duas variáveis aleatórias é o resultado do acaso.