Updating the Volume Curve Intraday: Does Adaptive Forecasting Actually Help?
Біз TWAP, VWAP және POV мақаласында BTCUSDT бойынша L2 replay-дің 90 күнінде үш scheduler-ді бетпе-бет салыстырдық және әдейі ашық қалдырылған қорытындыға келдік: криптовалютада pipeline-ның әлсіз жері slicing емес, көлем қисығы. Ол мақалада қарапайым нұсқа әдейі шығарылды — күн аптасы × тәулік уақытына негізделген медианалық қисық, апта сайын қайта fit жасалып, сауда күні бойы өзгеріссіз ұсталды. Нәтижесінде VWAP-тың TWAP-тан барлық артықшылығы болжам сапасына байланысты екені анықталды: іске асқан көлем қисығының қатесін ескергенде, ең жақсы болжамды күндер терцилінде VWAP TWAP-тан шамамен 4 bps озады, ал ең нашар терцильде айырма шуға сіңіп кетеді.
Бұл нәтиже нақты, жоққа шығаруға болатын жалғасты талап етеді. Егер VWAP қисық кездейсоқ дұрыс болған күндері ғана ұтса, онда күн өрбіген сайын өзін түзететін forecaster нашар терцильдегі күндердің бір бөлігін жақсы күндерге айналдыруы тиіс. Бірақ олай болмауы да мүмкін — мақаланың қызықты нұсқасы дәл осы нәтиже болар еді, өйткені криптовалютадағы нашар терцильге cascade және news күндері кіреді, ал дәл сол күндері байқалған көлемнің алғашқы екі сағаты келесі екі сағат туралы ең аз ақпарат береді.
Бұл мақала intraday updater-ді іске асырады, оны дәл сол harness-те жүргізеді және статикалық қисыққа қатысты IS delta-ны хабарлайды — тек орташаны емес, distribution мен соңғы квартиль санын да береді.
Не тексеріледі

Статикалық қисық — prior: offline бағаланған, әр bucket-тегі күтілетін көлем үлестерінің бекітілген векторы. Адаптивті нұсқа оны жаңартылатын prior ретінде қарастырады. bucket өтіп, нақты көлемдер бақыланғаннан кейін статикалық қисық елемейтін екі жаңа ақпарат бөлігі пайда болады:
- Деңгей бағасы. Егер prior bucket-тері күн көлемінің үлесін тасуы тиіс десе, ал олар бірлік тасымалдаса, онда толық күннің болжамды жиыны болады. Бұл "бүгін көлемді күн" / "бүгін өлі күн" сигналы және ол бірінші bucket-тен бастап қолжетімді.
- Пішінді түзету. Өткен bucket-тердің іске асқан пішіні prior пішінінен жүйелі түрде ауытқыса, қалған bucket-тер де ауытқуы мүмкін — бірақ бұл intraday көлем қисығының қателері күн ішінде autocorrelated болған жағдайда ғана мүмкін. Ал бұл өз алдына эмпирикалық сұрақ, оны тегін жасалатын болжам ретінде қабылдай алмаймыз.
Төмендегі implementation (1)-ді толық пайдаланады, ал (2)-ні мүлде пайдаланбайды: untouched prior tail-ды жаңартылған жиынға renormalize етеді. Бұл консервативті нұсқа және алғашқы экспериментке дұрыс таңдау, өйткені таза level update қолжетімді delta-ның көп бөлігін ұстап алса, shape machinery ақталмаған күрделілік болады.
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
Бұл кодтағы екі деталь экспериментті анықтайды. Prior — күн аптасына шартталған медианалық қисық, pooled mean емес. Бір liquidation cascade он минутта күндік көлемнің 15%-ын бере алатын нарықта мұның неге маңызды екенін VWAP мақаласының көлем қисығы бөлімінен көріңіз. Level update сыртқы ADV бағасына қарай shrink жасалады, оның салмағы өткен prior үлесіне тең, өйткені бірінші bucket-те implied_total нөлге жақын санға бөлінген бір бақылау ғана. Shrink жасалмаған updater бүлдіруге әлі ең көп уақыт қалған кезде ең нашар жұмыс істейді.
Стенд

