Updating the Volume Curve Intraday: Does Adaptive Forecasting Actually Help?
TWAP、VWAP、POV では、90 日間の BTCUSDT L2 リプレイで 3 つのスケジューラすべてを直接実行し、意図的に傷口として残された結論に達しました。暗号通貨では、スライスではなく、ボリューム カーブがパイプラインの最も弱いリンクです。 この記事では、中央値ベース、曜日 × 時刻のカーブ、毎週再調整されたシンプルなバージョンを意図的に出荷しました。取引日を通じて静的に維持されます。そして、TWAPに対するVWAPの優位性はすべて予測品質であることが判明した。現実の出来高曲線誤差を条件として、VWAPは数日の最良予測三分位でTWAPを約4bps上回り、そのギャップは最悪の三分位でノイズに崩壊する。
この結果は、具体的で反証可能な追跡調査を意味します。 VWAP がたまたま曲線が正しくなった日のみに勝つのであれば、その日の展開に応じて修正する 予報担当者は、悪い日の一部を良い日に変換するはずです。あるいは、そうすべきではありません。そして、この記事の興味深いバージョンは、そうでないバージョンです。なぜなら、暗号通貨で悪いターシルはカスケード日とニュース日であり、これらの日はまさに、最初の 2 時間の観測量が次の 2 時間についての情報が最も少ない日だからです。
この記事では、日内アップデータを実装し、同一のハーネスに対して実行し、平均値だけでなく分布と最終四分位数を含む静的曲線に対する IS デルタをレポートします。
何がテストされているか

静的曲線は、オフラインで推定されたバケットあたりの予想体積分率の固定ベクトル です。アダプティブ バージョンでは、更新前のバージョンとして扱われます。 バケットが経過し、実際の量 を観察すると、静的曲線が捨てた 2 つの新しい情報が得られます。
- レベルの推定値。 前項で、バケット がその日の端数 を運ぶ必要があり、 ユニットを運ぶ必要がある場合、暗黙の 1 日の合計は になります。これは、今日は忙しい日/今日はデッドデーのシグナルであり、最初のバケットから利用できます。
- 形状の修正。 経過バケットの現実の形状が以前の形状から系統的に逸脱する場合、残りのバケットも逸脱する可能性があります。ただし、それは日中の出来高曲線誤差がその日のうちに自己相関している場合に限ります。これはそれ自体経験的な問題であり、無料で行える仮定ではありません。
以下の実装では、(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
そのコードの 2 つの詳細には実験が含まれています。前のものは、プールされた平均ではなく、曜日で条件付けされた 中央値 曲線です。1 回の清算カスケードが 10 分間で 1 日の出来高の 15% になる可能性がある市場でなぜそれが重要なのかについては、VWAP 記事 の出来高曲線セクションを参照してください。また、最初のバケットでは implied_total が 1 つの観測値をゼロに近い数値で割ったものであるため、レベルの更新は 外部 ADV 推定に向けて縮小され、経過した前の部分に等しい重みが付けられます。縮小されていないアップデーターは、破滅まで残り時間がほとんどないときに、最悪の作業を実行します。
検証ハーネス

TWAP/VWAP/POV 実行と同じなので、数値は行ごとに比較できます。
- 商品/データ: BTCUSDT 永久、90 日間の L2 リプレイ (上位 20 レベル、100 ミリ秒) と取引テープ。 UTC 全体。資金調達タイムスタンプにフラグが立てられています。
- 親注文: 500、ホライズン h、サイズはトレーリング 30 日 ADV の 0.75%、買い側、決定価格 = 開始時中間。公開された実行と同じランダムな開始時間。
- アーム: (A) 静的な週次リフィット曲線上の VWAP — 公表されたベースライン。 (B) 日中の更新を伴う以前と同じ VWAP。 (C) フロアとしての TWAP。
- 指標: 到着対手数料を含む決定価格の BPS 単位の IS です。平均、中央値、標準偏差、95 パーセンタイル、および各親の最終四分位の IS として報告されます。 VWAP スリッページは診断としてのみ記録され、スコアボードとして記録されることはありません。 VWAP 記事のベンチマーク セクション は、VWAP スリッページと到着 IS が 2 つのアルゴリズムを逆の順序でランク付けする、成功したケースを示しています。機会費用項を含む完全な IS 分解は、実装不足と TCA に続きます。
### 結果
必要な場面で役立つか?
ここでの見出しの平均値は、最も興味のない数値です。公開された結果では、VWAP-TWAP ギャップが実現ボリューム曲線誤差において単調であることが確立されているため、適応アームも同じ方法でスコア付けする必要があります。つまり、静的 予測と実現バケット ボリュームの間の 距離によって 90 日を三分点にバケット化し、各三分点内の適応マイナス静的 IS デルタを報告します。
2 つの結果はどちらも公開可能ですが、意味は正反対です。
- デルタは良好なターシルに集中しています。 アップデーターは、すでに簡単だった日々を改良しています。コスト配分に対する最終的な影響は表面的なものです。テール(ハードホライズンのアルファ駆動の親が実際に支払うもの)は変化しません。これは、日中アップデーターは最も弱いリンクの修正ではなく、形状修正と資産間のルートが次に注目すべき場所であることを意味します。
- デルタは悪いターシルに集中しています。 アップデーターは、静的曲線が最も間違っているカスケードとニュース日を捕捉するという本来の目的を果たしています。これは、実行ループに追加された状態を正当化する結果です。
否定的な結果は予想された結果であり、明確に報告する価値があります。暗号通貨の出来高曲線を難しくするメカニズム — カスケードはレベルシフトではなく体制破壊です — は、まさにレベル更新予測を打ち負かすメカニズムです。経過したバケットが今日のボリュームが重いと示す頃には、重い部分は終わっているかもしれません。このブログがこれらを公開する理由については、正直な否定的]を参照してください。
板の傾き: 何かを付け加えるか?

