← 回到文章
可重現性

市場成熟度與 alpha

這一頁給出文章裡每一個數字背後的確切作法:資料、交易範圍、規則庫、執行引擎、成本、配對後的被估計量、凍結,以及描述性表格。程式片段是邏輯的簡短示意,不是生產用的程式碼。

資料

幣安:每一條序列都來自幣安的公開資料檔案庫(data.binance.vision),USD 保證金期貨,不需要任何憑證,每檔合約涵蓋:

  • 每月的 1 小時 K 線,也就是引擎與被估計量所用的價格序列;
  • 每月的 1 分鐘 K 線,一進來就縮成每小時一列,之後丟棄;
  • 每月的資金費率檔案,每筆支付一列,帶著檔案庫自己的結算間隔欄位;
  • 每日的 bookTicker 檔案(最佳買賣報價),公布期間為 2023 年 5 月 16 日到 2024 年 3 月 30 日;
  • 每日的 bookDepth 檔案(中價 ±1% 到 ±5% 之間的累積掛單名目金額,大約每 30 秒一個快照),使用期間為 2023 年 1 月 1 日到 2026 年 8 月 9 日。

合約清點:合約清單是從檔案庫重建的,而不是取自交易所當下的狀態。凡是曾經出現在每月 K 線前綴底下的代號都被列舉出來,這樣就能把交易所後來下架的合約找回來:986 個代號,其中 12 個從未有過成交。

每個代號的每月檔案都往前和往後走到第一根與最後一根成交量為正的 K 線。檔案存在不等於有在交易,所以邊界一律來自成交量,絕不來自第一個或最後一個檔案;之後以 USDT 報價且有過成交的 832 個代號構成這份研究。

第一個交易日:一檔合約的年齡時鐘,從它的永續合約在該交易所第一次錄得正成交量那天的 UTC 00:00 起算。以天計的年齡是從那個午夜算起的整數天數,所以同一個 UTC 日裡的每一根 K 線共用同一個年齡。

first_day_ms = first_positive_volume_bar_ms // DAY_MS * DAY_MS
age_days     = (bar_open_ms - first_day_ms) // DAY_MS          # one clock, used everywhere

由於檔案庫最早的月份是 2020 年 1 月,有 3 檔合約的第一根存檔 K 線落在那個月,上市日期因此是左設限的,而且全部都在校準世代裡。整份清點中最後一個交易日,2026 年 7 月 31 日,就是存活分析所用的檔案庫結束日。

K 線內路徑:每個月的 1 分鐘 K 線縮成每小時一列:該小時的最高價與最低價、各自出現的分鐘、一個 high_first旗標(最高價的分鐘早於最低價的分鐘),以及一個 ambiguous 旗標(兩者落在同一分鐘)。

Bybit:802 個 USDT 線性永續合約檔案的小時 K 線,在 2026 年 9 月 21 日 UTC 22:23:09 以快照的形式凍結,讓輸入在封存之後無法再變動。資金費率取自 Bybit 公開的 v5 資金費率歷史端點,從每檔合約的最後一根 K 線往回翻頁到第一根。

訂單簿來自 Bybit 公開的訂單簿檔案庫(500 檔位的檔案,2025 年起為 200 檔位),從 2023 年開始。一檔 Bybit 合約的第一個交易日,是它第一根成交量大於零的小時 K 線所在的 UTC 日。

交易範圍

幣安世代:切分依據是第一個交易日。

世代上市時間合約數用途
校準2021 年 12 月 31 日(含)之前140只用來挑選規則庫,別無他用
證據2022 年 1 月 1 日起692幣安的被估計量(開發樣本)

692 檔證據合約中有 108 檔已經不再交易。幣安的被估計量跑在全部 692 檔上;其中 688 檔具備被估計量所需的 96 根小時 K 線(48 根的波動度窗口再加 48 根),4 檔沒有。它的成熟參照組取自同樣這 692 檔,一檔證據合約在它年齡超過 365 天的每一天進入參照組。

