Updating the Volume Curve Intraday: Does Adaptive Forecasting Actually Help?
Dalam TWAP, VWAP, dan POV kami menjalankan ketiga scheduler secara head-to-head pada replay L2 BTCUSDT selama 90 hari dan mencapai kesimpulan yang sengaja dibiarkan sebagai luka terbuka: dalam crypto, kurva volume adalah mata rantai terlemah pipeline, bukan slicing. Artikel itu sengaja menerbitkan versi sederhana — kurva berbasis median, hari-dalam-minggu × waktu-dalam-hari, di-refit setiap minggu dan dibiarkan statis sepanjang hari trading. Hasilnya menunjukkan bahwa seluruh keunggulan VWAP atas TWAP adalah kualitas forecast: setelah dikondisikan pada error kurva volume yang terealisasi, VWAP mengungguli TWAP sekitar 4 bps pada sepertiga hari dengan forecast terbaik, sementara selisihnya runtuh menjadi noise pada sepertiga terburuk.
Hasil itu menyiratkan tindak lanjut yang spesifik dan dapat difalsifikasi. Jika VWAP hanya menang pada hari ketika kurvanya kebetulan benar, maka forecaster yang mengoreksi dirinya sendiri sepanjang hari seharusnya mengubah sebagian hari di sepertiga buruk menjadi hari yang baik. Atau tidak — dan versi artikel yang menarik adalah ketika hal itu tidak terjadi, karena sepertiga buruk dalam crypto adalah hari cascade dan hari berita, tepat ketika dua jam pertama volume yang diamati paling sedikit informasinya tentang dua jam berikutnya.
Artikel ini mengimplementasikan updater intraday, menjalankannya dengan harness yang identik, dan melaporkan delta IS terhadap kurva statis — lengkap dengan distribusi dan angka kuartil akhir, bukan hanya mean.
Apa yang Diuji

Kurva statis adalah prior: vektor tetap berisi fraksi volume yang diharapkan per bucket, yang diestimasi offline. Versi adaptif memperlakukannya sebagai prior yang dapat diperbarui. Setelah bucket berlalu dan Anda mengamati volume aktual , ada dua informasi baru yang dibuang oleh kurva statis:
- Estimasi level. Jika prior menyatakan bucket seharusnya membawa fraksi dari total hari dan bucket tersebut membawa unit, total penuh hari yang tersirat adalah . Ini adalah sinyal hari-ini-hari-besar / hari-ini-hari-sepi, dan tersedia sejak bucket pertama.
- Koreksi bentuk. Jika bentuk terealisasi dari bucket yang telah berlalu menyimpang secara sistematis dari bentuk prior, bucket yang tersisa mungkin juga menyimpang — tetapi hanya jika error kurva volume intraday berkorelasi secara otokorelasi di dalam hari, yang merupakan pertanyaan empiris dan bukan asumsi yang boleh kita buat begitu saja.
Implementasi di bawah menggunakan (1) sepenuhnya dan (2) sama sekali tidak digunakan: implementasi ini menormalisasi ulang ekor prior yang belum tersentuh ke total yang telah diperbarui. Ini adalah versi konservatif dan eksperimen pertama yang tepat, karena jika pembaruan level murni sudah menangkap sebagian besar delta yang tersedia, machinery bentuk tambahan merupakan kompleksitas yang tidak beralasan.
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
Dua detail dalam kode itu membawa eksperimen ini. Prior-nya adalah kurva median yang dikondisikan pada hari-dalam-minggu, bukan mean gabungan — untuk alasan pentingnya hal ini di pasar ketika satu liquidation cascade dapat menjadi 15% volume sehari dalam sepuluh menit, lihat bagian kurva volume pada artikel VWAP. Dan pembaruan level diciutkan menuju estimasi ADV eksternal dengan bobot yang sama dengan fraksi prior yang telah berlalu, karena pada bucket pertama implied_total adalah satu observasi dibagi angka yang mendekati nol. Updater tanpa shrinkage bekerja paling buruk tepat ketika masih ada bagian hari terbesar yang dapat dirusaknya.
Harness

