← 返回文章列表
August 13, 2026
5 分鐘閱讀

Updating the Volume Curve Intraday: Does Adaptive Forecasting Actually Help?

Updating the Volume Curve Intraday: Does Adaptive Forecasting Actually Help?
#microstructure
#liquidity
#execution
#prediction
#order-book

TWAP、VWAP 和 POV 中,我們在 90 天的 BTCUSDT L2 重播中對所有三個調度程序進行了正面交鋒,並得出了一個故意留下的結論:**在加密貨幣中,交易量曲線是管道中最薄弱的環節,而不是切片。 **那篇文章故意提供了簡單版本 - 基於中位數的、週內 × 日內時間曲線,每週重新調整,在交易過程中保持靜態一天。研究發現,VWAP 相對於 TWAP 的全部優勢在於預測品質:以已實現的成交量曲線誤差為條件,VWAP 在最佳預測的三分之一天數上比 TWAP 領先大約 4 個基點,而在最差的三分之一天數上,差距就變成了噪音。

這個結果意味著一個具體的、可證偽的後續行動。如果 VWAP 僅在曲線恰好正確的日子裡獲勝,那麼「隨著一天的展開而自我修正」的預測者應該將一些糟糕的 1/3 日子轉化為好的日子。或者它不應該——而這篇文章的有趣版本就是它不這樣做,因為加密貨幣中不好的三分位數是級聯日和新聞日,而這些天正是觀察到的前兩個小時的交易量對接下來兩個小時的信息最少的日子。

本文實現了日內更新程序,針對相同的工具運行它,並報告 IS 增量與靜態曲線的關係 - 包括分佈和最終四分位數,而不僅僅是平均值。

測試內容

根據觀察到的交易活動預先更新自適應交易量曲線

靜態曲線是先驗曲線:每個桶的預期體積分數的固定向量 u={u1,,uB}u = \{u_1, \ldots, u_B\},離線估計。自適應版本將其視為更新之前的內容。在 cc 儲存桶過去並且您觀察到實際磁碟區 V1,,VcV_1, \ldots, V_c 後,靜態曲線會丟棄兩個新資訊:

  1. **A 級別估計。 ** 如果前面說桶子 1..c1..c 應該攜帶當天的 icui\sum_{i \le c} u_i 部分,並且它們攜帶 icVi\sum_{i\le c} V_i 單位,則隱含的全天總數為 V^=icVi/icui\hat{V} = \sum_{i \le c} V_i \big/ \sum_{i \le c} u_i。這是一個今天是沉重的一天/今天是一個死日信號,它可以從第一個桶中獲得。
  2. **形狀修正。 ** 如果已過去的桶的實際形狀系統地偏離先前的形狀,則剩餘的桶也可能會偏離——但前提是日內成交量曲線誤差在當天內自相關,這本身就是一個經驗問題,而不是我們可以免費做出的假設。

下面的實作完全使用(1)和根本不使用(2):它將未觸及的先前尾部重新規範化為更新的總數。這是保守的版本,也是正確的第一個實驗,因為如果純粹的關卡更新已經捕捉了大部分可用的增量,那麼形狀機制就會變得不合理的複雜性。

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

在該程式碼中的兩個細節進行了實驗。先驗的是以星期幾為條件的中位數曲線,而不是匯總平均值——為什麼這在一個清算級聯可以在十分鐘內達到一天交易量 15% 的市場中很重要,請參閱 VWAP 文章 ](/en/blog/post/twap-vwap-pov-execution-algorithms) 的[交易量曲線部分。並且等級更新向外部 ADV 估計收縮,權重等於經過的先驗分數,因為在第一個儲存桶 implied_total 中是一個觀察值除以接近零的數字。一個未縮水的更新程序恰恰在剩下最多一天的時間來完成最糟糕的工作。

驗證工具

自適應預測研究工具中的平行執行路徑

TWAP/VWAP/POV 運行相同,因此這些數字是逐行比較的:

  • 工具/資料: BTCUSDT 永久,90 天的 L2 重播(前 20 個級別,100 毫秒)加上交易磁帶。全程採用 UTC 時間;資金時間戳記已標記。
  • 母單: 500,水平 T=4T = 4h,大小為追蹤 30 天 ADV 的 0.75%,買方,決策價格 = 開始時的中間價。與已發布的運行相同的隨機開始時間。
  • 武器: (A) 靜態每週改裝曲線上的 VWAP — 已發布的基線; (B) VWAP 與日內更新相同; (C) TWAP 作為底線。
  • 指標: 以基點為單位的決策價格、費用、與到達的 IS — 報告為平均值、中位數、標準差、第 95 個百分位數以及每個家長最後四分位數的 IS。 VWAP 滑點僅作為診斷記錄,絕不作為記分板; VWAP 文章的基準部分 顯示了一個可行的案例,其中 VWAP 滑點和到達是以相反的順序對兩種演算法進行排名。完整的 IS 分解,包括機會成本項,遵循實施不足和 TCA

結果

它能在需要的地方提供幫助嗎?

標題平均值是這裡最不有趣的數字。已發表的結果表明,VWAP-TWAP 差距在已實現的交易量曲線誤差中是單調的,因此自適應臂必須以相同的方式進行評分:根據靜態預測與已實現的存儲量之間的 L1L_1 距離將 90 天劃分為三分位數,然後報告每個三分位數內的自適應負靜態 IS 增量。

這兩個結果都是可發布的,但它們的含義相反:

  • **Delta 集中在良好的三分位。 ** 更新程式正在完善已經很容易的日子。對成本分配的淨影響是表面性的;尾部——這是硬視野阿爾法驅動的父母實際支付的費用——沒有改變。這意味著日內更新程序並不能解決最薄弱的環節,而形狀修正和跨資產路線是下一步需要關注的地方。
  • **Delta 集中在糟糕的三分位。 ** 更新程式正在執行其建構目的的工作:捕獲靜態曲線最錯誤的級聯和新聞日。這是證明執行循環中添加狀態的合理性的結果。

負面結果是預期的結果,值得明確報告。使加密貨幣交易量曲線變得困難的機制——級聯是“制度突破”,而不是水平轉移——正是擊敗水平更新預測者的機制:當經過的桶告訴你今天很重時,最重要的部分可能已經結束了。請參閱誠實的否定,以了解此部落格為何發布這些內容。

盤口斜率:它增加了什麼?

摘要限價訂單簿深度景觀與流動性斜率

草稿功能集中的一項功能未在本部落格的其他地方介紹:書坡度,當您遠離觸摸時累積深度的累積速度。將 CumVol(d)=α+βd\text{CumVol}(d) = \alpha + \beta d 安裝在頂部 KK 水平面上;大 β\beta 意味著深度集中在觸控處,小 β\beta 意味著深度分佈在書本上。

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])