Bybit 交易範圍:驗證樣本取自 2022 年 1 月 1 日到 2026 年 7 月 31 日之間第一次有成交的 Bybit USDT 線性永續合約,這個上市窗口內有 620 檔合約,只保留年輕期價格路徑不在幣安資料裡的那些。代幣是以身分而不是以代號與幣安配對的,因為兩個交易所常常把同一個代幣掛在不同的倍數前綴下:

  1. 去掉 USDT 後綴,以及開頭的 1M 或十的次方前綴(101001000 等),得到代幣名稱。
  2. 因為去掉前綴才成立的名稱配對,要在一個共同的小時上確認:兩個交易所開盤價的比值必須落在某個十的次方的 15% 以內;沒通過的前綴配對視為不同代幣。
  3. 代號完全相同時一律視為同一個代幣,即使價格檢查沒通過,因為把它當成幣安沒碰過才是不安全的方向;而找不到共同小時可檢查的名稱配對,也一樣視為同一個代幣。
def token(sym):                        # "1000000BABYDOGEUSDT" -> "BABYDOGE"
    return re.sub(r"^(1M|10+)(?=[A-Z])", "", sym[:-4])

def same_token(bybit_open, binance_open):
    r = bybit_open / binance_open
    k = round(math.log10(r))
    return abs(r / 10**k - 1) < 0.15   # 1000TAG vs TAG passes at 996.40

前綴配對確認了 5 組(1000000BABYDOGE/1MBABYDOGE、10000SATS/1000SATS、1000TAG/TAG、1000TOSHI/TOSHI、1000TURBO/TURBO)。在代號完全相同的當中,有 4 組沒通過價格檢查但仍視為同一個代幣(HNT、ON、ORBS、SNT),另有 7 組名稱配對找不到共同小時,同樣視為同一個代幣。

接著每一檔合約落進其中一組。

分組規則合約數
只在 Bybit該代幣從來沒有幣安 USDT 永續合約79
Bybit 先上市幣安比 Bybit 晚至少 30 天上市該代幣77
重疊其餘全部464 檔,排除

對於「Bybit 先上市」這一組,年輕日在幣安上市前一天為止,任何還沒平倉的部位都在那天的最後一根 K 線平掉。這樣得到 156 檔合約,以及年齡 2 到 30 天的 4,524 個年輕日曆合約日,其中 4,284 個(年齡 3 天起)有波動度估計值,3,295 個完成配對。

Bybit 成熟參照組:2022 年 1 月 1 日起第一次有成交的 Bybit USDT 合約,在它們年齡超過 365 天的日子進入參照組,與幣安成熟那條腿的上市窗口一致。一檔「Bybit 先上市」的合約過了 365 天之後,也和其他合約一樣加入成熟腿。802 個檔案中有 715 檔合約載入被估計量;80 檔因為 2022 年之前上市、落在交易範圍外而跳過;7 檔的 K 線少於 96 根。

規則

詞彙:這套詞彙由 34 個規則變體組成,11 個變換與 23 個匯流條件閘。變換型規則把收盤價的某個變換在滾動的 L 根 K 線窗口上取 z 分數,當 z 分數穿過門檻時就順著方向交易。條件閘型規則以同樣方式對原始收盤價取 z 分數,只在條件閘為真的 K 線上保留訊號。

def desired_state(kind, name, L, thr, o, h, l, c):
    if kind == "transform":
        z = rolling_z(transform(name, c, L), L)
        gate = True
    else:
        z = rolling_z(c, L)
        gate = confluence_gate(name, o, h, l, c, L)
    d = np.where(z > thr, 1, np.where(z < -thr, -1, 0))
    return np.where(gate, d, 0)            # 0 = no instruction this bar

變換:base(收盤價)、slopenormalized_pricerocbiasvolZacceldisFromMedianquant_stretchrank_residfold_dev。條件閘:RSIge40RSIge50Pge0.7Pge0.8BW_filterpivrkurtosisskewskew0.75atr_pctatr_pct0.8burstfreqTinyBodyNoNewLowGreenRangeSpikeYesterdayPeakDeadFlat10InsideBarSameDirectionTopOfRangeVolContractionEMAHug

