課程「建立自己的套利機器人」第 14 課。到目前為止,機器人尋找的是幾秒內就會消失的價差。今天它會得到第二種策略:它緩慢而穩定地賺錢,但風險類型不同。
擁有同一枚幣的兩種方式
你可以在現貨市場買一枚幣:付錢、拿幣,這枚幣歸你。
你也可以交易這枚幣的期貨。期貨是一種價格跟隨這枚幣的合約。你不會拿到這枚幣,而是得到一個倉位:如果你做多,價格上漲 10,每枚幣賺 10;價格下跌 10,每枚幣虧 10。做空時則相反。期貨只需要把部分資金作為保證金,所以會帶來槓桿。
你最常遇到的交易所會提供永續期貨:沒有到期日的合約。這帶來一個問題。有到期日的期貨會在最後一天被迫回到現貨價格。永續期貨永不到期,那麼什麼讓它的價格保持在現貨附近?
資金費率
答案是交易者之間的一筆支付,叫作資金費率。每 8 小時一次,在許多交易所中,一方支付給另一方。
- 如果永續期貨的價格高於現貨,費率為正,多頭支付給空頭。
- 如果它低於現貨,費率為負,空頭支付給多頭。
這筆支付等於費率乘以倉位大小。過於熱門的多頭會變得昂貴,一些人就會平倉,價格會回到現貨。這就是整個機制。
策略的想法
同時持有兩邊:在現貨市場買 1 枚幣,並在永續期貨開 1 枚幣的空頭倉位。現在幣價不重要。如果價格上漲 10,現貨幣賺 10,空頭虧 10;如果價格下跌,情況相反。你的總額不變,交易者稱之為 Delta 中性。
剩下的就是資金費率。費率為正時,你持有空頭,每 8 小時收到一次支付。持有一個沒有價格風險的倉位,別人會向你付錢。這叫現貨持有套利或資金費率套利。
直接的方法:看年度數字
假設費率每 8 小時是 0.01%。每天有 3 次支付,因此 3 × 365 × 0.01% = 每年 10.95%。直接的結論是:投入 100,每年無風險收到 10.95,所以應該把全部資金都投進去。
用一個考慮更多因素的迴圈來檢查這個結論。下面的程式碼以 100 的價格開這組倉位,經過 90 次資金費率支付,也就是 30 天,並加上手續費。費用是:現貨交易為 0.1%,永續期貨交易為 0.05%,開倉和平倉時各付一次。
SPOT_FEE, PERP_FEE = 0.001, 0.0005 # taker fees, per trade
price = 100.0
# funding rate per 8 hours, 3 payments a day, 30 days = 90 payments
rates = [0.0001] * 45 + [0.00005] * 20 + [-0.0001] * 15 + [0.0001] * 10
def carry(rates, exit_when_negative=False):
cost_in = price * SPOT_FEE + price * PERP_FEE # buy spot, open short
cost_out = price * SPOT_FEE + price * PERP_FEE # sell spot, close short
income = 0.0
for r in rates:
if exit_when_negative and r < 0:
break
income += price * r # the short side receives r * notional
return income - cost_in - cost_out, income
for name, flag in [("hold all 30 days", False), ("leave at first negative", True)]:
net, gross = carry(rates, flag)
print(f"{name:24} funding {gross:6.3f} fees {2*(price*SPOT_FEE+price*PERP_FEE):.3f} net {net:+.3f}")
fees = 2 * (price * SPOT_FEE + price * PERP_FEE)
print("payments to cover fees", round(fees / (price * 0.0001)), "=", round(fees / (price * 0.0001) / 3, 1), "days")
輸出:
hold all 30 days funding 0.500 fees 0.300 net +0.200
leave at first negative funding 0.550 fees 0.300 net +0.250
payments to cover fees 30 = 10.0 days
逐條來看。
- 測試中的費率不是固定的:45 次支付為 0.01%,接著 20 次為其一半,接著 15 次負費率支付,最後 10 次又回到 0.01%。這模擬了真實市場,費率會隨交易者情緒變化。
- 持有全部 30 天:資金費率收入為 0.45 + 0.10 − 0.15 + 0.10 = 0.50。費用為 0.30,開倉 0.15,平倉 0.15。100 的淨結果是 +0.20,也就是一個月 0.2%,一年約 2.4%,而不是標題裡的 10.95%。
- 費率一轉負就離場,可多賺 0.05:15 次負支付花掉 0.15,最後 10 次正支付又帶回 0.10。
- 即使費率處於完整水準,也要 30 次支付、10 天才能打平。交易者以 0.01% 的費率持有這組倉位 3 天會虧錢。
因此,10.95% 只是一個上限,只有費率始終為 0.01% 且你長期持倉時才存在。這個迴圈解釋了第一種想法為什麼過於樂觀:費率會改變正負,手續費則在兩端都要支付。
開倉前機器人會檢查什麼
- 目前和預期費率。 看過去幾天的平均值,而不只是最新值。
- 兩端的費用。 把它們計入打平時間,並與費率保持穩定的時長比較。
- 哪家交易所支付。 同一枚幣在不同交易所的費率不同。機器人可能在一家交易所使用現貨市場,在另一家使用永續期貨,這也增加了把資金放在兩處的成本。
- 離場規則。 例如,「當平均費率轉負時離場」。像上面的迴圈一樣,規則應該寫下來並經過測試。
真正的危險:空頭使用保證金
現貨幣和空頭位於不同帳戶。空頭是帶槓桿的倉位,虧損吃掉保證金時,交易所會強制平倉,稱為強平。忽略較小的維持保證金時,一個粗略公式是:槓桿為 L 的空頭會在價格上漲約 100 / L% 時被強平:
for L in (2, 5, 10):
print(f"leverage {L:>2}: perp short liquidated near price {price*(1+1/L):6.1f} (+{100/L:.0f}%)")
leverage 2: perp short liquidated near price 150.0 (+50%)
leverage 5: perp short liquidated near price 120.0 (+20%)
leverage 10: perp short liquidated near price 110.0 (+10%)
現在情況改變了。如果槓桿為 5 時價格一天上漲 20%,你持有的幣賺了 20,但交易所已經以 20 的虧損強平了空頭。你會留下沒計畫過的、帶有價格風險的開放幣倉位。紙面上的總額原本不變,強制平倉打破了它。解法雖然樸素但有效:使用低槓桿,1 到 2 倍,準備一筆備用資金,價格上漲時機器人可以把它轉入保證金帳戶,並讓第 12 課的風險限制在保證金水準變低時停止一切。
讓 AI 代理人寫它並測試
一個模糊的要求:
建立一個資金費率套利機器人。
一個內建檢查方式的要求:
撰寫 carry.py,其中 carry(rates, price, spot_fee, perp_fee, exit_when_negative) 回傳 (net, gross)。當 price 為 100、費用為 0.001 和 0.0005,且費率清單使用第 14 課的數值,45 次 0.0001、20 次 0.00005、15 次 -0.0001、10 次 0.0001,持有全部期間時必須回傳 net 0.2,使用 exit_when_negative 時必須回傳 net 0.25。加入 break_even_payments(rate, price, spot_fee, perp_fee),當 rate 為 0.0001 時它必須回傳 30。加入 liquidation_price(entry, leverage) = entry * (1 + 1 / leverage)。不要發起網路請求,不要下真實訂單。
在信任程式碼前,手動核對這三個數字。
練習
- 執行程式碼,將每一個印出的數字與本課對照。
- 將現貨費率改為 0.0002,將永續期貨費率改為 0.0002,這是一位享受折扣的交易者。現在需要多少天完整費率才能打平?先手算:費用為 2 × (0.02 + 0.02) = 0.08。
- 更改費率清單,讓負費率部分持續 40 次支付。現在是繼續持有更好,還是在第一次負費率時離場更好?差多少?
- 對於 5 倍槓桿的情況,價格一天上漲 20%。在紙上寫下現貨一側和空頭一側會發生什麼,以及機器人為了保持安全,本應在這次移動前做什麼。
接下來
機器人現在有兩種策略:交易所間快速消失的價差,以及緩慢的資金費率收入。第 15 課會給它第三種策略,你可以選擇交易一對會共同移動的幣,統計套利,或在既有訊號上加入機器學習篩選器。