此聲明唯一值得提出的版本是經過衡量的版本:將 book_slope 新增至現有功能集是否會使數量預測或產生的 IS 超出 AR/EWMA 基準? 傳播建模文章 設定了標準 - 報告技能高於具有規定範圍的瑣碎基線,因為這些系列以持久性為主,標題 R² 主要測量自相關。

本文故意不重新推導的內容

有界定量管道內的重點研究模組

下面的所有內容已經在部落格上進行了更深入的介紹,在這裡重新解釋它只會創建一個較弱的第二個版本:

  • Liquidity measurement. Roll's estimator (with the signed-root fix and the price-units-vs-returns trap) and Kyle's lambda: spread modeling with machine learning. Kyle's lambda is also calibrated on real Binance aggTrades as the permanent-impact coefficient in Almgren-Chriss. Walk-the-book sweep cost: slippage and cost models.
  • Order book features. The weighted mid (which is not Stoikov's microprice — that one is martingale-adjusted), multi-level book imbalance, OFI, and the full LOB feature taxonomy: DeepLOB and spread modeling.
  • Intraday patterns. The equity U-shape is the wrong model for a market with no close; the crypto session/funding/weekly structure that replaces it, plus the day-of-week × time-of-day grid, is in the VWAP article. Cyclical time-of-day encoding is in the spread article's feature table.
  • Scheduled events. Deribit 08:00 UTC expiries, US macro at 12:30/14:00 UTC, CME settlements — treat them as dummies rather than letting them pollute the baseline curve; the concrete crypto calendar is in the VWAP article. The adaptive updater above is not an event handler and should not be asked to be one.
  • Models. Gradient boosting with purged, embargoed walk-forward CV (a plain TimeSeriesSplit leaks across the overlapping forward-window target) is in spread modeling; the CNN-LSTM family, the 40-feature/10-level input tensor, LOBFrame, and the replication-crisis discussion are in DeepLOB. Note in particular that the level axis must not be collapsed before the recurrent layer.
  • The child-order decision. Passive versus aggressive is a computed break-even p=δ/(Π+δ)p^* = \delta/(\Pi + \delta), not a hard-coded spread threshold: child order execution tactics. Participation-rate targeting is endogenous — your own fills print on the tape — and the correction is in the VWAP article.
  • Venue fragmentation. Smart order routing in crypto, with the per-venue TCA scorecard in implementation shortfall.
  • Production latency. DeepLOB's production section; note that the spread article already qualifies inference-time claims — a 2000-round LightGBM predicts in tens of microseconds from Python, single-digit only with a compiled predictor.

對抗動態值得用一段而不是一節來描述。顯示的深度部分是執行性的,並且檢測機制——取消率、牆建立速度、價格接近時的行為、分層——在隊列位置和牆分析中使用基於PIQ的具體方法來涵蓋。本文可以添加的唯一增量是將它們視為「預測者輸入」:取消交易比率、觸摸時的平均休息時間以及出現後 100 毫秒內取消的深度分數,與經過的桶信號一起饋送到成交量模型。他們是否在現有功能集上增加了技能是一個開放的衡量標準,而不是一個聲明。

## 結論

從不確定性解析到測量執行結果的證據路徑

所測試的聲明範圍很窄,部落格已經設定了偽造它的條件:VWAP 文章 證實,VWAP 的優勢完全在於預測質量,並且預測在成本最高的日子裡失敗。日內更新程式要么修復這個問題,要么不修復這個問題,答案是 500 個父級重播的壞三分位數中的一個數字。

本文不會做的是將 bps 資料附加到生產系統,背後沒有重播。 「經過精心調整的流動性預測可以節省 2-5 個基點,夏普值為 1.5 和 2.0 之間的差異」這種形式的主張正是 洩氣夏普和多重測試 存在的目的是要拆除的類型:無源、無條件、且從不伴隨分散。這裡重要的數字是最差三分之一天數的最後四分位數,它要么被測量,要么不被報告。

免責宣告:本文提供的資訊僅用於教育和參考目的,不構成財務、投資或交易建議。加密貨幣交易涉及重大損失風險。

Authors

Eugen Soloviov
Eugen Soloviov

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.

Newsletter

緊跟市場步伐

訂閱我們的時事通訊,獲取獨家 AI 交易見解、市場分析和平台更新。

我們尊重您的隱私。您可以隨時退訂。