參數網格:每個變體都與回看期 L{4, 8, 12} 根 K 線、門檻取 {0.5, 1.0, 1.5}、最長持有取 {12, 48, 168} 根 K 線、停損距離取 {1, 2, 4} × ATR、報酬風險比取 {1, 1.5, 2, 3, 5} 交叉,共 34 × 405 = 13,770 組設定。把每一組設定都在 140 檔校準合約上篩過一遍,整個搜尋就是 13,770 × 140 = 1,927,800 次引擎執行。回看期最多到 12 根 K 線,好讓每一條規則在最年輕的被量測日之前就已經暖機完成。

篩選:篩選跑在至少有 2,000 根有成交小時 K 線的合約上,採用下面的保守 K 線內慣例,每一次成交收取 5 個基點的手續費,外加一檔成熟幣安合約實際量到的 7.4 個基點執行成本。年輕日永遠進不到這裡,因為合約年齡未滿 31 天的每一根 K 線,其訊號在評分之前就被設為零。一組設定要合格,必須有至少 35 檔合約(世代的四分之一)呈現至少 24 筆已平倉交易、分布在至少 6 個不同的日曆週,而且至少有 35 檔在合約最初 40 根 K 線之內出現第一個訊號。

signals[age_days < 31] = 0                                   # selection never sees young days
eligible = (n_contracts_active >= 35) & (n_contracts_warm >= 35)
ranked   = sorted(eligible_rows, key=lambda r: -r.pooled_net)
library  = first_per_variant(ranked, k=20)                   # one rule per variant

在這些條件下有 12,555 組設定合格,在校準世代上扣掉成本後沒有一組的合併淨值為正,毛值為正的有 73 組。規則庫是以合併的校準淨值排序的前 20 名,每個變體最多一條,且不做正值篩選,因為被估計量是「年輕減成熟」的差值,不論任一條腿是什麼符號,它都仍然有定義。

凍結的規則庫:

變體類型L門檻停損(× ATR)報酬風險比最長持有(K 線根數)
BW_filtergate41.541.5168
kurtosisgate120.545168
NoNewLowGreengate121.545168
pigate121.545168
Pge0.8gate121.545168
Pge0.7gate121.545168
TinyBodygate121.543168
skew0.75gate41.515168
InsideBargate41.545168
DeadFlat10gate41.545168
atr_pct0.8gate121.545168
vrgate121.545168
atr_pctgate121.545168
YesterdayPeakgate121.545168
RangeSpikegate81.543168
biastransform121.545168
skewgate41.545168
RSIge50gate121.54548
EMAHuggate41.543168
SameDirectiongate41.545168

規則庫裡的每一個條件閘測的都是已經收掉的 K 線:BW_filter,前一根 K 線的實體超過其全距的 70%;TinyBody,前一根 K 線的實體小於其全距的 10%;pi,前一根 K 線的實體除以 L 根 K 線的 ATR,與 π/4 相差在 0.05 以內;kurtosis,滾動 L 根報酬的峰度至少為 5;skewskew0.75,滾動報酬偏態的絕對值至少為 0.5 與 0.75;Pge0.7 Pge0.8,前一根收盤價落在它滾動 L 根全距的最高 30% 或 20%;atr_pct atr_pct0.8,對 L 根 K 線 ATR 在它自己的滾動全距內做同樣的測試;vr,2 根對 1 根的變異數比至少為 1;NoNewLowGreen,前一根 K 線收在上漲,且它的最低價高於再往前 5 根的收盤價;RangeSpike,前一根 K 線的全距超過它 20 根平均的 1.3 倍;YesterdayPeak,往前 2 根的收盤價是最近 3 根裡最高的;DeadFlat10,到前一根收盤為止的 10 根 K 線內,收盤價變動不到 0.5%;InsideBar,往前 2 根的 K 線落在前一根 K 線的全距之內;SameDirection,最近 2 根 K 線收在同一個方向;RSIge50,前一根的 14 根 K 線 RSI 至少為 50;EMAHug,前一根收盤價與它 21 根均價的距離,在前一根 K 線全距的 0.92 倍以內。唯一的變換 bias,是收盤價 L 根斜率的 L 根指數平均。

規則庫檔案的 SHA-256 是 3b4c9b75e5ce3ddb66ba21c1d4fcdeda3ad8a6513881857295b0cbdfae528556

引擎

每條規則、每檔合約同時只有一個部位,採固定名目金額、不複利。部位大小是進場時的一單位名目金額,所以每一個損益數字都是進場名目金額的一個比例。

  • 進場:在已收完的第 t 根 K 線上算出的訊號,在第 t+1 根 K 線的開盤進場;持有部位期間出現的同方向訊號則忽略。反方向訊號在下一個開盤平倉並就地反手,付兩次成交;而訊號為零並不是出場指令。
  • 障礙:停損與停利在進場時由進場前一根 K 線為止的 Wilder ATR(14) 決定,停損距進場價 stop × ATR,停利距進場價 stop × ATR × 報酬風險比;之後兩者都不再移動。
  • 最長持有:自進場起經過 H 根 K 線之後,部位在該根 K 線的開盤出場。
  • 跳空:開盤價穿過停損時以該開盤價成交;開盤價穿過停利時以停利價成交,絕不會更好。
  • 進場那根 K 線:進場在開盤,所以整根 K 線的全距都發生在進場之後,兩個障礙在進場那根 K 線上都是有效的。
  • 同一根 K 線同時碰到兩個障礙:真實順序(僅幣安)下由 1 分鐘路徑決定:多單若最高價出現在最低價之前,則停利先成交,否則停損先成交,空單則相反;兩個極值出現在同一分鐘、或路徑紀錄無法重現該根 K 線最高與最低價的 K 線,一律判為停損。保守慣例把每一根這樣的 K 線都判為停損,多空一視同仁。Bybit 沒有分鐘路徑,所以只跑保守慣例,幣安則兩種都跑。
  • 障礙成交後的再進場:如果在某根 K 線內停損或停利成交之後,規則仍然想要部位,新部位就以障礙價成交,也就是簿子實際被打平的價格,而不是那根 K 線的開盤價。在那根 K 線上只有新的停損會觸發,並以該 K 線的不利極值判定,而新的停利從下一根 K 線起才生效,因為成交之前那一段全距不能歸給新部位。
  • 一根 K 線內的順序:資金費率、跳空障礙、反手、最長持有、新進場、K 線內障礙、強制平倉。
  • 資金費率:觀測到的支付以它真實的結算時間收取,每一筆落在結算時點當時或之後第一根開盤的 K 線上,並按結算前一刻所持有的部位以 方向 × 費率 × 數量 × 價格 計算,以該根 K 線的開盤價計值。資金費率為正時扣多單、付空單;在結算那根 K 線上才開的部位既不付也不收,而從前面帶進來的部位則會。

沒有任何訊號使用資金費率。幣安的費率來自檔案庫的資金費率檔案,帶著每筆支付的間隔;Bybit 的費率來自資金費率歷史端點。

for i in range(1, n):
    if pos: funding_cost += pos * rate[i] * qty * open_[i]          # 1. funding
    if pos:
        hit = barrier(pos, open_[i], high[i], low[i], hi_first[i], ambiguous[i])
        if hit:     close(i, hit.price); reentry_px = hit.price     # 2. gap / intrabar barrier
        elif want[i-1] == -pos: close(i, open_[i])                   # 3. reversal
        elif i - entry_i >= max_hold: close(i, open_[i])             # 4. maximum hold
    if not pos and want[i-1]:
        enter(i, at=reentry_px if exited_this_bar else open_[i])     # 5. entry
        check_barriers_on_entry_bar(i)                               # 6. intrabar barriers

每一筆交易都在各自的欄位裡帶著毛損益、手續費、滑價與資金費率,而 gross - fee - slippage - funding = net 在每一筆交易上都檢查過。在 7,234,659 筆幣安交易(真實順序)、7,234,637 筆(保守)與 8,059,098 筆 Bybit 交易中,沒有任何一筆違反它,最大殘差是 0.0。

