Strasmore Research
Deep Dives · Matt ConnorBy Matt Connor ·

Trade Markout: entenda a qualidade da execução

Entenda o que é trade markout, como funciona o sinal e veja uma curva real de 1 segundo a 5 minutos para avaliar adverse selection na execução.

Uma trade markout é a variação do preço médio ao longo de um horizonte fixo após uma execução, medida a partir do momento em que essa execução foi registrada. Um resultado positivo significa que o mercado se moveu a seu favor depois da operação. Um resultado negativo significa que se moveu contra você, o que os desks chamam de adverse selection. O horizonte escolhido, de um segundo ou cinco minutos, determina qual pergunta o número está respondendo.

O que é uma trade markout?

Comece pelo preço médio: o ponto intermediário entre a melhor oferta de compra e a melhor oferta de venda, o midpoint de o NBBO. A markout usa esse preço médio em um horizonte escolhido após a execução, subtrai um preço de referência e atribui sinal ao resultado conforme o lado da operação.

**markout no horizonte h = lado * (preço médio em t+h - preço de referência)**, em que lado é mais um se você comprou e menos um se você vendeu.

A convenção de sinal é a principal fonte de confusão. Uma compra seguida de queda do preço médio tem markout negativo: você comprou, o preço caiu e quem vendeu para você obteve o melhor resultado nessa operação. Isso é adverse selection expresso em um número. Uma venda seguida de queda do preço médio tem markout positivo, pois o sinal muda conforme o lado. Toda execução tem dois lados, e a markout de um lado é a do outro com o sinal invertido.

Os três preços de referência

O preço de referência subtraído determina o que a markout mede.

  • O preço de execução. A markout passa a representar dinheiro: quanto a posição vale em t+h em comparação com o que você pagou. O spread pago ou recebido fica incluído nesse cálculo.
  • O preço médio no momento da execução. Isso retira o spread do cálculo e isola o movimento do mercado depois da operação. É a leitura mais limpa de adverse selection.
  • A cotação do lado em que você negociou. Medir em relação à melhor oferta que você tomou ou à melhor oferta que disponibilizou mostra como a execução se compara ao preço efetivamente disponível.

A análise da qualidade de execução usa principalmente o segundo preço para adverse selection e o primeiro para lucro e perda. Ambos aparecem no primeiro painel abaixo, sobre o mesmo conjunto de execuções.

A curva de markout e o significado do seu formato

Calcule a mesma estatística em vários horizontes e você terá uma curva. O formato dela revela mais do que qualquer número isolado.

  • Uma curva que cai rapidamente no primeiro segundo e permanece baixa descreve fluxo sendo antecipado: o preço se move contra a execução quase imediatamente.
  • Uma curva que continua caindo por minutos descreve fluxo que carregava informação efetiva sobre a direção do preço.
  • Uma curva estável perto de zero descreve fluxo benigno. Cinco minutos depois, o preço médio está próximo do nível observado na execução.
  • Uma curva que começa negativa e volta em direção a zero é o formato procurado por um market maker passivo que recebe rebates. A queda inicial é o spread mais o impacto imediato, e a recuperação representa o retorno do mercado.

A escolha do horizonte é uma decisão sobre o que está sendo medido. Abaixo de um segundo, a markout reflete principalmente latência e posição na fila. Ao estendê-la para um minuto, ela passa a captar a informação de curto prazo contida no fluxo. Depois de cinco minutos, o movimento normal do mercado começa a dominar o efeito da própria execução.

Uma curva de markout real, execução por execução

O painel abaixo considera todos os prints de INTC durante a sessão regular de 10 de junho de 2026, classifica cada um como iniciado por compra ou por venda em relação à última cotação do segundo anterior ao print e calcula a média da markout com sinal em 5 horizontes. Duas séries usam as mesmas execuções: uma medida a partir do preço médio na execução e outra a partir do preço de execução.

