Files
Chan/research/live/probe_depth.py
T
jackandCursor 181bca303f 影子测量改用框架吃单原语,并补齐容量与 maker 成交率两项测算
吃单查询换成 Hummingbot 的 OrderBook.get_vwap_for_volume:手写的 walk_book
返回的是按计价币吃单的加权均价,但框架的 get_price_for_quote_volume 返回
边际价、get_vwap_for_volume 收基础币量,两者语义不同。改为按基础币下单
(真实委托与 PositionExecutor.amount 均是基础币计价),深度不足由
query_volume/result_volume 判定,框架此时返回 nan 而非一个看似正常的
部分成交均价。

落盘完整盘口(双边 50 档)。此前只记三个固定名义额的成交价,这批数据的
寿命就等于那几个档位的寿命;存完整深度后任意资金量级的冲击都能离线重算。
仓位档同时从 1k/5k/20k 提到十万量级,此前低估真实仓位约两个数量级。

订阅成交流,按根按价位聚合。买卖分开存——多头在目标位挂卖出靠主动买盘
成交,混在一起会把成交率高估约一倍。BTC 每根总成交额中位与 210 天历史
的 volume×close 差 0.3%,可确认采集完整。

新增两项测算:
- 冲击不是绑定约束。32 万仓位单边冲击 0.19~2.39bp,对 8.58~20.64bp 的
  预算只占 1.6~14.2%,冲击反推的资金上限 100~500 万。
- maker 成交率才是。止盈位被首次触及时,限价在该根价格区间中的位置
  中位 k=0.28(63.9 万次触及,三币一致);合并每根成交额后,32 万仓位
  的全额成交率仅 30.1%/15.6%/1.5%。要 80% 全额成交,仓位须 ≤ 4.7 万
  /1.4 万/0.26 万——比冲击反推的上限低 40~370 倍。

回测把这些止盈按「全额成交在目标价」计,故预算所依据的收益流本身需重估。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 02:39:47 +08:00

69 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""真实 Bitget 盘口在 BOOK_DEPTH 档内能不能吃下各个名义额档位。
shadow_hb 把吃单换成了框架的 get_vwap_for_volume,深度不足时它返回 nan、
整行标 depth_ok=0。所以「档数够不够」直接决定某个仓位档会不会整段丢失,
不是个可以事后补救的参数——先量出来再定 BOOK_DEPTH。
"""
from __future__ import annotations
import asyncio
import sys
import numpy as np
sys.path.insert(0, "/repo/research/live")
from shadow_hb import BOOK_DEPTH, NOTIONALS, SYMS, book_from
async def run() -> None:
from hummingbot.connector.derivative.bitget_perpetual.bitget_perpetual_derivative import (
BitgetPerpetualDerivative,
)
conn = BitgetPerpetualDerivative(
bitget_perpetual_api_key="", bitget_perpetual_secret_key="",
bitget_perpetual_passphrase="",
trading_pairs=[f"{s}-USDT" for s in SYMS], trading_required=False)
await conn.start_network()
print(f"连接器已启动,等盘口(档数上限 {BOOK_DEPTH}")
for _ in range(60):
await asyncio.sleep(1)
try:
if all(conn.get_order_book(f"{s}-USDT") is not None for s in SYMS):
break
except Exception:
continue
for s in SYMS:
ob = conn.get_order_book(f"{s}-USDT")
bids = np.array([(float(r.price), float(r.amount), i)
for i, (r, _) in enumerate(
zip(ob.bid_entries(), range(BOOK_DEPTH)))])
asks = np.array([(float(r.price), float(r.amount), i)
for i, (r, _) in enumerate(
zip(ob.ask_entries(), range(BOOK_DEPTH)))])
mid = (bids[0][0] + asks[0][0]) / 2.0
snap = book_from(bids, asks)
ask_notional = float((asks[:, 0] * asks[:, 1]).sum())
print(f"\n{s} 中价 {mid:.2f} · 取到 {len(asks)} 档 · "
f"卖盘 {len(asks)} 档合计 {ask_notional:,.0f} USDT")
print(f" 最深一档距中价 "
f"{(asks[-1][0] / mid - 1) * 1e4:.1f}bp")
for notional in NOTIONALS:
base = notional / mid
r = snap.get_vwap_for_volume(True, base)
px = float(r.result_price)
ok = float(r.result_volume) >= base * 0.999
if ok:
print(f" 名义 {notional:>7,.0f}{base:.6f} 币 · "
f"冲击 {(px / mid - 1) * 1e4:6.2f}bp · 吃得下")
else:
print(f" 名义 {notional:>7,.0f}{base:.6f} 币 · "
f"深度不足,仅 {r.result_volume:.6f} 币 · "
f"这一档会整段丢失")
await conn.stop_network()
if __name__ == "__main__":
asyncio.run(run())