在真實順序慣例下,7,555,948 根幣安小時 K 線中,有 7,525,107 根帶著可判定的分鐘順序,24,391 根的兩個極值落在同一分鐘,6,450 根的路徑紀錄與該 K 線的最高最低價不符,後兩類一律判為停損。

成本

每一次成交都付吃單手續費,加上該合約年齡分組在登記在案的 $10,000 部位規模下實際量到的執行成本。進場成交按進場年齡所屬分組收費,出場成交按出場年齡所屬分組收費,並以出場價除以進場價縮放,好讓收費不取決於這筆交易的結果。年齡 0 或 1 天的成交沒有對應分組,付第 2 至 7 天的成本。

slip = (cost_bp[bucket(age_entry)] + cost_bp[bucket(age_exit)] * exit_px / entry_px) / 1e4
fee  = fee_bp / 1e4 * (1 + exit_px / entry_px)
net  = gross - fee - slip - funding

手續費:幣安每邊收 5 個基點,Bybit 每邊收 5.5 個基點,都是最基本的吃單費率等級。

幣安半價差:取自 bookTicker 檔案庫,按固定的年齡階梯取樣:年齡 0、1、2、3、5、7、10、14、21、30、45、60、120、200、300、400、500、700、900 與 1,200 天,涵蓋在報價窗口內任何時點有交易的每一檔 USDT 合約,只保留落在窗口內的階。每個合約日的半價差,是該日所有報價的 (ask - bid) / (ask + bid) 中位數,以基點計,並剔除有效報價少於 100 筆的日子。分組的值是跨合約日的中位數,共 257 檔合約、1,425 個合約日。

幣安的衝擊成本:單一一份深度取樣、單一一套取樣規則涵蓋所有年齡,所以年輕腿與成熟腿來自同一份面板。每一檔合約都取年齡 3、7、14、28、45、75、120、160、240 與 300 天的 bookDepth 日,再加上從年齡 366 天(若更晚則從 2023 年 1 月 1 日)到該合約最後一天之間平均分布的 8 天,全部落在檔案庫窗口之內。

在每一天之內,每一個價帶的累積掛單名目金額取該日所有快照的中位數。接著把一張 $10,000 的買單沿著 1% 到 5% 的賣方階梯掃上去,每個價帶內假設密度均勻,成本就是以名目金額加權的中價距離平均。每個分組的值,先取每檔合約在該分組內各日的中位數,再取跨合約的中位數。

def sweep_cost_bp(cum_notional, size=10_000, bands=(1, 2, 3, 4, 5)):   # bands in % of mid
    filled = paid = prev_n = prev_d = 0.0
    for d, n in zip(bands, cum_notional):
        take = min(size - filled, n - prev_n)
        paid += take * (prev_d + (d - prev_d) * take / (n - prev_n) / 2)   # uniform in band
        filled += take; prev_n, prev_d = n, d
        if filled >= size: break
    return paid / size * 100                                          # % of mid -> bp
幣安分組半價差,基點合約日(合約數)$10,000 衝擊,基點合約日(合約數)每次成交成本,基點
2-7 天1.56346 (88)4.561,273 (642)6.12
8-30 天1.22355 (94)3.981,266 (650)5.20
31-90 天1.20168 (89)4.801,160 (613)6.00
91-180 天1.2091 (91)5.691,022 (526)6.89
181-365 天1.22104 (64)7.39848 (448)8.61
超過 365 天1.18189 (150)6.223,780 (477)7.40

Bybit:成本取樣自 Bybit 公開的訂單簿檔案庫。年輕日涵蓋交易範圍內每一檔合約在年齡 3、7、14 與 28 天的日子,且該年齡仍屬年輕(對「Bybit 先上市」的合約而言,是在幣安上市之前)。成熟日取自交易範圍之外、以種子 3 抽出的 60 檔 Bybit USDT 合約,每檔隨機 4 個日期,年齡在 365 天以上,期間為 2023 年 6 月 1 日到 2026 年 7 月 31 日,其中只有 2022 年起第一次有成交的合約才計入成熟分組。