QueryCurva de markout da INTC, 10 de junho de 2026, medida a partir de duas bases de referência
O SQL exato por trás de cada número
WITH
    mid_by_second AS
    (
        SELECT
            dateDiff('second', toDateTime('2026-06-10 13:30:00', 'UTC'), sip_timestamp) AS sec,
            argMax((toFloat64(bid_price) + toFloat64(ask_price)) / 2, sip_timestamp)    AS mid
        FROM global_markets.cache_stocks_quotes
        WHERE ticker = 'INTC'
          AND sip_timestamp >= toDateTime('2026-06-10 13:30:00', 'UTC')
          AND sip_timestamp <  toDateTime('2026-06-10 20:00:00', 'UTC')
          AND bid_price > 0
          AND ask_price > bid_price
        GROUP BY sec
    ),
    signed_fills AS
    (
        SELECT
            t.sec        AS sec,
            t.fill_price AS fill_price,
            q.mid        AS ref_mid,
            if(t.fill_price > q.mid, 1, -1) AS side
        FROM
        (
            SELECT
                dateDiff('second', toDateTime('2026-06-10 13:30:00', 'UTC'), sip_timestamp) AS sec,
                sec - 1          AS ref_sec,
                toFloat64(price) AS fill_price
            FROM global_markets.stocks_trades
            WHERE ticker = 'INTC'
              AND sip_timestamp >= toDateTime('2026-06-10 13:30:01', 'UTC')
              AND sip_timestamp <  toDateTime('2026-06-10 19:55:00', 'UTC')
              AND price > 0
              AND size > 0
        ) AS t
        INNER JOIN mid_by_second AS q ON q.sec = t.ref_sec
        WHERE t.fill_price != q.mid
    )
SELECT
    multiIf(f.horizon_s < 60,
            concat(toString(f.horizon_s), ' sec'),
            concat(toString(intDiv(f.horizon_s, 60)), ' min'))              AS horizon,
    round(avg(f.side * (fut.mid - f.ref_mid) / f.ref_mid) * 10000, 3)       AS mid_basis_bps,
    round(avg(f.side * (fut.mid - f.fill_price) / f.fill_price) * 10000, 3) AS fill_basis_bps,
    count()                                                                 AS fill_count
FROM
(
    SELECT
        sec,
        fill_price,
        ref_mid,
        side,
        horizon_s,
        sec + horizon_s AS future_sec
    FROM signed_fills
    ARRAY JOIN [1, 5, 15, 60, 300] AS horizon_s
) AS f
INNER JOIN mid_by_second AS fut ON fut.sec = f.future_sec
GROUP BY f.horizon_s
ORDER BY f.horizon_s
Run this yourself

Entre 900593 execuções classificadas, a série baseada no preço médio registra 3.068 pontos-base em 1 sec e 2.977 pontos-base em 5 min. Um ponto-base corresponde a um centésimo de 1% do preço. Assim, uma execução isolada gera pouco efeito, mas um milhão de ações movimenta dinheiro relevante.

A série baseada no preço de execução começa em -0.488 pontos-base. A distância entre as duas séries no horizonte mais curto é o half spread efetivo: a distância entre o print e o preço médio. Um taker paga esse valor na entrada, e um maker o recebe. Tudo depois do primeiro horizonte representa o movimento do mercado.

O tamanho da execução e o formato da curva

A adverse selection não se distribui igualmente entre as execuções. Dividir a mesma sessão pelo tamanho dos prints coloca pequenas execuções e blocos de mil ações ou mais nos mesmos eixos.

QueryA mesma curva, dividida pelo tamanho do print: execuções pequenas versus blocos
O SQL exato por trás de cada número
WITH
    mid_by_second AS
    (
        SELECT
            dateDiff('second', toDateTime('2026-06-10 13:30:00', 'UTC'), sip_timestamp) AS sec,
            argMax((toFloat64(bid_price) + toFloat64(ask_price)) / 2, sip_timestamp)    AS mid
        FROM global_markets.cache_stocks_quotes
        WHERE ticker = 'INTC'
          AND sip_timestamp >= toDateTime('2026-06-10 13:30:00', 'UTC')
          AND sip_timestamp <  toDateTime('2026-06-10 20:00:00', 'UTC')
          AND bid_price > 0
          AND ask_price > bid_price
        GROUP BY sec
    ),
    signed_fills AS
    (
        SELECT
            t.sec        AS sec,
            t.fill_size  AS fill_size,
            q.mid        AS ref_mid,
            if(t.fill_price > q.mid, 1, -1) AS side
        FROM
        (
            SELECT
                dateDiff('second', toDateTime('2026-06-10 13:30:00', 'UTC'), sip_timestamp) AS sec,
                sec - 1          AS ref_sec,
                toFloat64(price) AS fill_price,
                size             AS fill_size
            FROM global_markets.stocks_trades
            WHERE ticker = 'INTC'
              AND sip_timestamp >= toDateTime('2026-06-10 13:30:01', 'UTC')
              AND sip_timestamp <  toDateTime('2026-06-10 19:55:00', 'UTC')
              AND price > 0
              AND size > 0
        ) AS t
        INNER JOIN mid_by_second AS q ON q.sec = t.ref_sec
        WHERE t.fill_price != q.mid
    )
