Baru-baru ini, niaga hadapan Binance melancarkan
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
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.
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.
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]:
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]:
Dalam [15]:
# Price difference of next quarter - perpetual
(df['BTCUSD_201225']-df['BTCUSD_PERP']).dropna().plot(figsize=(15,6),grid=True);
Keluar[15]:
Dalam [16]:
# Price difference of current quarter - perpetual
(df['BTCUSD_200925']-df['BTCUSD_PERP']).dropna().plot(figsize=(15,6),grid=True);
Keluar[16]:
Dalam [17]:
# Price difference of next quarter - current quarter
(df['BTCUSD_201225']-df['BTCUSD_200925']).dropna().plot(figsize=(15,6),grid=True);
Keluar[17]:
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]:
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]:
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]:
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]:
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]:
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.
Jika komisen adalah 0.03%, hasil ujian belakang BTC adalah seperti berikut:
Hasil backtest ETH:
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.
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 [ ]: