Updating the Volume Curve Intraday: Does Adaptive Forecasting Actually Help?
Em TWAP, VWAP e POV, executamos todos os três agendadores frente a frente em 90 dias de repetição BTCUSDT L2 e chegamos a uma conclusão que foi deliberadamente deixada como uma ferida aberta: na criptografia, a curva de volume é o elo mais fraco do pipeline, não o fatiamento. Esse artigo enviou a versão simples de propósito - um com base na mediana, curva do dia da semana x hora do dia, reajuste semanalmente, mantida estática durante o dia de negociação. E descobriu que toda a vantagem do VWAP sobre o TWAP é a qualidade da previsão: condicionada ao erro da curva de volume realizado, o VWAP supera o TWAP em cerca de 4 bps no tercil de dias com melhor previsão, e a diferença se transforma em ruído no pior tercil.
Esse resultado implica um acompanhamento específico e falsificável. Se o VWAP só vencer nos dias em que a curva estiver correta, então um previsor que se corrija à medida que o dia se desenrola deverá converter alguns dos dias do tercil ruim em bons. Ou não deveria - e a versão interessante deste artigo é aquela em que isso não acontece, porque o tercil ruim na criptografia são os dias em cascata e os dias de notícias, e esses são exatamente os dias em que as primeiras duas horas de volume observado são menos informativas sobre as próximas duas.
Este artigo implementa o atualizador intradiário, executa-o em um equipamento idêntico e relata o delta IS versus a curva estática – com a distribuição e o número do quartil final, não apenas a média.
O que está sendo testado

A curva estática é uma anterior: um vetor fixo de frações de volume esperadas por balde, estimadas off-line. A versão adaptativa trata isso como um pré-atualização. Depois os períodos decorridos e você observou os volumes reais , você tem duas informações novas que a curva estática descarta:
- Uma estimativa de nível. Se o anterior disser baldes deveria ter carregado fração do dia e eles carregaram unidades, o total implícito do dia inteiro é . Este é um sinal de hoje é um dia pesado / hoje é um dia morto e está disponível no primeiro balde.
- Uma correção de forma. Se a forma realizada dos intervalos decorridos se desviar sistematicamente da forma anterior, os intervalos restantes também poderão desviar-se - mas apenas se os erros da curva de volume intradiária forem autocorrelacionados dentro do dia, o que é em si uma questão empírica e não uma suposição que podemos fazer gratuitamente.
A implementação abaixo usa (1) totalmente e (2) nada: ela renormaliza a cauda anterior intocada no total atualizado. Essa é a versão conservadora e é o primeiro experimento correto, porque se a atualização de nível puro já captura a maior parte do delta disponível, então a maquinaria de forma é uma complexidade injustificada.
import numpy as np
from typing import Optional
class AdaptiveVolumePredictor:
"""
Bayesian-style adaptive volume profile predictor.
Combines a prior (the offline day-of-week x time-of-day curve)
with volume observed so far today to produce an updated forecast
for the remaining buckets.
"""
def __init__(self, historical_profiles: np.ndarray):
"""
Args:
historical_profiles: shape (n_days, n_buckets), each row sums to 1.0.
Use the median-based, day-of-week-conditioned curve from the
TWAP/VWAP/POV article -- a pooled mean curve is misspecified
and will make the adaptive version look better than it is by
giving it a weaker baseline to beat.
"""
self.prior_profile = np.median(historical_profiles, axis=0)
self.prior_profile /= self.prior_profile.sum()
self.prior_iqr = np.subtract(*np.percentile(historical_profiles, [75, 25], axis=0))
self.n_buckets = len(self.prior_profile)
def predict(
self,
observed_volumes: np.ndarray,
current_bucket: int,
total_volume_estimate: Optional[float] = None,
) -> np.ndarray:
"""
Predict absolute volume for every bucket: realized values for elapsed
buckets, forecasts for the remainder.
Args:
observed_volumes: actual volumes in buckets 0..current_bucket-1
current_bucket: index of the current bucket (0-based)
total_volume_estimate: external ADV estimate (optional prior on level)
"""
profile = np.zeros(self.n_buckets)
if current_bucket == 0:
base = total_volume_estimate if total_volume_estimate else 1.0
return self.prior_profile * base
profile[:current_bucket] = observed_volumes[:current_bucket]
observed_total = observed_volumes[:current_bucket].sum()
expected_fraction_so_far = self.prior_profile[:current_bucket].sum()
if expected_fraction_so_far > 0.01:
implied_total = observed_total / expected_fraction_so_far
else:
implied_total = observed_total * self.n_buckets
if total_volume_estimate:
w_obs = expected_fraction_so_far
implied_total = w_obs * implied_total + (1 - w_obs) * total_volume_estimate
remaining_prior = self.prior_profile[current_bucket:]
remaining_sum = remaining_prior.sum()
if remaining_sum > 0:
remaining_volume = max(0.0, implied_total - observed_total)
profile[current_bucket:] = remaining_prior / remaining_sum * remaining_volume
return profile
Dois detalhes nesse código conduzem o experimento. O anterior é a curva mediana condicionada ao dia da semana, não uma média agrupada - para saber por que isso é importante em um mercado onde uma cascata de liquidação pode ser 15% do volume de um dia em dez minutos, consulte a seção de curva de volume do artigo VWAP. E a atualização do nível é reduzida em direção a uma estimativa ADV externa com peso igual à fração anterior decorrida, porque no primeiro intervalo implied_total é uma observação dividida por um número próximo de zero. Um atualizador não reduzido faz seu pior trabalho exatamente quando ainda tem mais dias para arruinar.
Arnês

