[Binance Championship] Strategi Kontrak Pengiriman Binance 3 - Hedging Kupu-kupu

Penulis:Lydia, Dibuat: 2022-11-11 18:17:46, Diperbarui: 2023-09-14 20:32:10

img

Baru-baru ini, Binance futures meluncurkan Binance Championship yang kedua (alamat:https://www.binancezh.com/cn/futures/activity/anniversary-competition/129-38599440) Platform resmi FMZ Quant juga telah menyelenggarakan sebuah tim, yang dapat ditemukan dengan mencari FMZ Quant secara langsung. Saat ini, ada hanya lebih dari 100 orang. Selamat datang untuk bergabung dengan kami. Setelah itu, Anda dapat menambahkan WeChat pemimpin tim: fmz_zhangchao, membalas Binance, dan kami akan mengundang Anda untuk bergabung dengan grup WeChat.

Strategi yang disiapkan untuk Kejuaraan Binance adalah lindung nilai kupu-kupu dari kontrak pengiriman. Artikel ini adalah laporan penelitian strategi. Perhatian: strategi hanya untuk referensi. Anda dapat mengemukakan ide Anda sendiri untuk optimasi atas dasar ini. Anda juga dipersilakan untuk berbagi. Laporan dapat digunakan di lingkungan penelitian situs web FMZ secara langsung (klik sudut kanan atas untuk mengunduh, dan unggah di Analisis).

img

1. Alasan strategis

Hedging perlu menemukan perbedaan harga yang stabil. Ketika perbedaan harga terlalu besar, pergi pendek perbedaan harga. Ketika perbedaan harga terlalu kecil, pergi panjang perbedaan harga. Ketika perbedaan harga kembali untuk menutup posisi, Anda akan mendapatkan perbedaan harga. Jika berjangka dan spot adalah hedging, ketika harga berjangka yang tidak terkirim jauh lebih tinggi dari harga spot, Anda dapat pergi pendek kontrak berjangka dan pergi panjang harga spot untuk short perbedaan harga. Ada juga hedging intertemporal kontrak dengan waktu pengiriman yang berbeda, dengan berjangka dan spot hedging, mereka juga dapat pergi panjang perbedaan harga. Berjangka dan spot dan cross-futures adalah strategi umum dengan persaingan sengit. Ketika tidak ada pasar, perbedaan harga relatif stabil. Meskipun dapat menjadi pasar jangka panjang, ada beberapa peluang, dan operasi manual juga sedang dilakukan. Karena mereka semua memiliki perbedaan harga yang stabil, ketika kontrak diperbandingkan dengan tiga hal yang mungkin, ini juga dikenal sebagai arbitrage harga kupu-kupu.

2. Prinsip-prinsip strategi

Kontrak standar mata uang Binance, seperti BTC dan ETH, memiliki tiga kontrak pada saat yang sama, yaitu, BTCUSD_ PERP abadi, BTCUSD_200925 dari kuartal saat ini, BTCUSD_ 201225 dari kuartal berikutnya. Kontrak abadi dapat digunakan sebagai spot. Secara umum, ada tiga perbedaan harga untuk lindung nilai dua kontrak: kuartal abadi saat ini, kuartal abadi berikutnya, dan kuartal abadi berikutnya. Arbitrage kupu-kupu membutuhkan tiga kontrak. Perbedaannya adalah (kuartal berikutnya - kuartal saat ini) - (kuartal saat ini - abadi), yaitu, perbedaan = kuartal berikutnya + abadi - 2 * kuartal saat ini. Untuk pergi panjang perbedaan harga, Anda perlu membuka kontrak posisi panjang untuk kuartal berikutnya dan kontrak abadi, dan pergi pendek dua kontrak untuk kuartal saat ini.

3. Hedging ruang

Saya telah merayapi data 5min K-line Binance dari 14 Agustus hingga 14 September, yang dapat dibaca langsung (karena perbedaan waktu, perbedaan waktu yang ditunjukkan adalah 8 jam).

Dalam [4]:

# Libraries to be imported
import pandas as pd
import requests
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import time
%matplotlib inline

Dalam [12]:

#Read the data, you can also upload the data to the FMZ forum, which can be referenced in the "Analyze" directly
df = pd.read_csv('https://www.fmz.com/upload/asset/1420b2081ecd122522d.csv',index_col = 0)
df.index = pd.to_datetime(df.index)
df.tail(3)

Keluar[12]:

img

Pertama, mari kita lihat perbedaan harga antara kontrak Bitcoin. Pada tanggal 17 Agustus, harga Bitcoin naik dengan cepat sebesar 500u. Secara umum, kontrak yang dikirimkan dengan premi dibandingkan dengan harga spot, dan harga spot naik. Harapan untuk masa depan akan lebih optimis. Perbedaan harga antara kontrak yang tidak dikirimkan dan keabadian akan menjadi lebih besar. Misalnya, perbedaan harga antara kuartal berikutnya dan keabadian akan menjadi 700u. Dengan penurunan harga Bitcoin pada bulan September, harapan orang akan memburuk dengan cepat, perbedaan harga antara kuartal berikutnya dan keabadian turun menjadi sekitar 150u, dan hampir tidak ada perbedaan harga antara kuartal saat ini dan keabadian. Jika lindung nilai antara kuartal berikutnya dan keabadian dilakukan, hanya pengembalian harga jangka panjang yang besar yang dapat dilakukan. Jika perbedaan antara 400-600 Agustus diputuskan untuk dilakukan sekarang, jelas itu terkunci dalam keadaan.

Dalam [18]:

#Perpetual price
df['BTCUSD_PERP'].dropna().plot(figsize=(15,6),grid=True);

Keluar[18]:

img

Di [15]:

# Price difference of next quarter - perpetual
(df['BTCUSD_201225']-df['BTCUSD_PERP']).dropna().plot(figsize=(15,6),grid=True);

Keluar[15]:

img

Di [16]:

# Price difference of current quarter - perpetual
(df['BTCUSD_200925']-df['BTCUSD_PERP']).dropna().plot(figsize=(15,6),grid=True);

Keluar[16]:

img

Di [17]:

# Price difference of next quarter - current quarter
(df['BTCUSD_201225']-df['BTCUSD_200925']).dropna().plot(figsize=(15,6),grid=True);

Keluar[17]:

img

Jadi bagaimana perbedaan harga berubah pada saat ini? Seperti yang dapat dilihat dari gambar di bawah ini, perbedaan harga baru-baru ini telah stabil di 100-200u untuk waktu yang lama. Bahkan penurunan tajam pada awal September tidak banyak mempengaruhi, memberi kita banyak ruang untuk arbitrase berulang. Saat ini, jika perbedaan harga turun ke 100u, tidak apa-apa untuk pergi panjang secara manual.

Ketika harga spot berfluktuasi, kedua kontrak yang belum kadaluarsa mencerminkan harapan masa depan pada saat yang sama. Proses pengurangan perbedaan harga dapat mengimbangi fluktuasi ini hingga tingkat yang besar, dan kinerja relatif stabil.

Dalam [19]:

#(next quarter - current quarter)-(current quarter - perpetual)
(df['BTCUSD_201225']-df['BTCUSD_200925']-(df['BTCUSD_200925']-df['BTCUSD_PERP'])).dropna().plot(figsize=(15,6),grid=True);

Keluar[19]:

img

Dalam [22]:

#The price difference of ETH
(df['ETHUSD_201225']+df['ETHUSD_PERP']-2*df['ETHUSD_200925']).dropna().plot(figsize=(15,6),grid=True);

Keluar[22]:

img

4. tes strategi

Untuk menghemat waktu (hanya kemalasan), backtest masih menggunakan mesin standar USDT dari strategi Kejuaraan Binance terakhir. Meskipun mungkin ada beberapa kesalahan, itu juga dapat menjelaskan masalah. Mesin backtesting ditempatkan di akhir laporan ini. Saat menjalankan kode, Anda harus melihat akhir artikel. Strategi standar mata uang dapat mempertimbangkan lindung nilai jika Anda ingin menghasilkan USDT, dan tidak rumit.

Garis tengah perbedaan harga dilacak oleh EMA, dan posisi dikendalikan oleh grid, yaitu setiap kali perbedaan dibuka (seperti 30), pergi pendek N saham, dan sebaliknya. Jika garis tengah perbedaan harga adalah 100u, ketika perbedaan harga adalah 90, pergi pendek 3 saham, dan perbedaan harga menjadi 60, menutup satu saham. Ukuran grid adalah parameter kunci.

Berikut ini adalah kode dan hasil backtesting BTC dan ETH tertentu. Kinerja sesuai dengan harapan. Karena ETH dan LINK memiliki volatilitas yang lebih besar dan perbedaan harga lebih stabil, kinerjanya lebih baik. Perhatikan bahwa biaya layanan di sini adalah 0,02%, dan biaya layanan pengambil VIP0 default di Binance adalah 0,04%. Biaya layanan sangat penting, dan bab-bab berikut akan menganalisisnya.

Di [39]:

trade_symbols = ['BTCUSD_201225', 'BTCUSD_200925', 'BTCUSD_PERP']
account = []
diff = df['BTCUSD_201225']+df['BTCUSD_PERP']-2*df['BTCUSD_200925']
diff_mean = diff.ewm(alpha=0.001).mean()
e = Exchange(trade_symbols,initial_balance=10000,taker_fee=0.0002)
for row in df[trade_symbols].dropna().iterrows():
    date = row[0]
    prices = row[1]
    e.Update(date, trade_symbols, prices)
    account.append([e.account['USDT']['margin'],e.account['USDT']['realised_profit']+e.account['USDT']['unrealised_profit']])
    aim_amount = -round((diff[date] - diff_mean[date])/30,1)
    now_amount = e.account['BTCUSD_PERP']['amount']
    if aim_amount - now_amount < -1:
        trade_amount = now_amount - aim_amount
        e.Buy('BTCUSD_200925',prices['BTCUSD_200925'],2*trade_amount)
        e.Sell('BTCUSD_201225',prices['BTCUSD_201225'],trade_amount)
        e.Sell('BTCUSD_PERP',prices['BTCUSD_PERP'],trade_amount)
    if aim_amount - now_amount > 1:
        trade_amount = aim_amount - now_amount
        e.Sell('BTCUSD_200925',prices['BTCUSD_200925'],2*trade_amount)
        e.Buy('BTCUSD_201225',prices['BTCUSD_201225'],trade_amount)
        e.Buy('BTCUSD_PERP',prices['BTCUSD_PERP'],trade_amount)
    
e.df = pd.DataFrame(index=df[trade_symbols].dropna().index,columns=['margin','profit'],data=account)
e.df['profit'].plot(figsize=(15,6),grid=True);

Keluar[39]:

img

Di [59]:

symbol = 'ETH'
trade_symbols = [symbol+'USD_201225', symbol+'USD_200925', symbol+'USD_PERP']
fee = 0.0002
account = []
diff = df[trade_symbols[0]]+df[trade_symbols[2]]-2*df[trade_symbols[1]]
diff_mean = diff.ewm(alpha=0.001).mean()
e = Exchange(trade_symbols,initial_balance=10000,taker_fee=fee)
for row in df[trade_symbols].dropna().iloc[30:].iterrows():
    date = row[0]
    prices = row[1]
    e.Update(date, trade_symbols, prices)
    account.append([e.account['USDT']['margin'],e.account['USDT']['realised_profit']+e.account['USDT']['unrealised_profit']])
    aim_amount = -round((diff[date] - diff_mean[date])/(15*prices[trade_symbols[2]]*fee),1)
    now_amount = e.account[trade_symbols[2]]['amount']
    if aim_amount - now_amount < -1:
        trade_amount = 1
        e.Buy(trade_symbols[1],prices[trade_symbols[1]],2*trade_amount)
        e.Sell(trade_symbols[0],prices[trade_symbols[0]],trade_amount)
        e.Sell(trade_symbols[2],prices[trade_symbols[2]],trade_amount)
    if aim_amount - now_amount > 1:
        trade_amount = 1
        e.Sell(trade_symbols[1],prices[trade_symbols[1]],2*trade_amount)
        e.Buy(trade_symbols[0],prices[trade_symbols[0]],trade_amount)
        e.Buy(trade_symbols[2],prices[trade_symbols[2]],trade_amount)
e.df = pd.DataFrame(index=df[trade_symbols].dropna().iloc[30:].index,columns=['margin','profit'],data=account)
e.df['profit'].plot(figsize=(15,6),grid=True);

Keluar[59]:

img

Di [60]:

symbol = 'LINK'
trade_symbols = [symbol+'USD_201225', symbol+'USD_200925', symbol+'USD_PERP']
fee = 0.0002
account = []
diff = df[trade_symbols[0]]+df[trade_symbols[2]]-2*df[trade_symbols[1]]
diff_mean = diff.ewm(alpha=0.001).mean()
e = Exchange(trade_symbols,initial_balance=10000,taker_fee=fee)
for row in df[trade_symbols].dropna().iloc[30:].iterrows():
    date = row[0]
    prices = row[1]
    e.Update(date, trade_symbols, prices)
    account.append([e.account['USDT']['margin'],e.account['USDT']['realised_profit']+e.account['USDT']['unrealised_profit']])
    aim_amount = -round((diff[date] - diff_mean[date])/(15*prices[trade_symbols[2]]*fee),1)
    now_amount = e.account[trade_symbols[2]]['amount']
    if aim_amount - now_amount < -1:
        trade_amount = 1
        e.Buy(trade_symbols[1],prices[trade_symbols[1]],2*trade_amount)
        e.Sell(trade_symbols[0],prices[trade_symbols[0]],trade_amount)
        e.Sell(trade_symbols[2],prices[trade_symbols[2]],trade_amount)
    if aim_amount - now_amount > 1:
        trade_amount = 1
        e.Sell(trade_symbols[1],prices[trade_symbols[1]],2*trade_amount)
        e.Buy(trade_symbols[0],prices[trade_symbols[0]],trade_amount)
        e.Buy(trade_symbols[2],prices[trade_symbols[2]],trade_amount)
e.df = pd.DataFrame(index=df[trade_symbols].dropna().iloc[30:].index,columns=['margin','profit'],data=account)
e.df['profit'].plot(figsize=(15,6),grid=True);

Keluar[60]:

img

5.Konsensitivitas komisi

Karena 3 kontrak perlu dioperasikan pada saat yang sama, 8 biaya layanan diperlukan untuk menutup posisi setelah pembukaan, sehingga biaya layanan memiliki dampak besar pada strategi. Jika ada biaya layanan sebesar 0,01%, kesenjangan antara kisi perbedaan harga dapat lebih berkurang. Hasil backtesting BTC ditunjukkan dalam gambar berikut:

img

Jika komisi adalah 0,03%, hasil backtest BTC adalah sebagai berikut:

img

Hasil backtest dari ETH:

img

Tingkat penerima vip0 untuk pengguna terdaftar baru adalah 0,0004, 10% akan dikurangi pada bulan pertama diundang, 30% akan dikembalikan, dan 10% akan dikurangi untuk konsumsi BNB. Dengan demikian, biaya penanganan akhir adalah 0,0002268.

Ringkasan

Tujuan dari arbitrage adalah untuk menemukan perbedaan harga yang stabil. Perbedaan harga dari perbedaan harga lebih stabil. Oleh karena itu, arbitrage kupu-kupu jauh lebih berisiko daripada periode silang dan spot masa depan, dan juga dapat dioperasikan secara manual. Strategi ini hanya berfungsi sebagai pengenalan. Banyak masalah yang perlu dipertimbangkan saat menulis di bot nyata. Selamat datang semua untuk berkomunikasi.

Dalam [23]:

class Exchange:
    
    def __init__(self, trade_symbols, leverage=20, maker_fee=0.0002,taker_fee=0.0004,log='',initial_balance=10000):
        self.initial_balance = initial_balance #Initial assets
        self.taker_fee = taker_fee
        self.maker_fee = maker_fee
        self.leverage = leverage
        self.trade_symbols = trade_symbols
        self.date = ''
        self.log = log
        self.df = pd.DataFrame()
        self.account = {'USDT':{'realised_profit':0, 'margin':0, 'unrealised_profit':0, 
                                'total':initial_balance, 'leverage':0, 'fee':0,'maker_fee':0,'taker_fee':0}}
        for symbol in trade_symbols:
            self.account[symbol] = {'amount':0, 'hold_price':0, 'value':0, 'price':0, 'realised_profit':0,
                                    'margin':0, 'unrealised_profit':0,'fee':0}
            
    def Trade(self, symbol, direction, price, amount, msg='', maker=True):
        
        if (self.date and symbol == self.log) or self.log == 'all':
            print('%-26s%-15s%-5s%-10.8s%-8.6s %s'%(str(self.date)[:24], symbol, 'buy' if direction == 1 else 'sell', price, amount, msg))

        cover_amount = 0 if direction*self.account[symbol]['amount'] >=0 else min(abs(self.account[symbol]['amount']), amount)
        open_amount = amount - cover_amount
        if maker:
            self.account['USDT']['realised_profit'] -= price*amount*self.maker_fee #Deduct service charge
            self.account['USDT']['maker_fee'] += price*amount*self.maker_fee
            self.account['USDT']['fee'] += price*amount*self.maker_fee
            self.account[symbol]['fee'] += price*amount*self.maker_fee
        else:
            self.account['USDT']['realised_profit'] -= price*amount*self.taker_fee #Deduct service charge
            self.account['USDT']['taker_fee'] += price*amount*self.taker_fee
            self.account['USDT']['fee'] += price*amount*self.taker_fee
            self.account[symbol]['fee'] += price*amount*self.taker_fee

        
        
        if cover_amount > 0: #Close the position first
            self.account['USDT']['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount  #Profit
            self.account['USDT']['margin'] -= cover_amount*self.account[symbol]['hold_price']/self.leverage #Release margin
            
            self.account[symbol]['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount
            self.account[symbol]['amount'] -= -direction*cover_amount
            self.account[symbol]['margin'] -=  cover_amount*self.account[symbol]['hold_price']/self.leverage
            self.account[symbol]['hold_price'] = 0 if self.account[symbol]['amount'] == 0 else self.account[symbol]['hold_price']
            
        if open_amount > 0:
            total_cost = self.account[symbol]['hold_price']*direction*self.account[symbol]['amount'] + price*open_amount
            total_amount = direction*self.account[symbol]['amount']+open_amount
            
            self.account['USDT']['margin'] +=  open_amount*price/self.leverage            
            self.account[symbol]['hold_price'] = total_cost/total_amount
            self.account[symbol]['amount'] += direction*open_amount
            self.account[symbol]['margin'] +=  open_amount*price/self.leverage
            
        self.account[symbol]['unrealised_profit'] = (price - self.account[symbol]['hold_price'])*self.account[symbol]['amount']
        self.account[symbol]['price'] = price
        self.account[symbol]['value'] = abs(self.account[symbol]['amount'])*price
        
    
    def Buy(self, symbol, price, amount, msg='', maker=False):
        self.Trade(symbol, 1, price, amount, msg, maker)
        
    def Sell(self, symbol, price, amount, msg='', maker=False):
        self.Trade(symbol, -1, price, amount, msg,maker)
        

    def Update(self, date, symbols, close_price): #Update the assets
        self.date = date
        self.close = close_price
        self.account['USDT']['unrealised_profit'] = 0
        for symbol in symbols:
            self.account[symbol]['unrealised_profit'] = (close_price[symbol] - self.account[symbol]['hold_price'])*self.account[symbol]['amount']
            self.account[symbol]['price'] = close_price[symbol]
            self.account[symbol]['value'] = abs(self.account[symbol]['amount'])*close_price[symbol]
            
            self.account['USDT']['unrealised_profit'] += self.account[symbol]['unrealised_profit']
        self.account['USDT']['total'] = round(self.account['USDT']['realised_profit'] + self.initial_balance + self.account['USDT']['unrealised_profit'],6)
        self.account['USDT']['leverage'] = round(self.account['USDT']['margin']*self.leverage/self.account['USDT']['total'],4)

Dalam [ ]:


Berkaitan

Lebih banyak