σμ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 6 · Backtesting e custos de trading›Tópico 6.6·~55 minAvançado

Execuções de ordens realistas

Posição no roteiroMódulo 6 de 11 · Tópico 6 de 6
6.6 Execuções de ordens realistas
—Nota do lab— / 100XP total—Sequência—

Uma execução não é uma certeza

Um backtest ingênuo supõe que uma ordem de qualquer tamanho é executada ao preço dos dados. Ordens reais enfrentam três perguntas. Qual a profundidade do livro: uma ordem a mercado leva primeiro a melhor oferta, depois a seguinte, então uma ordem grande paga um preço médio pior. O mercado alcançou meu limite: uma ordem limitada obtém o preço pedido ou melhor, mas só se a negociação chegar a ele. E quanto posso levar: uma ordem grande só pode ser uma fração do volume da barra, então é executada em partes ao longo do tempo.

def fill_market_order(book, quantity):
    remaining = quantity
    cost = 0.0
    filled = 0
    for price, size in book:                      # cheapest offer first
        if remaining <= 0:
            break
        take = min(size, remaining)
        cost += take * price
        filled += take
        remaining -= take
    if filled == 0:
        return 0.0, 0
    return cost / filled, filled

book = [(50.00, 300), (50.02, 500), (50.05, 1000)]
print(fill_market_order(book, 200))        # (50.0, 200)           inside the first level
print(fill_market_order(book, 600))        # (50.01, 600)          300 at 50.00 and 300 at 50.02
print(fill_market_order(book, 5000))       # (50.0333, 1800)      the whole book; 3,200 shares stay unfilled
# The average price and the slippage against the best offer grow with the size
def average_price(book, quantity):
    remaining, cost, filled = quantity, 0.0, 0
    for price, size in book:
        take = min(size, remaining)
        cost += take * price
        filled += take
        remaining -= take
    return cost / filled

book = [(50.00, 300), (50.02, 500), (50.05, 1000)]
for quantity in (100, 300, 800, 1800):
    avg = average_price(book, quantity)
    print(quantity, round(avg, 4), round((avg - 50.00) / 50.00 * 10000, 2), "bps above the best offer")

Ordens limitadas e gaps

Com dados de barras (abertura, mínima, máxima) não se vê o caminho dentro da barra, só seus extremos. Uma compra limitada em L é executada se a mínima da barra chegou a L ou menos. O preço é L, a menos que a barra tenha aberto abaixo de L: então o mercado pulou seu limite e você é executado na abertura, que é melhor. Uma venda limitada é a imagem espelhada. Uma ordem limitada apenas tocada pode não ser executada na realidade, porque a fila à sua frente foi atendida primeiro, então este é o limite otimista.

def limit_fill(side, limit, bar_open, bar_low, bar_high):
    if side == "buy" and bar_low <= limit:
        return min(bar_open, limit)             # a gap below the limit fills at the better open
    if side == "sell" and bar_high >= limit:
        return max(bar_open, limit)
    return None

print(limit_fill("buy", 49.95, 50.10, 49.90, 50.20))   # 49.95   traded down through the limit
print(limit_fill("buy", 49.95, 49.90, 49.80, 50.20))   # 49.9    opened below: filled at the open
print(limit_fill("buy", 49.95, 50.10, 50.00, 50.20))   # None    never reached
print(limit_fill("sell", 50.15, 50.00, 49.90, 50.20))  # 50.15

Trabalhar uma ordem grande

Muitas mesas de execução usam um limite de participação: não levar mais que, digamos, 10% do volume. Numa barra com 40.000 ações negociadas são 4.000, arredondado para baixo. Uma ordem de 5.000 ações leva então duas barras, não uma. Percorrer as barras é um laço que carrega a quantidade restante: cada barra executa min(remaining, int(volume * participation)), e as barras depois do fim da ordem não executam nada.

def partial_fill(quantity, bar_volume, participation):
    return min(quantity, int(bar_volume * participation))

def fill_over_bars(quantity, volumes, participation):
    remaining = quantity
    fills = []
    for volume in volumes:
        filled = partial_fill(remaining, volume, participation)
        fills.append(filled)
        remaining -= filled
    return fills

fills = fill_over_bars(5000, [40000, 30000, 80000, 100000], 0.1)
print(fills, sum(fills))                      # [4000, 1000, 0, 0] 5000
Modelos de execução definem sua honestidadeCada simplificação aqui pende para o mesmo lado: supor que uma ordem limitada é executada ao ser tocada, que você nunca move o mercado, que o volume está lá. Quanto mais um resultado depende das execuções, mais deve ser testado com regras pessimistas (executar só se o preço atravessar o limite, um teto de participação menor) e verificar se a vantagem sobrevive.
  • Uma ordem a mercado percorre o livro nível a nível; o preço médio é ponderado por volume e piora com o tamanho, e um livro raso executa só parte.
  • Uma ordem limitada é executada se a barra alcança o limite, na abertura se a barra o pulou; um simples toque pode não ser executado na realidade.
  • Os tetos de participação limitam cada barra a int(volume * participation); um laço carrega a quantidade restante entre as barras.

A seguir: CAPM e beta, medir quanto de um retorno vem do mercado.

Lab: o que é avaliado

  • Percorrer o livro com fill_market_order25 pts
  • Decidir se o limite é atingido com limit_fill25 pts
  • Respeitar o volume com partial_fill25 pts
  • Trabalhar a ordem ao longo do tempo com fill_over_bars25 pts
Explorador · lab-92-1
▾ lab-92-1
…
bash · no navegador
learner@quantcraft:~/lab-92-1$
Python ainda não carregadoPythonLn 1, Col 1Spaces: 4UTF-8

Redefinir este tópico?

Tudo em lab-92-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