SELECT
    multiIf(f.horizon_s < 60,
            concat(toString(f.horizon_s), ' sec'),
            concat(toString(intDiv(f.horizon_s, 60)), ' min'))                                   AS horizon,
    round(avgIf(f.side * (fut.mid - f.ref_mid) / f.ref_mid, f.fill_size < 1000) * 10000, 3)       AS small_fill_bps,
    round(avgIf(f.side * (fut.mid - f.ref_mid) / f.ref_mid, f.fill_size >= 1000) * 10000, 3)      AS block_fill_bps,
    countIf(f.fill_size >= 1000)                                                                 AS block_fill_count
FROM
(
    SELECT
        sec,
        fill_size,
        ref_mid,
        side,
        horizon_s,
        sec + horizon_s AS future_sec
    FROM signed_fills
    ARRAY JOIN [1, 5, 15, 60, 300] AS horizon_s
) AS f
INNER JOIN mid_by_second AS fut ON fut.sec = f.future_sec
GROUP BY f.horizon_s
HAVING countIf(f.fill_size < 1000) > 0
   AND countIf(f.fill_size >= 1000) > 0
ORDER BY f.horizon_s
Run this yourself

No horizonte de 5 min, prints com menos de mil ações registram, em média, 2.983 pontos-base, enquanto os 11588 prints de mil ações ou mais registram, em média, 2.495. Duas cotações que executem o mesmo volume total contra esses dois grupos não terminam o dia no mesmo nível.

Como as markouts se transformam nos números de spread dos relatórios de execução

A markout é o termo que falta na decomposição padrão do spread. O spread efetivo é o que um taker realmente pagou: duas vezes a distância com sinal entre o preço médio e o print. Divida esse valor em duas partes. Uma é o spread realizado, o que o maker conserva depois que o mercado se move. A outra é a adverse selection, que corresponde à markout baseada no preço médio multiplicada por dois. A identidade é exata: spread efetivo = spread realizado + adverse selection.

QuerySpread efetivo dividido em spread realizado e seleção adversa, por meia hora
O SQL exato por trás de cada número
WITH
    mid_by_second AS
    (
        SELECT
            dateDiff('second', toDateTime('2026-06-10 13:30:00', 'UTC'), sip_timestamp) AS sec,
            argMax((toFloat64(bid_price) + toFloat64(ask_price)) / 2, sip_timestamp)    AS mid
        FROM global_markets.cache_stocks_quotes
        WHERE ticker = 'INTC'
          AND sip_timestamp >= toDateTime('2026-06-10 13:30:00', 'UTC')
          AND sip_timestamp <  toDateTime('2026-06-10 20:00:00', 'UTC')
          AND bid_price > 0
          AND ask_price > bid_price
        GROUP BY sec
    ),
    signed_fills AS
    (
        SELECT
            t.sec + 60   AS future_sec,
            t.et_time    AS et_time,
            t.fill_price AS fill_price,
            q.mid        AS ref_mid,
            if(t.fill_price > q.mid, 1, -1) AS side
        FROM
        (
            SELECT
                dateDiff('second', toDateTime('2026-06-10 13:30:00', 'UTC'), sip_timestamp) AS sec,
                sec - 1          AS ref_sec,
                toFloat64(price) AS fill_price,
                formatDateTime(toStartOfInterval(toTimeZone(sip_timestamp, 'America/New_York'), toIntervalMinute(30)), '%H:%i') AS et_time
            FROM global_markets.stocks_trades
            WHERE ticker = 'INTC'
              AND sip_timestamp >= toDateTime('2026-06-10 13:30:01', 'UTC')
              AND sip_timestamp <  toDateTime('2026-06-10 19:55:00', 'UTC')
              AND price > 0
              AND size > 0
        ) AS t
        INNER JOIN mid_by_second AS q ON q.sec = t.ref_sec
        WHERE t.fill_price != q.mid
    )
