Updating the Volume Curve Intraday: Does Adaptive Forecasting Actually Help?
In TWAP, VWAP e POV abbiamo eseguito tutti e tre gli scheduler testa a testa in 90 giorni di replay di BTCUSDT L2 e abbiamo raggiunto una conclusione che è stata lasciata deliberatamente come una ferita aperta: nelle criptovalute, la curva del volume è l'anello più debole della pipeline, non lo slicing. Quell'articolo ha spedito apposta la versione semplice: a curva basata sulla mediana, giorno della settimana x ora del giorno, aggiornamento settimanale, mantenuta statica durante il giorno di negoziazione. E ha scoperto che l’intero vantaggio di VWAP rispetto a TWAP è la qualità della previsione: condizionato all’errore realizzato nella curva del volume, VWAP batte TWAP di circa 4 bps sul tercile di giorni con la migliore previsione, e il divario crolla nel rumore sul tercile peggiore.
Questo risultato implica un seguito specifico e falsificabile. Se VWAP vince solo nei giorni in cui la curva è andata bene, allora un meteorologo che si corregge man mano che la giornata si svolge dovrebbe convertire alcuni dei giorni cattivi in giorni buoni. Oppure non dovrebbe – e la versione interessante di questo articolo è quella in cui non lo fa, perché il terzo trimestre negativo nelle criptovalute sono i giorni a cascata e i giorni delle notizie, e quelli sono esattamente i giorni in cui le prime due ore di volume osservato sono meno informative sui due successivi.
Questo articolo implementa l'aggiornamento intraday, lo esegue rispetto allo stesso cablaggio e riporta il delta IS rispetto alla curva statica, con la distribuzione e il numero del quartile finale, non solo la media.
Cosa viene testato

La curva statica è a priori: un vettore fisso delle frazioni di volume previste per bucket, stimate offline. La versione adattiva lo considera come un elemento precedente all'aggiornamento. Dopo i bucket sono trascorsi e hai osservato i volumi effettivi , hai due nuove informazioni che la curva statica elimina:
- Una stima del livello. Se il precedente dice secchi avrebbe dovuto portare la frazione del giorno e hanno portato unità, il totale implicito dell'intera giornata è . Questo è un segnale “oggi è un giorno pesante/oggi è un giorno morto” ed è disponibile dal primo bucket.
- Una correzione della forma. Se la forma realizzata dei bucket trascorsi devia sistematicamente dalla forma precedente, anche i restanti bucket potrebbero deviare, ma solo se gli errori della curva di volume intraday sono autocorrelati durante il giorno, che è di per sé una questione empirica e non un'ipotesi che possiamo fare gratuitamente.
L'implementazione seguente utilizza (1) completamente e (2) per niente: rinormalizza la coda precedente intatta sul totale aggiornato. Questa è la versione conservativa, ed è il primo esperimento giusto, perché se il puro aggiornamento del livello cattura già la maggior parte del delta disponibile, allora il meccanismo della forma è di complessità ingiustificata.
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
Due dettagli in quel codice portano all'esperimento. La prima è la curva mediana condizionata al giorno della settimana, non una media aggregata: per capire perché è importante in un mercato in cui una cascata di liquidazione può rappresentare il 15% del volume giornaliero in dieci minuti, consultare la sezione sulla curva del volume dell'articolo VWAP. E l'aggiornamento del livello viene ristretto verso una stima ADV esterna con un peso pari alla frazione precedente trascorsa, perché nel primo bucket implied_total è un'osservazione divisa per un numero vicino allo zero. Un programma di aggiornamento non ridotto fa il suo peggior lavoro esattamente quando ha più giorni da rovinare.
Imbracatura

