¿Es real el rendimiento medio?
Un backtest muestra un rendimiento medio de +0,14 % al día. ¿Es buena la estrategia o tuvo suerte? Los rendimientos son ruidosos, así que toda muestra tiene una media, e incluso una estrategia de cara o cruz la tiene positiva la mitad de las veces. Una prueba de hipótesis hace una pregunta precisa: si la media verdadera fuera mu0 (normalmente 0), ¿cuán sorprendente sería una media muestral tan alejada de mu0? La respuesta es un valor p. Un valor p pequeño dice que los datos serían muy improbables bajo la hipótesis de que «no pasa nada».
El estadístico t mide la media en unidades de su propia incertidumbre. La incertidumbre de una media es el error estándar s / sqrt(n): disminuye al crecer la muestra, por eso más datos hacen más convincente la misma media. Reescalar todos los rendimientos cambia por igual la media y el error estándar, así que t no cambia. Como regla práctica, un |t| superior a 2 difícilmente es suerte.
import math
import numpy as np
returns = np.array([0.004, -0.002, 0.001, 0.003, -0.004, 0.002, 0.006, -0.001, 0.005, 0.002, 0.003, -0.002])
n = len(returns)
mean = returns.mean()
std_error = returns.std(ddof=1) / math.sqrt(n) # the uncertainty of the mean
t = mean / std_error # testing against mu0 = 0
print(round(mean, 5), round(std_error, 6)) # 0.00142 0.000892 the mean is only 1.6 standard errors from 0
print(round(t, 3)) # 1.589De t al valor p
Bajo la hipótesis nula, t se comporta como una normal estándar cuando la muestra es grande, así que el valor p bilateral es la probabilidad de caer a más de |t| de 0 en cualquier dirección: erfc(|t| / sqrt(2)). Con t = 1,59 es el 11 %: un resultado así de bueno ocurre una vez de cada nueve por azar, así que no podemos afirmar una ventaja real. El umbral habitual es el 5 % (|t| = 1,96). Para muestras pequeñas la referencia correcta es la t de Student, de colas más gruesas, por lo que el valor p normal es algo demasiado pequeño; con menos de 30 puntos usa una tabla t de verdad.
p_value = math.erfc(abs(t) / math.sqrt(2))
print(round(p_value, 4)) # 0.1121 an outcome this good happens by chance about 1 time in 9
print(round(math.erfc(1.96 / math.sqrt(2)), 4)) # 0.05 |t| = 1.96 is the usual 5% limit
# Testing against another value: is the mean different from 0.2% a day?
t_other = (mean - 0.002) / std_error
print(round(t_other, 3), round(math.erfc(abs(t_other) / math.sqrt(2)), 3)) # -0.654 0.513Intervalos de confianza y muestras pareadas
Un intervalo de confianza dice más que una prueba sí/no: media -/+ 1,96 * error estándar es un rango que contiene la media verdadera alrededor del 95 % de las veces. Si el intervalo contiene 0, la media no es significativa al 5 %. Nuestro intervalo, de -0,03 % a +0,32 % diario, cruza el cero y es ancho comparado con la media. Para comparar dos estrategias medidas en los mismos días, contrasta sus diferencias diarias con 0. El emparejamiento elimina el ruido que ambas comparten (los días buenos y malos del mercado), así que detecta una ventaja mucho más nítidamente que dos pruebas separadas.
low, high = mean - 1.96 * std_error, mean + 1.96 * std_error
print(round(low, 5), round(high, 5)) # -0.00033 0.00316 the interval contains 0: not significant at 5%
# Paired: the same six days for two strategies
a = np.array([0.004, -0.002, 0.001, 0.003, -0.004, 0.002])
b = np.array([0.002, -0.003, 0.000, 0.001, -0.002, 0.0])
d = a - b
t_paired = d.mean() / (d.std(ddof=1) / math.sqrt(len(d)))
print(round(d.mean(), 5), round(t_paired, 3)) # 0.001 1.581 a daily edge of 0.1%, but only 6 days# Same mean and spread, four times the data: t doubles and the p-value collapses
spread = returns.std(ddof=1)
for n in (12, 48):
t_n = mean / (spread / math.sqrt(n))
print(n, round(t_n, 3), round(math.erfc(abs(t_n) / math.sqrt(2)), 4))
# 12 1.589 0.1121
# 48 3.178 0.0015t = (mean - mu0) / (s / sqrt(n)): la media en unidades de su error estándars / sqrt(n); más datos, |t| mayor.- El valor p bilateral es
erfc(|t| / sqrt(2))para muestras grandes; |t| > 1,96 significa p < 5 %; un intervalomean -/+ 1,96 * seque contiene 0 significa no significativo. - Compara estrategias en los mismos días con el estadístico t de las diferencias diarias; cuidado con probar muchas variantes.
A continuación: la regresión lineal (MCO), para ajustar una recta que explique un rendimiento con otro.
Lab: qué se califica
- Medir la media en unidades de su ruido con
t_statistic25 pts - Convertir t en un valor p con
two_sided_p25 pts - Acotar la media verdadera con
confidence_interval25 pts - Comparar dos estrategias día a día con
paired_t_statistic25 pts