¿Predice algo la señal?
Antes de construir una estrategia sobre una señal, pregunta si apunta en la dirección correcta. Cada día una señal da una puntuación a cada acción y un día después cada acción tiene un rendimiento. El coeficiente de información (IC) es la correlación, entre acciones, de la puntuación y el rendimiento posterior. Va de -1 a 1; cero significa sin poder predictivo. Las señales reales son débiles: un IC de 0,02 a 0,05 ya es útil, porque se repite en muchas acciones y muchos días.
import numpy as np
signal = np.array([0.3, -1.2, 0.8, 0.1, 1.5]) # today's score for five stocks
returns = np.array([0.01, -0.02, 0.005, -0.004, 0.03]) # their returns over the next day
s = signal - signal.mean()
r = returns - returns.mean()
ic = np.sum(s * r) / np.sqrt(np.sum(s ** 2) * np.sum(r ** 2)) # the Pearson correlation
print(round(float(ic), 4))
print(round(float(np.corrcoef(signal, returns)[0, 1]), 4)) # the same numberIC de rangos: robusto a valores extremos
Una correlación de Pearson está dominada por los valores extremos: una acción con una puntuación enorme o un salto del 40 % en un día puede inclinarla. El IC de rangos sustituye cada array por el rango de sus valores (1 para el menor) y correlaciona los rangos. Solo pregunta si las acciones que la señal pone más arriba terminan más arriba, sea cual sea el tamaño de los números, así que no cambia con ninguna transformación creciente de la señal. Es la versión que citan la mayoría de equipos cuantitativos, y es la correlación de Spearman.
# The rank of each value: argsort gives the order, assigning 1..n through it gives the ranks
import numpy as np
values = np.array([30.0, 10.0, 20.0, 5.0])
order = np.argsort(values) # positions from smallest to largest: [3 1 2 0]
ranks = np.empty(len(values))
ranks[order] = np.arange(1, len(values) + 1)
print(order, ranks) # [3 1 2 0] [4. 2. 3. 1.]# Ranks via argsort, and a rank IC that shrugs off an extreme value
import numpy as np
def ranks(values):
order = np.argsort(values)
out = np.empty(len(values))
out[order] = np.arange(1, len(values) + 1)
return out
def ic(a, b):
a, b = a - a.mean(), b - b.mean()
return float(np.sum(a * b) / np.sqrt(np.sum(a ** 2) * np.sum(b ** 2)))
signal = np.array([0.3, -1.2, 0.8, 0.1, 1.5])
returns = np.array([0.01, -0.02, 0.005, -0.004, 0.03])
print(ranks(signal)) # [3. 1. 4. 2. 5.]
print(round(ic(signal, returns), 4), round(ic(ranks(signal), ranks(returns)), 4))
signal_with_outlier = signal.copy()
signal_with_outlier[4] = 1000.0 # one absurd score
print(round(ic(signal_with_outlier, returns), 4), round(ic(ranks(signal_with_outlier), ranks(returns)), 4))Consistencia en el tiempo: el ratio de información del IC
El IC de un día es ruidoso. Calcúlalo cada día para obtener una serie y mira su media y su regularidad. El ICIR, el IC medio dividido por su desviación típica, premia las señales que aciertan un poco cada día frente a las que aciertan mucho unos pocos días. Es un ratio tipo Sharpe para la propia señal. Una serie diaria de IC con media 0,03 y desviación 0,06 tiene un ICIR de 0,5.
# A daily rank-IC series for a weak signal, and its ICIR
import numpy as np
def ranks(values):
out = np.empty(len(values))
out[np.argsort(values)] = np.arange(1, len(values) + 1)
return out
def ic(a, b):
a, b = a - a.mean(), b - b.mean()
return float(np.sum(a * b) / np.sqrt(np.sum(a ** 2) * np.sum(b ** 2)))
rng = np.random.default_rng(8)
daily_ics = []
for day in range(250):
signal = rng.normal(size=300) # 300 stocks
returns = 0.01 * (0.05 * signal + rng.normal(size=300)) # the signal explains a sliver of the return
daily_ics.append(ic(ranks(signal), ranks(returns)))
daily_ics = np.array(daily_ics)
print(round(float(daily_ics.mean()), 4), round(float(daily_ics.std(ddof=1)), 4))
print(round(float(daily_ics.mean() / daily_ics.std(ddof=1)), 3))- El IC es la correlación entre la señal de hoy en las acciones y sus rendimientos posteriores; 0,02 a 0,05 es útil, por encima de 0,1 es sospechoso.
- El IC de rangos correlaciona rangos (
argsortdos veces): robusto a valores extremos y sin cambio con cualquier transformación creciente de la señal. - ICIR = IC medio / desviación típica del IC durante muchos días: premia la habilidad constante; evalúe siempre fuera de muestra.
A continuación: el VaR histórico, la pérdida que una cartera no debe superar salvo en los peores días.
Lab: qué se califica
- Ordenar los valores con
ranks25 pts - Correlacionar señal y resultado con
ic25 pts - Ignorar los valores extremos con
rank_ic25 pts - Juzgar la consistencia con
icir25 pts