Бұл TWAP/VWAP/POV run-ымен бірдей, сондықтан сандарды жол-жолымен салыстыруға болады:
- Instrument/data: BTCUSDT perpetual, L2 replay-дің 90 күні (жоғарғы 20 level, 100 ms) және trades tape. Барлығы UTC; funding timestamp-тері белгіленген.
- Parent orders: 500, horizon h, trailing 30-day ADV-дің 0.75%-ы, buy side, decision price — басындағы mid. Жарияланған run-дегідей random start time-дер.
- Arms: (A) статикалық weekly-refit қисығындағы VWAP — жарияланған baseline; (B) intraday update жасалған сол prior-дағы VWAP; (C) floor ретінде TWAP.
- Metrics: decision price-тың bps-індегі IS, fee-лер қосылған, arrival-ға қатысты — әр parent үшін mean, median, standard deviation, 95th percentile және final quartile IS ретінде хабарланады. VWAP slippage тек diagnostic ретінде жазылады, scoreboard ретінде ешқашан қолданылмайды; VWAP мақаласының benchmark бөлімінде VWAP slippage пен arrival IS екі algorithm-ді кері ретпен бағалайтын worked case көрсетілген. Opportunity-cost term-ін қоса алғандағы толық IS decomposition implementation shortfall және TCA мақаласында берілген.
Нәтижелер
Ол қажет жерде көмектесе ме?
Headline mean — мұндағы ең қызықсыз сан. Жарияланған нәтиже VWAP–TWAP айырмасы realized volume-curve error-ына қатысты monotone екенін көрсетті, сондықтан adaptive arm дәл солай бағалануы тиіс: 90 күнді static forecast пен realized bucket volumes арасындағы distance бойынша tercile-дерге бөліп, әр tercile ішіндегі adaptive-minus-static IS delta-ны хабарлаңыз.
Екі нәтиже де жариялауға жарайды, бірақ олардың мағынасы қарама-қарсы:
- Delta good tercile-де шоғырланған. Updater онсыз да жеңіл болған күндерді нақтылап жатыр. Cost distribution-ға net effect косметикалық; tail — hard-horizon alpha-driven parent нақты төлейтін нәрсе — өзгермейді. Бұл intraday updater әлсіз жердің шешімі емес екенін, әрі қарай shape-correction және cross-asset бағыттарын қарау керегін білдіреді.
- Delta bad tercile-де шоғырланған. Updater өзі үшін жасалған жұмысты атқарып жатыр: статикалық қисық ең көп қателесетін cascade және news күндерін ұстайды. Дәл осы нәтиже execution loop-қа қосылған state-ті ақтар еді.
Negative result — күтілетін нәтиже және оны ашық хабарлау керек. Crypto volume curve-ларын қиындататын механизм — cascade level shift емес, regime break — level-update forecaster-ді дәл осы механизм жеңеді: өткен bucket-тер бүгін көлемді күн екенін айтқан кезде, ең белсенді бөлік өтіп кетуі мүмкін. Бұл блогтың мұндай нәтижелерді неге жариялайтынын honest negative мақаласынан көріңіз.
Book slope: ол бірдеңе қоса ма?

Draft feature set-тегі, бірақ осы блогтың басқа жерінде қамтылмаған бір feature бар: book slope — touch-тен алыстаған сайын cumulative depth қаншалықты жылдам жиналады. формуласын top level бойынша fit жасаңыз; үлкен depth touch маңында шоғырланғанын, кіші оның 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])
Бұл пікірдің айтуға тұрарлық жалғыз нұсқасы — өлшенген нұсқа: қолданыстағы feature set-ке book_slope қосу volume forecast-ты немесе алынған IS-ті AR/EWMA baseline-інен жоғары өзгерте ме? Spread modeling мақаласы стандарт қояды — horizon-ды көрсетіп, trivial baseline-нен жоғары skill-ті хабарлаңыз, өйткені бұл series-терде persistence басым, ал headline R² негізінен autocorrelation-ды өлшейді.
Бұл мақала әдейі қайта шығармайтын нәрселер