ドラフト機能セットの 1 つの機能は、このブログの他の場所では取り上げていません。ブック スロープ、タッチから離れるにつれて累積深度が蓄積する速さです。 を最上位の レベルに当てはめます。大きい はタッチ部分に奥行きが集中していることを意味し、小さい は本全体に薄く広がっていることを意味します。
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² は主に自己相関を測定するため、水平線が記載された簡単なベースラインを 上に レポートするスキルです。
この記事で意図的に再導出していないもの

以下のすべてはすでにブログに詳細に記載されており、ここで再説明しても、より弱い第 2 バージョンが作成されるだけです。
- 流動性測定。 Roll の推定器 (署名付きルート修正および価格単位対収益トラップを使用) と Kyle のラムダ: 機械学習によるスプレッド モデリング。カイルのラムダは、Almgren-Chriss.実例通りのスイープコスト: スリッページとコストモデル。
- オーダーブックの機能。 加重ミッド (ストイコフのマイクロプライスではありません。マーチンゲール調整されています)、マルチレベルブックインバランス、OFI、および完全な LOB フィーチャー分類: DeepLOB および スプレッドモデリング]。
- 日中パターン。 株価の U 字型は、終値のない市場にとっては間違ったモデルです。これに代わる暗号セッション/ファンディング/週単位の構造と曜日×時間帯のグリッドは、VWAP 記事.周期的な時刻エンコーディングは スプレッド記事の 機能テーブルにあります。
- スケジュールされたイベント。 デリビット 08:00 UTC 満了、米国マクロ 12:30/14:00 UTC、CME 決済 - ベースライン曲線を汚すのではなく、ダミーとして扱います。具体的な暗号カレンダーは VWAP の記事.上記のアダプティブ アップデーターはイベント ハンドラーではないため、イベント ハンドラーであるように要求されるべきではありません。
- モデル。 パージされ禁輸されたウォークフォワード CV (重複するフォワード ウィンドウ ターゲット全体でプレーン
TimeSeriesSplitがリーク) を使用したグラジエント ブースティングは、スプレッド モデリング; CNN-LSTM ファミリ、40 特徴/10 レベルの入力テンソル、LOBFrame、およびレプリケーションの危機に関する議論は DeepLOB.特に、レベル軸をリカレント レイヤーの前で折りたたんではいけないことに注意してください。 - 子注文の決定。 パッシブかアグレッシブは、ハードコーディングされたスプレッドしきい値ではなく、計算された損益分岐点 です: 子注文実行戦術。参加率の目標設定は内生的であり、テープには自分のフィルが印刷されます。修正は VWAP の記事.
- 会場の断片化。 crypto のスマート オーダー ルーティング、実装不足 ] の会場ごとの TCA スコアカード。
- 本番レイテンシ。 DeepLOB の本番セクション;スプレッド記事はすでに推論時間の主張を認定していることに注意してください。2000 ラウンドの LightGBM は Python から 数十マイクロ秒 で予測しますが、コンパイルされた予測子を使用した場合のみ 1 桁です。
敵対的なダイナミクス は、セクションではなく 1 つの段落に値します。表示される深さは部分的にパフォーマンス的なものであり、検出メカニズム (キャンセル率、壁の構築速度、価格が近づいたときの動作、階層化) は、キューの位置と壁の分析] の具体的な PIQ ベースの手法でカバーされています。この記事で追加できる唯一のデルタは、これらを 予測者入力 として扱うことです。つまり、キャンセル対トレードの比率、タッチ時の平均休止時間、出現から 100 ミリ秒以内にキャンセルされる深度の割合が、経過バケット信号とともにボリューム モデルに供給されます。既存の機能セットにスキルを追加するかどうかは、オープンな評価であり、主張するものではありません。
## 結論

検証されている主張は狭い範囲であり、ブログはすでにそれを改ざんするための条件を設定しています。VWAP の記事 は、VWAP の優位性は完全に予測品質であり、最もコストがかかる日には予測が失敗することを確立しました。日中のアップデーターはそれを修正するか修正しないかのどちらかであり、答えは 500 親のリプレイの悪い三分位の数字です。
この記事では、背後にリプレイを行わずに bps 数値を実稼働システムに接続することは行いません。 「適切に調整された流動性予測により 2 ~ 5 bps が節約され、シャープ 1.5 と 2.0 の差」という形の主張は、まさに 収縮したシャープと複数のテスト が解体するために存在するジャンルです。ソースがなく、条件付けされておらず、決して分散を伴わないものです。ここで重要な数値は、最悪の三分位日における最終四分位 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.