Identik dengan run TWAP/VWAP/POV, sehingga angkanya dapat dibandingkan baris demi baris:
- Instrumen/data: perpetual BTCUSDT, replay L2 selama 90 hari (20 level teratas, 100 ms) ditambah tape trades. Seluruhnya UTC; timestamp funding diberi penanda.
- Parent orders: 500, horizon h, ukuran 0.75% ADV trailing 30 hari, sisi beli, harga keputusan = mid pada awal. Waktu mulai acak sama dengan run yang dipublikasikan.
- Arms: (A) VWAP pada kurva statis hasil refit mingguan — baseline yang dipublikasikan; (B) VWAP pada prior yang sama dengan pembaruan intraday; (C) TWAP sebagai batas bawah.
- Metrik: IS dalam bps dari harga keputusan, termasuk fee, dibandingkan arrival — dilaporkan sebagai mean, median, standar deviasi, persentil ke-95, dan IS kuartil terakhir setiap parent. Slippage VWAP dicatat hanya sebagai diagnostik, tidak pernah sebagai scoreboard; bagian benchmark artikel VWAP menunjukkan kasus terperinci ketika slippage VWAP dan arrival IS memberi peringkat dua algoritme dalam urutan berlawanan. Dekomposisi IS lengkap, termasuk komponen opportunity cost, mengikuti implementation shortfall dan TCA.
Hasil
Apakah ini membantu di tempat yang dibutuhkan?
Mean headline adalah angka yang paling tidak menarik di sini. Hasil yang dipublikasikan menetapkan bahwa selisih VWAP–TWAP monoton terhadap error kurva volume yang terealisasi, sehingga arm adaptif harus dinilai dengan cara yang sama: kelompokkan 90 hari ke dalam tercile berdasarkan jarak antara forecast statis dan volume bucket yang terealisasi, lalu laporkan delta IS adaptif dikurangi statis dalam setiap tercile.
Dua hasil sama-sama layak dipublikasikan dan memiliki makna yang berlawanan:
- Delta terkonsentrasi pada tercile baik. Updater menyempurnakan hari yang sejak awal sudah mudah. Efek bersih pada distribusi biaya bersifat kosmetik; tail — yang harus dibayar oleh parent yang didorong alpha dengan horizon ketat — tidak berubah. Ini berarti updater intraday bukan perbaikan untuk mata rantai terlemah, dan jalur koreksi bentuk serta lintas aset adalah tempat berikutnya untuk mencari.
- Delta terkonsentrasi pada tercile buruk. Updater melakukan tugas yang dibangun untuknya: menangkap hari cascade dan berita ketika kurva statis paling salah. Inilah hasil yang akan membenarkan state tambahan dalam execution loop.
Hasil negatif adalah yang diharapkan dan layak dilaporkan secara terus terang. Mekanisme yang membuat kurva volume crypto sulit — cascade adalah regime break, bukan pergeseran level — tepat merupakan mekanisme yang mengalahkan forecaster pembaruan level: ketika bucket yang telah berlalu memberi tahu bahwa hari ini berat, bagian beratnya mungkin sudah berakhir. Lihat honest negative untuk alasan blog ini menerbitkan hasil seperti itu.
Kemiringan Book: Apakah Menambah Sesuatu?

Satu fitur dalam draft feature set yang belum dibahas di tempat lain di blog ini adalah book slope, yaitu seberapa cepat kedalaman kumulatif bertambah ketika Anda bergerak menjauh dari touch. Fit pada level teratas; besar berarti depth terkonsentrasi di touch, sedangkan kecil berarti depth tersebar tipis di seluruh book.
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])
Satu-satunya versi klaim ini yang layak dibuat adalah versi yang diukur: apakah penambahan book_slope ke feature set yang ada mengubah forecast volume, atau IS yang dihasilkan, melampaui baseline AR/EWMA? Artikel pemodelan spread menetapkan standarnya — laporkan skill di atas baseline sederhana dengan horizon yang dinyatakan, karena series ini didominasi persistence dan headline R² sebagian besar hanya mengukur autokorelasi.
Apa yang Sengaja Tidak Diturunkan Ulang oleh Artikel Ini

