Dois números para uma distribuição
Uma coluna de retornos é difícil de comparar com outra. Dois números resumem a maior parte: a média diz onde os retornos estão centrados e a variância o quanto se espalham em torno desse centro. Para n retornos, a média é sum(x) / n; os desvios x - mean sempre somam zero, então para medir a dispersão eles são primeiro elevados ao quadrado. A variância amostral é a soma dos desvios ao quadrado dividida por n - 1, não n: a média foi estimada com os mesmos dados, o que deixa os desvios um pouco pequenos demais, e dividir por n - 1 corrige isso.
import numpy as np
returns = np.array([0.004, -0.002, 0.001, 0.003, -0.004, 0.002, 0.006, -0.001])
mean = returns.mean()
deviations = returns - mean
print(round(mean, 5)) # 0.00113
print(abs(deviations.sum()) < 1e-12) # True the deviations always add up to zero
variance = (deviations ** 2).sum() / (len(returns) - 1)
print(round(variance, 8), round(returns.var(ddof=1), 8)) # 1.098e-05 1.098e-05 the same as numpy's var(ddof=1)Desvio padrão e volatilidade
Elevar ao quadrado mudou as unidades: uma variância de retornos está em "percentual ao quadrado". Sua raiz quadrada, o desvio padrão, volta à unidade dos retornos e, em finanças, chama-se volatilidade. É a medida de risco mais comum. Um dia típico de uma ação grande se move cerca de 1 a 2%, ou seja, uma volatilidade de 0,01 a 0,02 ao dia. Lê-se em relação à média: com volatilidade de 1,2% ao dia, um dia de -3,6% está a três desvios padrão.
std = np.sqrt(variance)
print(round(std, 6), round(returns.std(ddof=1), 6)) # 0.003314 0.003314 daily volatility of these returns
# How many standard deviations is the worst day from the mean?
print(round((returns.min() - mean) / std, 2)) # -1.55Anualizar e o índice de Sharpe
Os números diários são pequenos e pouco expressivos, então são dados por ano. A média cresce linearmente com o tempo (252 dias úteis por ano: multiplica-se por 252), mas a volatilidade cresce com a raiz quadrada do tempo: multiplica-se por sqrt(252), cerca de 15,9. O motivo é que os movimentos diários aleatórios se cancelam em parte, então a incerteza se acumula mais devagar que a média. O índice de Sharpe divide o retorno médio acima da taxa livre de risco (o retorno excedente) pela volatilidade: recompensa por unidade de risco, anualizada do mesmo modo. Permite comparar uma estratégia calma com uma agitada.
periods = 252
print(round(mean * periods, 4)) # 0.2835 annual mean: 28.35% (a made-up, very lucky sample)
print(round(std * np.sqrt(periods), 4)) # 0.0526 annual volatility: 5.26%
risk_free = 0.0001 # risk-free return of one day
excess = returns - risk_free
sharpe = excess.mean() / np.sqrt(((excess - excess.mean()) ** 2).sum() / (len(excess) - 1)) * np.sqrt(periods)
print(round(sharpe, 3)) # 4.91 absurdly good, because 8 lucky days prove nothing# How precisely do 8 days pin down the mean? The standard error is std / sqrt(n)
standard_error = std / np.sqrt(len(returns))
print(round(float(standard_error), 6)) # 0.001172 larger than the mean itself (0.00113)std / sqrt(n), aqui 0,0012, maior que a própria média (0,0011). Um ótimo índice de Sharpe em poucas semanas diz pouco; quanto mais observações, mais se pode confiar numa média, e os números de risco são muito mais estáveis que os retornos médios.- Média:
x.mean(); variância amostral:((x - mean) ** 2).sum() / (n - 1); a volatilidade é sua raiz quadrada. - Anualize a média com
* periodse a volatilidade com* sqrt(periods): o risco cresce com a raiz quadrada do tempo. - Sharpe = retorno excedente médio / seu desvio padrão *
sqrt(periods): recompensa por unidade de risco; amostra curta a torna pouco confiável.
A seguir: a assimetria e a curtose, as duas estatísticas que descrevem a forma da distribuição além do seu centro e da sua dispersão.
Lab: o que é avaliado
- Medir a dispersão dos retornos com
sample_variance25 pts - Expressar a dispersão na unidade dos retornos com
sample_std25 pts - Anualizar a média e a volatilidade com
annualized_stats25 pts - Avaliar o retorno por unidade de risco com
sharpe_ratio25 pts