σμ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 AcademyRoteiros
Ctrl K
AO
+1,2 mil alunos
EntrarParticipar ↗
Roteiros
AO
+1,2 mil alunos
Entrar
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Roteiro de Python›Módulo 7 · Pesquisa de alfa e risco›Tópico 7.3·~55 minAvançado

O coeficiente de informação

Posição no roteiroMódulo 7 de 11 · Tópico 3 de 9
7.3 O coeficiente de informação
—Nota do lab— / 100XP total—Sequência—

O sinal prevê alguma coisa?

Antes de construir uma estratégia sobre um sinal, pergunte se ele aponta na direção certa. Todo dia um sinal dá uma pontuação a cada ação, e um dia depois cada ação tem um retorno. O coeficiente de informação (IC) é a correlação, entre ações, da pontuação e do retorno posterior. Vai de -1 a 1; zero significa nenhum poder preditivo. Sinais reais são fracos: um IC de 0,02 a 0,05 já é útil, porque se repete em muitas ações e muitos dias.

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 postos: robusto a valores extremos

Uma correlação de Pearson é dominada por valores extremos: uma ação com pontuação enorme ou um salto de 40% em um dia pode virá-la. O IC de postos substitui cada array pelo posto de seus valores (1 para o menor) e correlaciona os postos. Só pergunta se as ações que o sinal coloca mais alto terminam mais alto, seja qual for o tamanho dos números, então não muda com qualquer transformação crescente do sinal. É a versão que a maioria das equipes quantitativas cita, e é a correlação 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))

Consistência no tempo: o índice de informação do IC

O IC de um dia é ruidoso. Calcule-o todo dia para obter uma série e olhe sua média e sua regularidade. O ICIR, o IC médio dividido por seu desvio-padrão, premia sinais que acertam um pouco todo dia em vez de acertar muito em poucos dias. É um índice tipo Sharpe para o próprio sinal. Uma série diária de IC com média 0,03 e desvio-padrão 0,06 tem ICIR 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))
Um bom IC é pequeno, e um grande é um alertaOs mercados são quase eficientes, então um IC acima de 0,1 é mais provavelmente um bug do que uma descoberta: procure viés de antecipação, um sinal construído com os retornos que prevê ou erro de dados. Um IC real também decai com o horizonte, e seu valor após custos importa mais que antes. Calcule-o sempre em dados aos quais o sinal não foi ajustado.
  • O IC é a correlação entre o sinal de hoje nas ações e seus retornos posteriores; 0,02 a 0,05 é útil, acima de 0,1 é suspeito.
  • O IC de postos correlaciona postos (argsort duas vezes): robusto a valores extremos e inalterado por qualquer transformação crescente do sinal.
  • ICIR = IC médio / desvio-padrão do IC em muitos dias: premia a habilidade constante; avalie sempre fora da amostra.

A seguir: o VaR histórico, a perda que uma carteira não deve exceder exceto nos piores dias.

Lab: o que é avaliado

  • Colocar os valores em ordem com ranks25 pts
  • Correlacionar sinal e resultado com ic25 pts
  • Ignorar valores extremos com rank_ic25 pts
  • Avaliar a consistência com icir25 pts
Explorador · lab-95-1
▾ lab-95-1
…
bash · no navegador
learner@quantcraft:~/lab-95-1$
Python ainda não carregadoPythonLn 1, Col 1Spaces: 4UTF-8

Redefinir este tópico?

Tudo em lab-95-1 volta aos arquivos iniciais e o terminal é limpo. Sua solução atual será perdida — isso não pode ser desfeito.

Será redefinido
  • main.py → código inicial
  • Histórico do terminal e saída dos testes
  • Alterações não enviadas
Será mantido
  • Melhor nota do lab
  • Seu XP e sua sequência
  • Progresso da aula e anotações

Entre para executar o seu código.

Todas as aulas são gratuitas para ler. Crie uma conta ou entre para executar código, rodar os testes e enviar este lab.

  • IDE no navegador com terminal bash — nada para instalar
  • Correção instantânea, XP e o seu lugar no roteiro
Criar uma contaEntrar
OU
Continuar com o GitHub