每一天的檔案都由快照加上增量重播,每隔 60 秒的交易所時間就記錄一次半價差,以及一張 $10,000 市價單相對中價的成本,該成本是走過簿子的一買一賣取平均。每個合約日保留各自的中位數,每個分組再取跨合約日的中位數。衝擊成本是完整成本減去半價差。

取樣的 788 個合約日中,有 706 個存在於檔案庫裡。

Bybit 來源分組合約日(合約數)半價差,基點衝擊,基點每次成交成本,基點
2-7 天270 (135)3.8125.2029.01
8-30 天272 (136)3.9725.1729.14
超過 365 天164 (42)2.6127.2029.81

由於這份取樣只量到 3 個分組,其餘分組對應到最接近的已量測分組:31-90 天採用 8-30 天的成本,91-180 天與 181-365 天採用超過 365 天的成本。兩個交易所的每一個成本常數都放在同一個檔案裡,被估計量與凍結程序都會讀它(SHA-256 eb0e6aa42c367840b8d59fd8ac59ec43200bd968b4514ef53f594a0cd434e4eb)。

被估計量

觀測單位:觀測值是合約日,也就是該合約至少有一根小時 K 線的一個 UTC 日;年齡 0 與 1 天從不作為觀測日,不過那時開的交易,從年齡 2 天起仍然會計入它被持有的那些日子。每一筆交易的毛損益、手續費、滑價、資金費率與淨值,都平均分攤到從進場日到出場日(含)之間的存活日子上。一個合約日的值,是 20 條規則當天各自分攤額的總和除以 20,以基點計;當天沒有任何規則持有部位的日子計為零。

share = 1.0 / (exit_day_idx - entry_day_idx + 1)
day_pnl[entry_day_idx : exit_day_idx + 1] += trade_pnl * share
daily_bp = day_pnl.sum(over_rules) / 20 * 1e4                # fixed library size

波動度:實現波動度是最近 48 個小時對數報酬的標準差,以 K 線根數而不是時鐘小時計算。第 d 日的值讀自前一天 UTC 23:00 開盤的那根 K 線,也就是恰好在第 d 日開始時收掉的 K 線,所以第 d 日裡的任何東西都不會進到它自己的共變數。

如果那根 K 線缺漏,該日就沒有波動度,也無法配對。由於 48 根的窗口必須在當日開始之前收掉,年齡 2 天沒有估計值,所以第一個有估計值的年輕日是年齡 3 天。

分組:波動度分組是在小時實現波動度的自然對數上,以 −7.0、−6.5、−6.0、 −5.5、−5.0、−4.5、−4.25、−4.0、−3.75、−3.5、−3.25 與 −3.0 切開,得到 13 個兩端開放的分組。年齡分組為 2-7、8-30、31-90、91-180 與 181-365 天,成熟為 366 天以上,主要的年輕窗口是年齡 2 到 30 天。

配對:成熟合約日先在每一個(日曆日、波動度分組)格子內取平均,這樣擁擠的格子才不會壓過稀疏的格子。每一個年輕合約日再與自己所屬格子的成熟平均值相減。若某個年輕日所在的格子裡沒有成熟合約,該日算作未配對,絕不會拿去和別的格子比較。

被估計量就是這些配對差值的平均。一項列數檢查確認每一個年輕觀測值,恰好以一列配對或一列未配對的形式離開。

ref = mature.groupby(["day", "vol_bucket"]).net.mean()
diffs = young.join(ref, on=["day", "vol_bucket"], how="left", rsuffix="_ref")
matched = diffs.dropna(subset=["net_ref"])
estimand = (matched.net - matched.net_ref).mean()
樣本配對到的年輕日未配對未配對比例
幣安,年齡 2-30 天15,2443,57319.0%
Bybit,年齡 2-30 天3,29598923.1%