Semua hal di bawah ini sudah dibahas lebih mendalam di blog, dan menjelaskannya ulang di sini hanya akan membuat versi kedua yang lebih lemah:
- Pengukuran likuiditas. Estimator Roll (dengan signed-root fix dan jebakan price-units versus returns) serta lambda Kyle: pemodelan spread dengan machine learning. Lambda Kyle juga dikalibrasi pada aggTrades Binance nyata sebagai koefisien dampak permanen dalam Almgren-Chriss. Biaya sweep walk-the-book: model slippage dan biaya.
- Fitur order book. Weighted mid (yang bukan microprice Stoikov — microprice itu disesuaikan dengan martingale), imbalance book multi-level, OFI, dan taksonomi fitur LOB lengkap: DeepLOB dan pemodelan spread.
- Pola intraday. U-shape ekuitas adalah model yang salah untuk pasar tanpa penutupan; struktur sesi/funding/mingguan crypto yang menggantikannya, ditambah grid hari-dalam-minggu × waktu-dalam-hari, ada dalam artikel VWAP. Encoding waktu-dalam-hari siklik ada di tabel fitur artikel spread.
- Peristiwa terjadwal. Expiry Deribit 08:00 UTC, makro AS pada 12:30/14:00 UTC, settlement CME — perlakukan sebagai dummy, bukan membiarkannya mencemari kurva baseline; kalender crypto konkret ada dalam artikel VWAP. Updater adaptif di atas bukan event handler dan tidak boleh diminta menjadi event handler.
- Model. Gradient boosting dengan purged, embargoed walk-forward CV (plain
TimeSeriesSplitbocor melewati target forward-window yang saling tumpang tindih) ada di pemodelan spread; keluarga CNN-LSTM, tensor input 40 fitur/10 level, LOBFrame, dan diskusi krisis replikasi ada di DeepLOB. Perhatikan khususnya bahwa axis level tidak boleh dikolaps sebelum recurrent layer. - Keputusan child order. Pasif versus agresif adalah break-even terhitung , bukan threshold spread hard-coded: taktik eksekusi child order. Target participation rate bersifat endogen — fill Anda sendiri tercetak di tape — dan koreksinya ada dalam artikel VWAP.
- Fragmentasi venue. Smart order routing dalam crypto, dengan scorecard TCA per venue dalam implementation shortfall.
- Latensi produksi. Bagian produksi DeepLOB; perhatikan bahwa artikel spread sudah memberi kualifikasi pada klaim waktu inference — LightGBM 2000 putaran memprediksi dalam puluhan mikrodetik dari Python, dan hanya satu digit mikrodetik dengan predictor terkompilasi.
Dinamika adversarial cukup mendapat satu paragraf, bukan satu section. Depth yang ditampilkan sebagian bersifat performatif, dan mekanisme deteksinya — cancel rate, kecepatan pembentukan wall, perilaku saat harga mendekat, layering — dibahas dengan metode konkret berbasis PIQ dalam analisis queue position dan wall order book. Satu-satunya delta yang dapat ditambahkan artikel ini adalah memperlakukannya sebagai input forecaster: rasio cancel-to-trade, mean resting time di touch, dan fraksi depth yang membatalkan dalam 100 ms setelah muncul, lalu memasukkannya ke model volume bersama sinyal bucket yang telah berlalu. Apakah fitur-fitur itu menambah skill di atas feature set yang ada adalah pengukuran terbuka, bukan klaim.
Kesimpulan

Klaim yang diuji bersifat sempit dan blog sudah menyiapkan kondisi untuk memfalsifikasinya: artikel VWAP menetapkan bahwa keunggulan VWAP sepenuhnya merupakan kualitas forecast dan bahwa forecast gagal pada hari-hari yang paling mahal. Updater intraday memperbaiki masalah itu atau tidak, dan jawabannya adalah satu angka pada tercile buruk dari replay 500 parent.
Artikel ini tidak akan menempelkan angka bps pada sistem produksi tanpa replay di belakangnya. Klaim seperti "prediksi likuiditas yang dituning dengan baik menghemat 2–5 bps, perbedaan antara Sharpe 1,5 dan 2,0" adalah tepat jenis klaim yang deflated Sharpe dan multiple testing hadir untuk membongkar: tanpa sumber, tanpa kondisi, dan tidak pernah disertai dispersi. Angka yang penting di sini adalah IS kuartil terakhir pada tercile hari terburuk, dan angka itu sudah diukur atau tidak dilaporkan.
Penulis
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.