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

Penulis:Lydia, Dicipta: 2022-11-11 18:17:46, Dikemas kini: 2023-09-14 20:32:10

img

Baru-baru ini, niaga hadapan Binance melancarkan Binance Championship yang kedua (alamat:https://www.binancezh.com/cn/futures/activity/anniversary-competition/129-38599440FMZ Quant secara langsung. Pada masa ini, terdapat hanya lebih daripada 100 orang. Selamat datang untuk menyertai kami. Selepas itu, anda boleh menambah WeChat ketua pasukan: fmz_zhangchao, balas Binance, dan kami akan menjemput anda untuk menyertai kumpulan WeChat.

Strategi yang disediakan untuk Kejohanan Binance adalah lindung nilai kupu-kupu kontrak penghantaran. Artikel ini adalah laporan penyelidikan strategi. Perhatian: strategi hanya untuk rujukan. Anda boleh mengemukakan idea anda sendiri untuk pengoptimuman atas asas ini. Anda juga dialu-alukan untuk berkongsi. Laporan ini boleh digunakan di persekitaran penyelidikan laman web FMZ secara langsung (klik sudut kanan atas untuk memuat turun, dan muat naik di Analisis).

img

1. Sebab-sebab strategi

Hedging perlu mencari perbezaan harga yang stabil. Apabila perbezaan harga terlalu besar, pergi pendek perbezaan harga. Apabila perbezaan harga terlalu kecil, pergi panjang perbezaan harga. Apabila perbezaan harga kembali untuk menutup kedudukan, anda akan memperoleh perbezaan harga. Jika niaga hadapan dan tempat adalah lindung nilai, apabila harga niaga hadapan yang tidak dihantar jauh lebih tinggi daripada harga spot, anda boleh pergi pendek kontrak niaga hadapan dan pergi panjang harga spot untuk pendek perbezaan harga. Terdapat juga lindung nilai intertemporal kontrak dengan masa penghantaran yang berbeza, dengan niaga hadapan dan tempat lindung nilai, mereka juga boleh pergi panjang perbezaan harga. niaga hadapan dan tempat dan masa depan silang adalah strategi biasa dengan persaingan sengit. Apabila tidak ada pasaran, perbezaan harga agak stabil. Walaupun ia boleh menjadi pasaran jangka panjang, terdapat beberapa peluang, dan operasi manual juga sedang dilakukan. Oleh kerana mereka semua mempunyai perbezaan harga yang stabil, apabila terdapat tiga kontrak yang boleh menjadi subjek untuk perdagangan, ini juga dikenali sebagai arbitrage harga kupu-kupu.

2. Prinsip-prinsip strategi

Kontrak standard mata wang Binance, seperti BTC dan ETH, mempunyai tiga kontrak pada masa yang sama, iaitu, BTCUSD_ PERP kekal, BTCUSD_200925 suku semasa, BTCUSD_ 201225 suku seterusnya. Kontrak kekal boleh digunakan sebagai tempat. Secara umum, terdapat tiga perbezaan harga untuk lindung nilai dua kontrak: suku semasa kekal, suku seterusnya kekal, dan suku semasa seterusnya. Arbitraj kupu-kupu memerlukan tiga kontrak. Perbezaannya adalah (sekian suku - suku semasa) - (sekian suku semasa - kekal), iaitu, perbezaan = suku seterusnya + kekal - 2 * suku semasa. Untuk pergi panjang perbezaan harga, anda perlu membuka kontrak kedudukan panjang untuk kontrak suku berikutnya dan kontrak kekal, dan pergi dua kontrak pendek untuk suku semasa.

3. ruang lindung nilai

Saya telah merakam data 5min K-line Binance dari 14 Ogos hingga 14 September, yang boleh dibaca secara langsung (kerana perbezaan masa, perbezaan masa yang ditunjukkan adalah 8h).

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 perbezaan harga antara kontrak Bitcoin. Pada 17 Ogos, harga Bitcoin meningkat dengan cepat sebanyak 500u. Secara umum, kontrak yang dihantar adalah dengan premium berbanding dengan harga spot, dan harga spot meningkat. Harapan untuk masa depan akan lebih optimis. Perbezaan harga antara kontrak yang tidak dihantar dan keabadian akan menjadi lebih besar. Sebagai contoh, perbezaan harga antara suku berikutnya dan keabadian akan menjadi 700u. Dengan penurunan harga Bitcoin pada bulan September, harapan orang akan merosot dengan cepat, perbezaan harga antara suku berikutnya dan keabadian jatuh ke sekitar 150u, dan hampir tidak ada perbezaan harga antara suku semasa dan keabadian. Jika lindung nilai antara suku berikutnya dan keabadian dilakukan, hanya pengembalian harga jangka panjang yang besar boleh dilakukan. Jika perbezaan antara 400-600 Ogos telah diputuskan untuk dilakukan sekarang, jelas ia terkunci dalam keadaan.

Dalam [18]:

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

Keluar [1]:

img

Dalam [15]:

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

Keluar[15]:

img

Dalam [16]:

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

Keluar[16]:

img

Dalam [17]:

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

Keluar[17]:

img

Oleh itu, bagaimana perbezaan harga berubah pada masa ini? Seperti yang dapat dilihat dari gambar di bawah, perbezaan harga baru-baru ini telah stabil pada 100-200u untuk masa yang lama. Walaupun penurunan tajam pada awal September tidak memberi banyak kesan, memberi kita banyak ruang untuk arbitrage berulang. Pada masa ini, jika perbezaan harga jatuh ke 100u, tidak mengapa untuk pergi lama secara manual.

Apabila harga spot turun naik, kedua-dua kontrak yang tidak tamat tempoh mencerminkan jangkaan masa depan pada masa yang sama. Proses pengurangan perbezaan harga dapat mengimbangi turun naik ini hingga tahap yang besar, dan prestasi agak 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. Ujian belakang strategi

Untuk menjimatkan masa (hanya malas), backtest masih menggunakan enjin standard USDT dari strategi Kejohanan Binance terakhir. Walaupun mungkin ada beberapa kesilapan, ia juga dapat menjelaskan masalah ini. Enjin backtesting diletakkan di akhir laporan ini. Apabila menjalankan kod, anda harus melihat akhir artikel. Strategi standard mata wang boleh mempertimbangkan lindung nilai jika anda ingin memperoleh USDT, dan tidak rumit.

Garis pertengahan perbezaan harga dikesan oleh EMA, dan kedudukan dikawal oleh grid, iaitu setiap kali perbezaan dibuka (seperti 30), pergi pendek N saham, dan sebaliknya. Jika garis tengah perbezaan harga adalah 100u, apabila perbezaan harga adalah 90, pergi pendek 3 saham, dan perbezaan harga menjadi 60, menutup satu saham.

Berikut adalah kod dan hasil pengujian belakang BTC dan ETH tertentu. Prestasi adalah selaras dengan jangkaan. Kerana ETH dan LINK mempunyai turun naik yang lebih besar dan perbezaan harga lebih stabil, prestasi lebih baik. Perhatikan bahawa caj perkhidmatan di sini adalah 0.02%, dan caj perkhidmatan pemegang vip0 lalai di Binance adalah 0.04%.

Dalam [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

Dalam [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

Dalam [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.Rasa komisen

Oleh kerana 3 kontrak perlu dioperasikan pada masa yang sama, 8 caj perkhidmatan diperlukan untuk menutup kedudukan selepas pembukaan, jadi caj perkhidmatan mempunyai kesan yang besar terhadap strategi. Jika terdapat caj perkhidmatan sebanyak 0.01%, jurang antara grid perbezaan harga dapat dikurangkan lagi.

img

Jika komisen adalah 0.03%, hasil ujian belakang BTC adalah seperti berikut:

img

Hasil backtest ETH:

img

Kadar penerima vip0 untuk pengguna baru berdaftar adalah 0.0004, 10% akan dikurangkan pada bulan pertama dijemput, 30% akan dikembalikan, dan 10% akan dikurangkan untuk penggunaan BNB. Oleh itu, yuran pengendalian akhir adalah 0.0002268. Terdapat juga ganjaran langsung untuk jumlah transaksi besar kontrak penghantaran Binance baru-baru ini. Di samping itu, sebahagian bil boleh diletakkan dan sebahagian bil boleh diambil, dan kadar komprehensif akhir boleh dikurangkan menjadi 0.02%. Di samping itu, pegawai FMZ juga membincangkan isu diskaun caj perkhidmatan dengan Binance. Anda boleh menantikannya.

Ringkasan

Tujuan arbitraj adalah untuk mencari perbezaan harga yang stabil. Perbezaan harga perbezaan harga lebih stabil. Oleh itu, arbitraj rama-rama jauh lebih kurang berisiko daripada tempoh silang dan spot masa depan, dan ia juga boleh dikendalikan secara manual. Strategi ini hanya berfungsi sebagai pengenalan. Banyak isu perlu dipertimbangkan ketika menulis dalam bot sebenar. Selamat datang anda 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 lanjut