做拆解時,同一套配對分別跑在毛損益、手續費、滑價與資金費率上,也跑在每一個年齡分組(只在該組至少有 30 個年輕列時)與 3 條手臂上。所有手臂都來自同一條訊號流:多空兩個方向都交易,只做多把空方訊號打平成現金,只放空則把多方訊號打平。

統計推論:在配對差值上做以週分群的百分位拔靴法,2,000 次重抽,種子 20260810。週是從 Unix epoch 起算的 7 天區塊,所以是 UTC 的週四到週三,被抽到的區塊裡每一個年輕觀測值都一起移動。

成熟格子的平均值固定在全樣本的數值上,重抽只在年輕差值上進行。95% 區間取重抽平均值的第 2.5 與第 97.5 百分位。

rng    = np.random.default_rng(20260810)
block  = matched_day // 7                                  # epoch-day blocks
groups = [diff[block == b] for b in np.unique(block)]
draws  = [np.concatenate(rng.choice(groups, len(groups))).mean() for _ in range(2000)]
lo, hi = np.percentile(draws, [2.5, 97.5])

讀法:幣安在兩種 K 線內慣例下都跑,而且是開發樣本。Bybit 在保守慣例下只跑一次,是驗證性的檢定。發表規則在 Bybit 執行之前就定好了:若區間不含零且符號與幣安的估計值相同,就是一個被複現的年齡效應;其餘一切都是虛無結果,連同量到的區間寬度一起報告。

凍結

在 Bybit 的被估計量執行之前,封存了一個套件,裡面包含以下項目的 SHA-256 雜湊值:

  • 實作本身,包括被估計量、引擎、篩選引擎、規則詞彙、規則庫篩選、常數模組、檔案庫客戶端、成本建構器、成本檔案、Bybit 交易範圍建構器、分析驅動程式,以及凍結程序自己;
  • 各項產物:凍結的規則庫、完整的 13,770 列篩選結果、Bybit 交易範圍、Bybit 成本取樣、合約清點,以及完整的檔案庫代號清單;
  • 每一條輸入資料序列,逐檔計算:全部 832 檔合約的每一條幣安面板序列(小時 K 線、標記價格、溢價指數、資金費率、分鐘路徑、深度與深度取樣)、報價價差取樣、986 筆清點紀錄,再加上 802 個 Bybit K 線檔案、802 個 Bybit 資金費率檔案與 872 個 Bybit 訂單簿取樣檔案;
  • 登記在案的常數,直接從執行它們的模組讀出:年齡與波動度分組、波動度窗口、規則庫大小、部位規模、拔靴法的種子與重抽次數、參數網格、合格門檻與成本表。

封存在 2026 年 9 月 21 日 UTC 22:26:51 完成,套件雜湊值為 23f5bf876015564577d880fe86f7a5ac22b370d05f42713a7ef4fb846c8d31e1。一份副本在 22:28:34 UTC 上傳到機器之外的物件儲存,那裡會記錄一個本機無法竄改的上傳時間;Bybit 的結果在 22:32:53 UTC 產生,2 份幣安結果隨後在 22:32:58 UTC 產生。

驗證:被估計量在執行前會把套件裡的所有東西重新雜湊一次,只要有任何一項變動過、或封存時間不早於執行時間,就拒絕啟動。Bybit 的執行另外會拒絕非封存版本的規則庫、拒絕代號的子集合、拒絕非封存指定的輸出位置,也拒絕任何比封存更早的 Bybit 輸出檔案。每一份結果檔案接著都會記下套件雜湊值與封存時間。

ok, moved, bundle = verify(bundle_path)          # re-hash code, data, artifacts, constants
if not ok or bundle["created_utc"] >= now_utc():
    raise SystemExit("freeze does not verify; run refused")
results["seal"] = {"bundle_sha256": bundle["bundle_sha256"], "sealed_utc": bundle["created_utc"]}

描述性表格

文章前半的每一張表都是這樣算出來的,而年齡一律從清點認定的第一個交易日起算,以整數天計。