Idêntico à execução TWAP/VWAP/POV, portanto os números são comparáveis linha por linha:
- Instrumento/dados: BTCUSDT perpétuo, 90 dias de replay L2 (20 níveis principais, 100 ms) mais a fita de negociações. UTC por toda parte; carimbos de data/hora de financiamento sinalizados.
- Pedidos principais: 500, horizonte h, tamanho 0,75% do ADV final de 30 dias, lado da compra, preço de decisão = médio no início. Os mesmos horários de início aleatórios da execução publicada.
- Braços: (A) VWAP na curva estática de reajuste semanal — a linha de base publicada; (B) VWAP no mesmo anterior com atualização intradiária; (C) TWAP como piso.
- Métricas: IS em bps de preço de decisão, taxas incluídas, versus chegada — relatado como média, mediana, desvio padrão, percentil 95 e IS do quartil final de cada pai. A derrapagem do VWAP é registrada apenas como um diagnóstico, nunca como um placar; a seção de benchmark do artigo VWAP mostra um caso resolvido em que o deslizamento do VWAP e o IS de chegada classificam dois algoritmos em ordens opostas. A decomposição completa do SI, incluindo o termo custo de oportunidade, segue déficit de implementação e TCA.
Resultados
Ajuda onde é necessário?
A média do título é o número menos interessante aqui. O resultado publicado estabeleceu que a lacuna VWAP-TWAP é monótona no erro da curva de volume realizada, portanto o braço adaptativo deve ser pontuado da mesma maneira: agrupar os 90 dias em tercis por distância entre a previsão estática e os volumes de bucket realizados e, em seguida, relate o delta IS adaptativo menos estático dentro de cada tercil.
Os dois resultados podem ser publicados e significam coisas opostas:
- Delta concentrada no tercil bom. O atualizador está refinando dias que já eram fáceis. O efeito líquido na distribuição de custos é cosmético; a cauda – que é o que um pai orientado por alfa no horizonte rígido realmente paga – permanece inalterada. Isso diria que o atualizador intradiário não é a solução para o elo mais fraco, e a correção de forma e as rotas de ativos cruzados são o próximo passo.
- Delta concentrado no tercil ruim. O atualizador está fazendo o trabalho para o qual foi construído: capturando a cascata e os dias de notícias onde a curva estática está mais errada. Este é o resultado que justificaria o estado adicionado no loop de execução.
Um resultado negativo é o esperado e vale a pena reportá-lo claramente. O mecanismo que dificulta as curvas de volume criptográfico – uma cascata é uma quebra de regime, não uma mudança de nível – é precisamente o mecanismo que derrota um previsor de atualização de nível: no momento em que os intervalos decorridos lhe disserem que hoje é pesado, a parte pesada pode ter acabado. Veja o negativo honesto para saber por que este blog os publica.
Inclinação do livro: acrescenta alguma coisa?

Um recurso do conjunto de recursos de rascunho não é abordado em nenhum outro lugar deste blog: inclinação do livro, a rapidez com que a profundidade cumulativa se acumula à medida que você se afasta do toque. Ajustar por cima níveis; grande significa que a profundidade está concentrada no toque, pequeno significa que está espalhado pelo livro.
def book_slope(prices: np.ndarray, volumes: np.ndarray, mid: float) -> float:
"""Slope of cumulative depth vs. distance from mid. One side only."""
distances = np.abs(prices - mid)
return float(np.polyfit(distances, np.cumsum(volumes), 1)[0])
A única versão desta afirmação que vale a pena fazer é a medida: será que adicionar book_slope ao conjunto de recursos existente mover a previsão de volume, ou o IS resultante, além de uma linha de base AR/EWMA? O artigo sobre modelagem de spread define o padrão - habilidade de relatório acima de uma linha de base trivial com o horizonte declarado, porque essas séries são dominadas pela persistência e um título R² mede principalmente a autocorrelação.
O que este artigo deliberadamente não deriva