Identico all'esecuzione TWAP/VWAP/POV, quindi i numeri sono comparabili riga per riga:
- Strumento/dati: BTCUSDT perpetuo, 90 giorni di replay L2 (primi 20 livelli, 100 ms) più il nastro delle transazioni. UTC in tutto; timestamp di finanziamento contrassegnati.
- Ordini principali: 500, orizzonte h, dimensione 0,75% dell'ADV finale di 30 giorni, lato acquisto, prezzo decisionale = metà all'inizio. Stessi orari di inizio casuali della corsa pubblicata.
- Arms: (A) VWAP sulla curva statica di ristrutturazione settimanale: il riferimento pubblicato; (B) VWAP sullo stesso precedente con aggiornamento intraday; (C) TWAP come pavimento.
- Metriche: IS in punti base del prezzo della decisione, commissioni incluse, rispetto all'arrivo - riportato come media, mediana, deviazione standard, 95° percentile e IS del quartile finale di ciascun genitore. Lo slittamento del VWAP viene registrato solo come diagnostica, mai come quadro di valutazione; la sezione benchmark dell'articolo VWAP mostra un caso funzionante in cui lo slittamento e l'arrivo IS del VWAP classificano due algoritmi in ordini opposti. La scomposizione completa dell'IS, incluso il termine costo-opportunità, segue mancanza di implementazione e TCA.
Risultati
Aiuta dove serve?
La media del titolo è il numero meno interessante qui. Il risultato pubblicato ha stabilito che il divario VWAP-TWAP è monotono nell'errore della curva di volume realizzato, quindi il braccio adattivo deve essere valutato allo stesso modo: suddividere i 90 giorni in tercili secondo distanza tra la previsione statica e i volumi dei bucket realizzati, quindi riportare il delta IS adattivo meno statico all'interno di ciascun tercile.
I due risultati sono entrambi pubblicabili e significano cose opposte:
- Delta concentrato nel tercile buono. L'aggiornamento sta perfezionando giornate che erano già facili. L’effetto netto sulla distribuzione dei costi è cosmetico; la coda – che è ciò che effettivamente paga un genitore orientato all’alfa dall’orizzonte difficile – è invariata. Ciò direbbe che l’aggiornamento intraday non è la soluzione per l’anello più debole e che i percorsi di correzione della forma e tra asset sono i prossimi a cui guardare.
- Delta concentrato nel tercile cattivo. L'aggiornamento sta facendo il lavoro per cui è stato creato: catturare la cascata e i giorni delle notizie in cui la curva statica è più sbagliata. Questo è il risultato che giustificherebbe lo stato aggiunto nel ciclo di esecuzione.
Un risultato negativo è quello atteso e merita di essere riportato con chiarezza. Il meccanismo che rende difficili le curve del volume delle criptovalute (una cascata è una rottura del regime, non uno spostamento di livello) è proprio il meccanismo che sconfigge un previsore di aggiornamento del livello: nel momento in cui i periodi trascorsi ti dicono che oggi è pesante, la parte pesante potrebbe essere finita. Vedi the onesto negativo per sapere perché questo blog li pubblica.
Pendenza del libro: aggiunge qualcosa?

Una caratteristica della bozza non è trattata altrove in questo blog: pendenza del libro, la velocità con cui si accumula la profondità cumulativa quando ti allontani dal tocco. Adatto esagerato livelli; grande significa che la profondità è concentrata al tatto, piccola significa che è distribuito in modo sottile in tutto il libro.
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])
L’unica versione di questa affermazione che vale la pena fare è misurata: fa l’aggiunta book_slope all'insieme di funzionalità esistente spostare la previsione del volume, o l'IS risultante, oltre una linea di base AR/EWMA? L'articolo sullo spread modeling stabilisce lo standard: riportare l'abilità sopra una banale linea di base con l'orizzonte dichiarato, perché queste serie sono dominate dalla persistenza e un titolo R² misura principalmente l'autocorrelazione.
Ciò che questo articolo volutamente non ri-deriva