Төмендегінің бәрі блогта әлдеқайда терең қамтылған, сондықтан оны мұнда қайта түсіндіру тек әлсіз екінші нұсқа жасар еді:
- Liquidity measurement. Roll estimator-і (signed-root fix және price-units-vs-returns trap-ымен) және Kyle lambda-сы: machine learning көмегімен spread modeling. Kyle lambda-сы real Binance aggTrades-та Almgren-Chriss мақаласындағы permanent-impact coefficient ретінде де calibrated жасалған. Walk-the-book sweep cost: slippage және cost models.
- Order book features. Weighted mid (ол Stoikov microprice-ы емес — microprice martingale-adjusted), multi-level book imbalance, OFI және толық LOB feature taxonomy: DeepLOB және spread modeling.
- Intraday patterns. Equity U-shape close-ы жоқ market үшін қате model; оны алмастыратын crypto session/funding/weekly structure және day-of-week × time-of-day grid VWAP мақаласында. Cyclical time-of-day encoding spread мақаласының feature table-інде.
- Scheduled events. Deribit 08:00 UTC expiries, US macro 12:30/14:00 UTC-та, CME settlements — baseline curve-ды ластауға жол бермей, оларды dummy ретінде қараңыз; нақты crypto calendar VWAP мақаласында. Жоғарыдағы adaptive updater event handler емес және одан сондай болуды сұрамау керек.
- Models. Purged, embargoed walk-forward CV бар gradient boosting spread modeling мақаласында берілген (қарапайым
TimeSeriesSplitқабаттасатын forward-window target арқылы leakage жасайды); CNN-LSTM family, 40-feature/10-level input tensor, LOBFrame және replication-crisis discussion DeepLOB мақаласында. Level axis-ті recurrent layer-ге дейін collapse жасауға болмайтынын ерекше ескеріңіз. - Child-order шешімі. Passive пен aggressive арасындағы break-even арқылы есептеледі, ол hard-coded spread threshold емес: child order execution tactics. Participation-rate targeting endogenous — өз fills-теріңіз tape-те басылады — ал түзету VWAP мақаласында.
- Venue fragmentation. Crypto-дағы smart order routing, әр venue бойынша TCA scorecard implementation shortfall мақаласында.
- Production latency. DeepLOB production section; spread мақаласы inference-time claims-ті әлдеқашан нақтылайды — 2000-round LightGBM Python-нан tens of microseconds ішінде болжайды, single-digit тек compiled predictor арқылы мүмкін.
Adversarial dynamics жеке section емес, бір paragraph-қа лайық. Displayed depth жартылай performative, ал detection mechanics — cancel rate, wall build-up speed, price жақындағандағы behavior, layering — queue position және wall analysis мақаласында нақты PIQ-based method арқылы қамтылған. Бұл мақала қоса алатын жалғыз delta — оларды forecaster input-тары ретінде қарау: cancel-to-trade ratio, touch-тағы mean resting time және пайда болғаннан кейін 100 ms ішінде cancel болатын depth үлесі elapsed-bucket signal-ымен бірге volume model-ге беріледі. Олардың қолданыстағы feature set үстіне skill қосатыны — claim емес, ашық measurement.
Қорытынды

Тексеріліп отырған claim тар, blog оны жоққа шығаруға жағдайды әлдеқашан жасады: VWAP мақаласы VWAP edge-і толығымен forecast quality-ге байланысты екенін және forecast ең қымбат күндері сәтсіз болатынын көрсетті. Intraday updater мұны түзетеді немесе түзетпейді, ал жауап 500-parent replay-дің bad tercile ішіндегі сан болады.
Бұл мақала replay-сыз production system-ге bps санын жапсырмайды. "Well-tuned liquidity prediction 2–5 bps үнемдейді, бұл Sharpe-ті 1.5-тен 2.0-ге өзгертеді" түріндегі claims — deflated Sharpe және multiple testing тарқатуға арналған дәл сол жанр: source жоқ, condition жоқ және dispersion көрсетілмейді. Мұндағы маңызды сан — ең нашар күндер терциліндегі final-quartile IS; ол не өлшенеді, не хабарланбайды.
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.