σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft AcademyParcours
Ctrl K
AO
+1,2 k apprenants
ConnexionRejoindre ↗
Parcours
AO
+1,2 k apprenants
Connexion
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Parcours Python›Module 7 · Recherche d'alpha et risque›Sujet 7.3·~55 minAvancé

Le coefficient d'information

Position dans le parcoursModule 7 sur 11 · Sujet 3 sur 9
7.3 Le coefficient d'information
—Score du lab— / 100XP total—Série—

Le signal prédit-il quelque chose ?

Avant de bâtir une stratégie sur un signal, demandez s'il pointe dans la bonne direction. Chaque jour, un signal donne un score à chaque action, et un jour plus tard chaque action a un rendement. Le coefficient d'information (IC) est la corrélation, entre actions, du score et du rendement ultérieur. Il va de -1 à 1 ; zéro signifie aucun pouvoir prédictif. Les vrais signaux sont faibles : un IC de 0,02 à 0,05 est déjà utile, car il se répète sur de nombreuses actions et de nombreux jours.

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 number

IC de rang : robuste aux valeurs extrêmes

Une corrélation de Pearson est dominée par les valeurs extrêmes : une action avec un score énorme ou un saut de 40 % en un jour peut la faire basculer. L'IC de rang remplace chaque tableau par le rang de ses valeurs (1 pour la plus petite) et corrèle les rangs. Il demande seulement si les actions que le signal met plus haut finissent plus haut, quelle que soit la taille des nombres, donc il est inchangé par toute transformation croissante du signal. C'est la version que citent la plupart des équipes quantitatives, et c'est la corrélation 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))

La régularité dans le temps : le ratio d'information de l'IC

L'IC d'un jour est bruité. Calculez-le chaque jour pour obtenir une série, et regardez sa moyenne et sa régularité. L'ICIR, l'IC moyen divisé par son écart-type, récompense les signaux justes un peu chaque jour plutôt que très justes quelques jours. C'est un ratio de type Sharpe pour le signal lui-même. Une série quotidienne d'IC de moyenne 0,03 et d'écart-type 0,06 a 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))
Un bon IC est petit, et une valeur élevée est un avertissementLes marchés sont presque efficients, donc un IC supérieur à 0,1 est plus probablement un bug qu'une découverte : cherchez un biais d'anticipation, un signal construit à partir des rendements qu'il prédit, ou une erreur de données. Un vrai IC décroît aussi avec l'horizon, et sa valeur après coûts compte plus qu'avant. Calculez-le toujours sur des données auxquelles le signal n'a pas été ajusté.
  • L'IC est la corrélation entre le signal du jour sur les actions et leurs rendements ultérieurs ; 0,02 à 0,05 est utile, au-dessus de 0,1 est suspect.
  • L'IC de rang corrèle les rangs (argsort deux fois) : robuste aux valeurs extrêmes et inchangé par toute transformation croissante du signal.
  • ICIR = IC moyen / écart-type de l'IC sur de nombreux jours : récompense une compétence régulière ; évaluez toujours hors échantillon.

À suivre : la VaR historique, la perte qu'un portefeuille ne doit pas dépasser sauf les pires jours.

Lab : ce qui est noté

  • Mettre les valeurs en ordre avec ranks25 pts
  • Corréler signal et résultat avec ic25 pts
  • Ignorer les valeurs extrêmes avec rank_ic25 pts
  • Juger la régularité avec icir25 pts
Explorateur · lab-95-1
▾ lab-95-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-95-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

Tout le contenu de lab-95-1 revient aux fichiers de départ et le terminal est vidé. Votre solution actuelle sera perdue : cette action est irréversible.

Sera réinitialisé
  • main.py → code de départ
  • Historique du terminal et sortie des tests
  • Modifications non soumises
Sera conservé
  • Meilleur score du lab
  • Votre XP et votre série
  • Progression du cours et notes

Connectez-vous pour exécuter votre code.

Tous les cours sont gratuits à lire. Créez un compte ou connectez-vous pour exécuter du code, lancer les tests et soumettre ce lab.

  • IDE dans le navigateur avec terminal bash — rien à installer
  • Correction instantanée, XP et votre place dans le parcours
Créer un compteSe connecter
OU
Continuer avec GitHub