Tutto quello che segue è già sul blog in modo più approfondito e spiegarlo qui creerebbe solo una seconda versione più debole:
- Misurazione della liquidità. Lo stimatore di Roll (con la correzione della radice con segno e la trappola delle unità di prezzo rispetto ai rendimenti) e il lambda di Kyle: spread modeling con machine learning. Il lambda di Kyle è anche calibrato su Binance aggTrades reale come coefficiente di impatto permanente in Almgren-Chriss. Costo walk-the-book: modelli di slippage e di costo.
- Caratteristiche del libro degli ordini. Il valore medio ponderato (che non è il microprezzo di Stoikov, quello è aggiustato per la martingala), lo sbilanciamento del libro multilivello, l'OFI e la tassonomia completa delle funzioni LOB: DeepLOB e spread modeling.
- Modelli intraday. La forma a U delle azioni è il modello sbagliato per un mercato senza chiusura; la struttura della sessione crittografica/finanziamento/settimanale che la sostituisce, più la griglia del giorno della settimana × dell'ora del giorno, si trova nell'articolo VWAP. La codifica ciclica dell'ora del giorno si trova nella tabella delle caratteristiche dell'articolo diffuso.
- Eventi programmati. Scadenze Deribit alle 08:00 UTC, macro USA alle 12:30/14:00 UTC, liquidazioni CME: trattali come manichini anziché lasciare che inquinino la curva di base; il calendario crittografico concreto si trova nell'articolo VWAP. Il programma di aggiornamento adattivo sopra non è un gestore di eventi e non dovrebbe essere richiesto di esserlo.
- Modelli. Potenziamento del gradiente con CV walk-forward eliminato ed embargato (un semplice
TimeSeriesSplitperdite attraverso l'obiettivo della finestra forward sovrapposta) è in spread modeling; la famiglia CNN-LSTM, il tensore di input a 40 funzionalità/10 livelli, LOBFrame e la discussione sulla crisi di replica si trovano in DeepLOB. Si noti in particolare che l'asse del livello non deve essere collassato prima del livello ricorrente. - La decisione dell'ordine del bambino. Passivo contro aggressivo è un pareggio calcolato , non una soglia di diffusione codificata: tattiche di esecuzione degli ordini secondari. Il targeting del tasso di partecipazione è endogeno (i tuoi riempimenti vengono stampati sul nastro) e la correzione è nell'articolo VWAP.
- Frammentazione della sede. Instradamento intelligente degli ordini nelle criptovalute, con la scorecard TCA per sede in mancanza di implementazione.
- Latenza di produzione. Sezione produzione di DeepLOB; si noti che l'articolo diffuso qualifica già le affermazioni sul tempo di inferenza: un LightGBM da 2000 round prevede in decine di microsecondi da Python, solo a una cifra con un predittore compilato.
Le Dinamiche contraddittorie meritano un paragrafo piuttosto che una sezione. La profondità visualizzata è in parte performativa e i meccanismi di rilevamento (tasso di annullamento, velocità di costruzione del muro, comportamento all'avvicinarsi del prezzo, stratificazione) sono trattati con un metodo concreto basato su PIQ in posizione della coda e analisi del muro. L'unico delta che questo articolo potrebbe aggiungere è trattarli come input di previsione: rapporto cancellazione-operazione, tempo di riposo medio al tocco e frazione di profondità che si cancella entro 100 ms dalla comparsa, fornita al modello di volume insieme al segnale del bucket trascorso. Il fatto che aggiungano competenze al set di funzionalità esistente è una misurazione aperta, non un'affermazione.
Conclusione

L'affermazione in esame è ristretta e il blog ha già creato le condizioni per falsificarla: l'articolo VWAP ha stabilito che il vantaggio di VWAP è interamente la qualità della previsione e che la previsione fallisce nei giorni che costano di più. Un programma di aggiornamento intraday risolve il problema oppure no, e la risposta è un numero nel tercile negativo di un replay di 500 genitori.
Ciò che questo articolo non farà è allegare una cifra in bps a un sistema di produzione senza una replica dietro di essa. Affermazioni del tipo "una previsione di liquidità ben calibrata fa risparmiare 2-5 punti base, la differenza tra uno Sharpe di 1,5 e 2,0" sono esattamente il genere che Sharpe sgonfio e test multipli esiste per smantellare: senza fonti, incondizionato e mai accompagnato dalla dispersione. Il numero che conta qui è l'IS del quartile finale sul peggior tercile di giorni e può essere misurato oppure non riportato.
Autori
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.