SELECT
    f.et_time                                                                  AS et_time,
    round(avg(2 * f.side * (f.fill_price - f.ref_mid) / f.ref_mid) * 10000, 3) AS effective_spread_bps,
    round(avg(2 * f.side * (f.fill_price - fut.mid) / f.ref_mid) * 10000, 3)   AS realized_spread_bps,
    round(avg(2 * f.side * (fut.mid - f.ref_mid) / f.ref_mid) * 10000, 3)      AS adverse_selection_bps,
    count()                                                                    AS fill_count
FROM signed_fills AS f
INNER JOIN mid_by_second AS fut ON fut.sec = f.future_sec
GROUP BY f.et_time
ORDER BY f.et_time
Run this yourself

Na meia hora iniciada em 09:30, horário do leste dos Estados Unidos, o spread efetivo registra, em média, 10.651 pontos-base. Desse total, 8.313 corresponde ao componente de adverse selection no horizonte de sessenta segundos, e 2.338 é o que o maker retém. O painel cobre 13 intervalos de meia hora.

Esses componentes são os valores resumidos por venue nos relatórios de execução Rule 605 e 606, e formam a base matemática das alegações de price improvement associadas à regra de sub-penny e ao price improvement. Um rebate é um crédito fixo por ação. A adverse selection é um custo variável por ação nas execuções que uma cotação efetivamente recebe. Comparar um com o outro ao longo de uma curva medida, em vez de usar apenas uma tabela de taxas, é a verificação por trás de taxas e rebates maker-taker, em conjunto com a mecânica explicada em por que market makers perdem dinheiro.

Como esses números foram calculados

Todos os painéis usam cotações e prints de INTC da sessão regular de 10 de junho de 2026, das 09:30 às 16:00, horário do leste dos Estados Unidos. As cotações são consolidadas em um preço médio por segundo: o último registrado dentro daquele segundo. Um print é classificado como iniciado por compra quando ocorre acima do preço médio do segundo anterior e como iniciado por venda quando ocorre abaixo dele. Essa é a regra padrão baseada na cotação. Prints exatamente no preço médio são excluídos, em vez de classificados por estimativa; por isso, execuções no midpoint ficam fora da amostra. Usar o preço médio do segundo anterior como referência impede o uso de informação futura. Os horizontes são contados em segundos inteiros a partir do segundo do print, e uma execução entra em um horizonte somente quando existe uma cotação no segundo-alvo.

Perguntas frequentes

O que é uma markout em trading?

Uma markout é a variação, com sinal, do preço médio ao longo de um horizonte fixo após uma execução. Um resultado positivo significa que o mercado se moveu na direção da sua operação depois que ela foi executada. Um resultado negativo significa que se moveu na direção contrária, que é a definição de adverse selection.

Uma markout negativa sempre indica uma execução ruim?

Não. Uma markout negativa em um segundo, em uma ordem que cruza o spread, reflete principalmente o spread pago para executar imediatamente. O mais importante é saber se a curva continua caindo em horizontes mais longos ou se estabiliza.

Qual é a diferença entre markout e slippage?

Slippage compara uma execução com um preço de decisão ou de chegada. Por isso, avalia o percurso completo de uma ordem. A markout compara a execução com o preço médio em um horizonte posterior. Assim, avalia o que aconteceu depois. Uma mede a ordem principal; a outra mede a execução individual.

Qual horizonte uma markout deve usar?

Depende da finalidade da execução. Horizontes inferiores a um segundo avaliam execução sensível à latência, enquanto um minuto é o padrão mais comum para medir adverse selection em ativos líquidos. Informar o horizonte ao lado do número é o que permite comparar duas markouts.

Qual é a relação entre markout e spread efetivo?

O spread efetivo se divide em spread realizado mais um componente de adverse selection. Esse componente corresponde à markout baseada no preço médio multiplicada por dois. Quando o horizonte muda, a divisão entre os dois componentes também muda. Por isso, uma estatística de spread publicada não é completa sem o horizonte correspondente.


Todos os painéis vêm acompanhados do SQL que os produziu. Abra um deles, substitua o ticker ou a data, e a mesma curva de markout será reconstruída do zero no terminal Strasmore.