Sagt das Signal etwas voraus?
Bevor man eine Strategie auf ein Signal baut, fragt man, ob es in die richtige Richtung zeigt. Jeden Tag gibt ein Signal jeder Aktie einen Score, und einen Tag später hat jede Aktie eine Rendite. Der Informationskoeffizient (IC) ist die Korrelation über die Aktien zwischen Score und späterer Rendite. Er reicht von -1 bis 1; null heißt keine Vorhersagekraft. Echte Signale sind schwach: Ein IC von 0,02 bis 0,05 ist schon nützlich, weil er sich über viele Aktien und viele Tage wiederholt.
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 numberRang-IC: robust gegen Ausreißer
Eine Pearson-Korrelation wird von Extremwerten dominiert: Eine Aktie mit riesigem Score oder einem Tagessprung von 40 % kann sie kippen. Der Rang-IC ersetzt jedes Array durch den Rang seiner Werte (1 für den kleinsten) und korreliert die Ränge. Er fragt nur, ob die vom Signal höher eingestuften Aktien höher landen, egal wie groß die Zahlen sind, und bleibt daher bei jeder wachsenden Transformation des Signals unverändert. Die meisten Quant-Teams nennen diese Variante; es ist die Spearman-Korrelation.
# 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))Beständigkeit über die Zeit: die Information Ratio des IC
Der IC eines Tages ist verrauscht. Berechnen Sie ihn täglich, um eine Reihe zu erhalten, und betrachten Sie Mittelwert und Stetigkeit. Die ICIR, der mittlere IC geteilt durch seine Standardabweichung, belohnt Signale, die jeden Tag ein wenig richtig liegen, gegenüber solchen, die an wenigen Tagen sehr richtig liegen. Sie ist eine Sharpe-ähnliche Kennzahl für das Signal selbst. Eine Tagesreihe von IC-Werten mit Mittel 0,03 und Standardabweichung 0,06 hat eine ICIR von 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))- Der IC ist die Korrelation zwischen dem heutigen Signal über die Aktien und deren späteren Renditen; 0,02 bis 0,05 ist nützlich, über 0,1 verdächtig.
- Der Rang-IC korreliert Ränge (zweimal
argsort): robust gegen Ausreißer und unverändert bei jeder wachsenden Transformation des Signals. - ICIR = mittlerer IC / Standardabweichung des IC über viele Tage: belohnt stetiges Können; immer außerhalb der Stichprobe bewerten.
Als Nächstes: historischer VaR, der Verlust, den ein Portfolio außer an den schlimmsten Tagen nicht überschreiten soll.
Lab: Was bewertet wird
- Mit
ranksdie Werte in eine Reihenfolge bringen25 Pkt. - Mit
icSignal und Ergebnis korrelieren25 Pkt. - Mit
rank_icAusreißer ignorieren25 Pkt. - Mit
icirdie Beständigkeit beurteilen25 Pkt.