σμ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 11 · Sistemas de produção e modelos de ponta›Tópico 11.4·~1 hEspecialista

Execução TWAP

Posição no roteiroMódulo 11 de 11 · Tópico 4 de 13
11.4 Execução TWAP
—Nota do lab— / 100XP total—Sequência—

Por que não enviar tudo de uma vez

Compre 200.000 ações com uma única ordem a mercado e você vai devorar o livro de ofertas: as primeiras ações executam no melhor ask, as seguintes a um preço pior, e assim por diante, e todos que veem você comprar sobem seus preços. Esse impacto de mercado é um custo real, muitas vezes maior que a corretagem. Um algoritmo de execução corta a ordem em ordens filhas menores enviadas ao longo do tempo para que cada uma seja absorvida com menos impacto. O mais simples é o TWAP, o algoritmo de preço médio ponderado pelo tempo: divide a quantidade em partes iguais e envia uma em cada um dos instantes igualmente espaçados entre um início e um fim.

# Splitting 10 shares into 3 child orders: whole shares, earlier pieces take the extra
def twap_schedule(total, slices):
    size, extra = divmod(total, slices)
    return [size + (1 if index < extra else 0) for index in range(slices)]

print(twap_schedule(10, 3))                          # [4, 3, 3]
print(twap_schedule(200_000, 8))                     # [25000, 25000, 25000, 25000, 25000, 25000, 25000, 25000]
print(sum(twap_schedule(10_001, 7)))                 # 10001   nothing is lost to rounding

O cronograma: quanto e quando

Um cronograma TWAP tem duas partes. Os tamanhos dividem o total em n partes de ações inteiras que diferem no máximo em uma ação e somam exatamente a ordem: divmod(total, n) dá o tamanho base e quantas partes recebem uma ação extra. Os horários são n horas de início igualmente espaçadas entre o início e o fim: start + i * (end - start) / n. Uma ordem de um dia inteiro de 200.000 ações em 40 partes são 5.000 ações a cada dez minutos, enviadas por um agendador como o do tópico anterior. As implementações reais randomizam um pouco tamanhos e horários, pois um padrão perfeitamente regular é fácil de notar e de explorar por outros.

# When each slice starts: a trading day from 09:30 to 16:00 in 13 half-hour slices (seconds since midnight)
def slice_times(start, end, slices):
    step = (end - start) / slices
    return [start + index * step for index in range(slices)]

times = slice_times(9.5 * 3600, 16 * 3600, 13)
print(times[0], times[1] - times[0])                 # 34200.0 1800.0   09:30 and a slice every 30 minutes
print(times[-1] / 3600)                              # 15.5             the last slice starts at 15:30, the end (16:00) is not a start time

Medindo: preço médio de execução e slippage

Depois que as partes são executadas, o preço médio de execução é a média dos preços ponderada pelas quantidades, sum(price * quantity) / sum(quantity): uma execução grande pesa mais que uma pequena, então uma média simples dos preços estaria errada. Para julgar o resultado compare-o com o preço de chegada, o preço de mercado no momento da decisão. A diferença é o slippage, expresso em pontos-base (1 pb é 0,01 %): numa compra (médio - chegada) / chegada * 10.000, numa venda o sinal oposto, de modo que um número positivo é sempre um custo. É o núcleo do implementation shortfall, a forma padrão de avaliar uma execução.

# Average fill price (quantity-weighted) and slippage against the arrival price, in basis points
def average_fill_price(fills):
    return sum(price * quantity for price, quantity in fills) / sum(quantity for _, quantity in fills)

def slippage_bps(avg_price, arrival_price, side):
    sign = 1 if side == "buy" else -1
    return sign * (avg_price - arrival_price) / arrival_price * 10000

fills = [(100.0, 400), (100.2, 300), (100.4, 300)]
average = average_fill_price(fills)
print(round(average, 2), sum(price for price, _ in fills) / 3)      # 100.18 100.2   the plain mean of the prices is not the answer
print(round(slippage_bps(average, 100.0, "buy"), 2))                # 18.0   a buy that averaged 100.18 against an arrival of 100.00 cost 18 bp
print(round(slippage_bps(average, 100.0, "sell"), 2))               # -18.0  the same prices would have been a gain for a seller
# A toy run: the price drifts up while we buy 10 slices; the slippage is what the drift cost us
prices = [100.00, 100.03, 100.05, 100.04, 100.08, 100.10, 100.09, 100.12, 100.15, 100.14]     # price at each slice time
pieces = [100] * 10                                                                         # TWAP: equal child orders

arrival = prices[0]
fills = list(zip(prices, pieces))
average = sum(p * q for p, q in fills) / sum(pieces)
print(round(average, 4))                             # 100.08
print(round((average - arrival) / arrival * 10000, 1))      # 8.0   bp of slippage for buying into a rising market
O que é previsível é explorávelO TWAP ignora o mercado: negocia a mesma quantidade em momentos calmos e movimentados, e sua pegada regular pode ser reconhecida e antecipada. É uma base sensata quando você não tem opinião sobre o volume e quer simplicidade. As melhorias são o próximo tema: seguir a curva de volume do dia (VWAP), limitar sua fatia do volume de cada intervalo, randomizar tamanhos e horários, e parar ou desacelerar quando o preço foge de você. Compare sempre o slippage do algoritmo com uma referência simples nos mesmos dias antes de confiar.
  • Ordens grandes movem o preço; um algoritmo de execução envia ordens filhas menores ao longo do tempo. O TWAP envia partes iguais em horários igualmente espaçados.
  • Tamanhos: divmod(total, n) com as ações extras nas primeiras partes; horários: start + i * (end - start) / n.
  • Avalie uma execução pelo preço médio ponderado por quantidades contra o preço de chegada, em pontos-base; um número positivo é um custo.

A seguir: execução VWAP, seguir o volume do dia em vez do relógio.

Lab: o que é avaliado

  • Dimensionar cada parte com twap_schedule25 pts
  • Espaçar as partes no tempo com slice_times25 pts
  • Calcular a média das execuções com average_fill_price25 pts
  • Precificar o custo com slippage_bps25 pts
Explorador · lab-133-1
▾ lab-133-1
…
bash · no navegador
learner@quantcraft:~/lab-133-1$
Python ainda não carregadoPythonLn 1, Col 1Spaces: 4UTF-8

Redefinir este tópico?

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