Tudo abaixo já está no blog com mais detalhes, e reexplicá-lo aqui apenas criaria uma segunda versão mais fraca:
- Medição de liquidez. Estimador de Roll (com a correção de raiz assinada e a armadilha preço-unidades-vs-retornos) e lambda de Kyle: modelagem de propagação com aprendizado de máquina. O lambda de Kyle também é calibrado em Binance aggTrades reais como o coeficiente de impacto permanente em Almgren-Chriss. Custo de varredura padrão: modelos de derrapagem e custo.
- Recursos do livro de pedidos. O meio ponderado (que não é o micropreço de Stoikov — aquele é ajustado por martingale), desequilíbrio do livro de vários níveis, OFI e a taxonomia completa do recurso LOB: DeepLOB e modelagem de spread.
- Padrões intradiários. O formato em U do patrimônio é o modelo errado para um mercado sem fechamento; a estrutura criptográfica de sessão/financiamento/semanal que a substitui, mais a grade de dia da semana x hora do dia, está no artigo VWAP. A codificação cíclica da hora do dia está na tabela de recursos do artigo de divulgação.
- Eventos programados. Deribit 08:00 UTC expira, macro dos EUA às 12:30/14:00 UTC, liquidações CME - trate-os como manequins em vez de deixá-los poluir a curva de linha de base; o calendário criptográfico concreto está no artigo VWAP. O atualizador adaptativo acima não é um manipulador de eventos e não deve ser solicitado que o seja.
- Modelos. Aumento de gradiente com CV purgado e embargado (um simples
TimeSeriesSplitvazamentos no alvo sobreposto da janela direta) está em modelagem de propagação; a família CNN-LSTM, o tensor de entrada de 40 recursos/10 níveis, LOBFrame e a discussão sobre crise de replicação estão em DeepLOB. Observe em particular que o eixo do nível não deve ser recolhido antes da camada recorrente. - A decisão da ordem infantil. Passivo versus agressivo é um ponto de equilíbrio calculado , não um limite de propagação codificado: táticas de execução de ordem infantil. A segmentação pela taxa de participação é endógena – seus próprios preenchimentos estão impressos na fita – e a correção está no artigo VWAP.
- Fragmentação do local. Roteamento inteligente de pedidos em criptografia, com o scorecard TCA por local em déficit de implementação.
- Latência de produção. seção de produção do DeepLOB; observe que o artigo divulgado já qualifica declarações de tempo de inferência - um LightGBM de 2.000 rodadas prevê em dezenas de microssegundos do Python, um dígito apenas com um preditor compilado.
A dinâmica adversária merece um parágrafo em vez de uma seção. A profundidade exibida é parcialmente performática, e a mecânica de detecção – taxa de cancelamento, velocidade de construção da parede, comportamento conforme o preço se aproxima, camadas – é coberta com um método concreto baseado em PIQ em posição da fila e análise da parede. O único delta que este artigo poderia adicionar é tratá-los como entradas do previsor: proporção de cancelamento para negociação, tempo médio de descanso no toque e a fração de profundidade que é cancelada dentro de 100 ms após o aparecimento, alimentada no modelo de volume junto com o sinal de intervalo decorrido. Se eles acrescentam habilidade ao conjunto de recursos existente é uma medida aberta, não uma afirmação.
Conclusão

A afirmação em teste é restrita e o blog já estabeleceu as condições para falsificá-la: o artigo VWAP estabeleceu que a vantagem do VWAP é inteiramente de qualidade de previsão e que a previsão falha nos dias que custam mais. Um atualizador intradiário corrige isso ou não, e a resposta é um número no tercil ruim de um replay de 500 pais.
O que este artigo não fará é anexar um número de bps a um sistema de produção sem um replay por trás dele. Alegações do tipo "previsão de liquidez bem ajustada economiza 2–5 bps, a diferença entre um Sharpe de 1,5 e 2,0" são exatamente o gênero que Sharpe deflacionado e testes múltiplos existe para desmantelar: sem fontes, sem condicionamento e nunca acompanhado pela dispersão. O número que importa aqui é o IS do quartil final no pior tercil de dias, e é medido ou não é relatado.
Authors
Trading-systems engineer
Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.