一檔合約隨年齡如何改變:全部 692 檔幣安證據合約都納入,不設歷史長度下限,其中 691 檔實際有貢獻。以合約與年齡分組(0-1、2-7、8-30、31-90、91-180、181-365、超過 365 天)為單位,各欄使用該合約成交量大於零的小時 K 線,且該分組內至少需要 24 根 K 線:

  • 波動度:小時對數報酬的標準差乘以 √8,760;
  • 與比特幣的相關係數:在共同時間戳上,小時對數報酬與 BTCUSDT 的皮爾森相關係數;
  • 成交量對自身成熟水準:該分組的小時報價成交量中位數,除以同一檔合約超過 365 天時的中位數,只計入達到該年齡的 352 檔合約。

資金費率是按每筆支付而不是按每根 K 線計算的。每一筆支付以 rate × 8 / interval 換算成八小時等值(零也包含在內),並歸入該筆支付年齡所屬的分組。每檔合約在至少 3 筆支付上取平均值與標準差,之後每一欄都是跨合約的中位數。

r8 = rate * 8.0 / interval_hours                     # 1h, 2h, 4h and 8h payments comparable
per_contract = payments.groupby("bucket").r8.agg(["mean", "std"])   # needs >= 3 payments
table = per_contract_all.groupby("bucket").median()                 # median across contracts

結算時程:全部 832 檔 USDT 合約都以檔案庫的每筆支付間隔欄位涵蓋,起始間隔取自該合約第一筆支付的間隔,並依上市年份製表。「從來沒有以八小時結算」與「至少改過一次間隔」是在每檔合約完整的支付歷史上計算的。依年齡看的支付比例,則是把年齡分組(0-7 天、8-30 天等等)內所有合約的每一筆支付合在一起算。

依年齡看的報價價差:使用 成本 一節所述的半價差取樣,分組值取跨合約日的中位數。同一檔合約的那張表用的是報價窗口內上市的 86 檔合約:每檔合約在各分組的半價差中位數;它 0-1 天的值對它在較晚分組的值的比值;再取這些比值的中位數與大於一的比例。

依年齡看的深度與衝擊成本:使用 成本 一節所述的深度取樣與掃簿計算,買方向、$10,000,第一列把年齡 3 天與 7 天合在一起。同一檔合約那一欄,是把每檔合約在年輕分組的衝擊中位數,除以它自己超過 365 天的中位數(僅限兩者都有的合約),再報告比值的中位數與小於一的比例。

Bybit 執行成本:使用 成本 一節所述的訂單簿取樣,706 個合約日。

Abdi-Ranaldo 檢定:報價窗口內上市的 86 檔合約,在固定階梯上貢獻年齡 0 到 60 天、共 987 個合約日。每個合約日的估計值,是該日小時 K 線上 Abdi-Ranaldo 數值的中位數(負值截在零),只取成交量大於零的 K 線。用來對照的真實值,是同一天實際量到的報價半價差。

每個格子是該年齡區間內所有配對的中位數,比值那一欄是各配對比值的中位數,而等級相關係數是全部 987 組配對上的 Spearman 係數(+0.0349)。這個估計式回傳的是完整的有效價差,這說明了水準落差的大約一半,而把它除以二並不會改變等級相關係數。

存活:檔案庫結束日是清點中的最後一個交易日(2026 年 7 月 31 日),而一檔合約若在檔案庫結束前至少 k 天上市,就有資格計入年齡標記 k。若它至少交易了 k 天,或在檔案庫結束前 7 天之內還在交易,就算達到該標記。比例是達到數除以有資格數,並對 2022 年起上市的合約(692 檔)與 2021 年之前上市的合約(140 檔)分別計算。

eligible = archive_end - first_traded >= k_days
reached  = (last_traded - first_traded >= k_days) | (last_traded >= archive_end - 7_days)
share    = reached[eligible].mean()

索取完整的流程程式

完整的流程程式(合約清點、面板建構器、訂單簿取樣器、篩選、引擎、被估計量、凍結與描述性統計腳本)並未從這一頁散布。來信 daniel@daru.finance 索取。