Baru-baru ini, Binance futures meluncurkan
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
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.
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.
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]:
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]:
Di [15]:
# Price difference of next quarter - perpetual
(df['BTCUSD_201225']-df['BTCUSD_PERP']).dropna().plot(figsize=(15,6),grid=True);
Keluar[15]:
Di [16]:
# Price difference of current quarter - perpetual
(df['BTCUSD_200925']-df['BTCUSD_PERP']).dropna().plot(figsize=(15,6),grid=True);
Keluar[16]:
Di [17]:
# Price difference of next quarter - current quarter
(df['BTCUSD_201225']-df['BTCUSD_200925']).dropna().plot(figsize=(15,6),grid=True);
Keluar[17]:
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]:
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 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]:
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]:
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]:
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
Jika komisi adalah 0,03%, hasil backtest BTC adalah sebagai berikut:
Hasil backtest dari ETH:
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.
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 [ ]: