Die Ressourcen sind geladen. Beförderung...

[Binance Championship] Binance Liefervertrag Strategie 3 - Schmetterling Absicherung

Schriftsteller:FMZ~Lydia, Erstellt: 2022-11-11 18:17:46, Aktualisiert: 2023-09-14 20:32:10

img

Vor kurzem startete Binance Futures die zweite Binance Championship (Adresse:https://www.binancezh.com/cn/futures/activity/anniversary-competition/129-38599440) Die offizielle FMZ Quant Plattform hat auch ein Team organisiert, das direkt durch Suche nach FMZ Quant gefunden werden kann. Derzeit sind es nur knapp mehr als 100 Personen. Willkommen, um sich uns anzuschließen. Danach können Sie den WeChat des Teamleiters hinzufügen: fmz_zhangchao, antworten Binance, und wir laden Sie ein, sich der WeChat-Gruppe anzuschließen.

Die Strategie, die für die Binance Championship vorbereitet wurde, ist die Schmetterlingssicherung des Liefervertrags. Dieser Artikel ist der Forschungsbericht der Strategie. Achtung: Strategien dienen nur zur Referenz. Sie können Ihre eigenen Ideen für die Optimierung auf dieser Grundlage vorlegen. Sie sind auch herzlich eingeladen zu teilen. Der Bericht kann direkt in der Forschungsumgebung der FMZ-Website verwendet werden (klicken Sie in der oberen rechten Ecke zum Herunterladen und laden Sie in der Analyze).

img

1. Strategische Gründe

Der Hedging muss eine stabile Preisdifferenz finden. Wenn die Preisdifferenz zu groß ist, kann man die Preisdifferenz auch abschneiden. Wenn die Preisdifferenz zu klein ist, geht man lang die Preisdifferenz. Wenn die Preisdifferenz zurückkehrt, um die Position zu schließen, verdient man die Preisdifferenz. Wenn die Futures und Spots abgeschirmt werden, wenn der Preis der nicht ausgelieferten Futures viel höher ist als der Spotpreis, kann man den Futures-Kontrakt kurz gehen und den Spotpreis lang gehen, um die Preisdifferenz zu kürzen. Es gibt auch intertemporalen Hedges von Verträgen mit unterschiedlichen Lieferzeiten, mit Futures und Spots Hedges, sie können auch lange Preisdifferenzen gehen. Futures und Spots und Cross-Futures sind gemeinsame Strategien mit heftigem Wettbewerb. Wenn es keinen Markt gibt, ist die Preisdifferenz relativ stabil. Obwohl es ein langfristiger Markt sein kann, gibt es nur wenige Möglichkeiten, und man sucht auch nach manuellen Operationen. Da es alle drei Differenzen

2. Grundsätze der Strategie

Die Binance-Währungsstandardkontrakte, wie BTC und ETH, haben drei Kontrakte gleichzeitig, nämlich perpetual BTCUSD_ PERP, BTCUSD_200925 des laufenden Quartals, BTCUSD_ 201225 des nächsten Quartals. Perpetual-Kontrakte können als Spots verwendet werden. Im Allgemeinen gibt es drei Preisdifferenzen zur Absicherung von zwei Kontrakte: aktuelles Quartal-perpetual, nächstes Quartal-perpetual und nächstes Quartal-aktuelles Quartal. Butterfly-Arbitrage erfordert drei Kontrakte. Der Unterschied ist (nächstes Quartal - aktuelles Quartal) - (aktuelles Quartal - perpetual), dh der Unterschied = nächstes Quartal + perpetual - 2 * aktuelles Quartal. Um den Unterschied zu verlängern, müssen Sie einen Long-Position-Kontrakt für das nächste Quartal und perpetual-Kontrakte eröffnen und zwei Short-Kontrakte für das aktuelle Quartal eröffnen.

3. Absicherung von Flächen

Ich habe die Daten von 5min K-Line von Binance vom 14. August bis zum 14. September durchsucht, die direkt gelesen werden können (aufgrund des Zeitunterschieds ist der zeitliche Unterschied 8h).

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

In [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)

Ausgeschaltet:

img

Zuerst werfen wir einen Blick auf die Preisunterschiede zwischen Bitcoin-Kontrakten. Am 17. August stieg der Preis von Bitcoin schnell um 500u. Im Allgemeinen war der ausgelieferte Vertrag im Vergleich zum Spotpreis zu einem Plus, und der Spotpreis stieg. Die Erwartung für die Zukunft wird optimistischer sein. Die Preisunterschiede zwischen dem nicht ausgelieferten Vertrag und der Perpetuität wird größer. Zum Beispiel wird die Preisunterschiede zwischen dem nächsten Quartal und der Perpetuität 700u betragen. Mit der Abnahme des Bitcoin-Preises im September werden sich die Erwartungen der Leute schnell verschlechtern, die Preisunterschiede zwischen dem nächsten Quartal und der Perpetuität fiel auf etwa 150u, und es gab fast keinen Preisunterschied zwischen dem aktuellen Quartal und der Perpetuität. Wenn die Absicherung zwischen dem nächsten Quartal und der Perpetuität durchgeführt wurde, könnte nur die Rückkehr des großen langfristigen Preises durchgeführt werden. Wenn die Differenz zwischen 400-600 August beschlossen wurde, im August durchgeführt zu werden, ist sie offensichtlich in einem Zust

In [18]:

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

Ausgeschaltet[1]:

img

In [15]:

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

Ausgeschaltet[1]:

img

In [16]:

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

Ausgeschaltet [1]:

img

In [17]:

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

Ausgeschaltet [1]:

img

Wie ändert sich die Preisdifferenz zu diesem Zeitpunkt? Wie aus der Abbildung unten zu sehen ist, ist die jüngste Preisdifferenz seit langem bei 100-200u stabil. Selbst der starke Rückgang Anfang September hat nicht viel beeinflusst, was uns viel Raum für wiederholte Arbitrage gibt.

Wenn der Spotpreis schwankt, spiegeln die beiden nicht abgelaufenen Kontrakte gleichzeitig die Erwartung der Zukunft wider. Der Prozess der Preisdifferenzreduktion kann diese Schwankung weitgehend ausgleichen, und die Performance ist relativ stabil.

In [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);

Ausgeschaltet[1]:

img

In [22]:

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

Außen [1]:

img

4. Strategie-Backtest

Um Zeit zu sparen (nur Faulheit), verwendet der Backtest immer noch die USDT-Standard-Engine der letzten Binance Championship-Strategie. Obwohl es einige Fehler geben kann, kann er auch das Problem erklären. Die Backtesting-Engine wird am Ende dieses Berichts platziert. Wenn Sie den Code ausführen, sollten Sie das Ende des Artikels sehen. Die Währungsstandardstrategie kann Hedging in Betracht ziehen, wenn Sie USDT verdienen möchten, und es ist nicht kompliziert.

Die Mittellinie der Preisdifferenz wird von der EMA verfolgt, und die Position wird durch das Gitter gesteuert, d.h. jedes Mal, wenn die Differenz geöffnet wird (z.B. 30), gehen Sie kurz N Aktien und umgekehrt. Wenn die Mittellinie der Preisdifferenz 100u beträgt, wenn die Preisdifferenz 90 beträgt, gehen Sie kurz 3 Aktien, und die Preisdifferenz wird 60, schließen Sie eine Aktie. Die Größe des Gitter ist ein wichtiger Parameter.

Hier sind die spezifischen BTC- und ETH-Backtest-Codes und -Ergebnisse. Die Leistung entspricht den Erwartungen. Da ETH und LINK eine größere Volatilität aufweisen und der Preisunterschied stabiler ist, ist die Leistung besser. Beachten Sie, dass die Servicegebühr hier 0,02%, und die Standard-VIP0-Nutzer-Servicegebühr in Binance 0,04%. Die Servicegebühr ist sehr wichtig, und die folgenden Kapitel werden sie analysieren.

In [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);

Außen [1]:

img

In [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);

Aus [59]:

img

In [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);

Ausgeschaltet[60]:

img

5.Kommissionsempfindlichkeit

Da 3 Verträge gleichzeitig betrieben werden müssen, sind 8 Servicegebühren erforderlich, um die Position nach der Eröffnung zu schließen, so dass die Servicegebühren einen großen Einfluss auf die Strategie haben.

img

Bei einer Provision von 0,03% sind die Ergebnisse des BTC-Backtests wie folgt:

img

Die Ergebnisse des Backtests von ETH:

img

Der Taker-Rate von vip0 für neue registrierte Benutzer beträgt 0,0004, 10% wird im ersten Monat der Einladung reduziert, 30% wird zurückgegeben und 10% wird für den BNB-Verbrauch reduziert. Somit beträgt die endgültige Bearbeitungsgebühr 0,0002268. Es wird auch eine direkte Belohnung für den jüngsten großen Transaktionsbetrag des Binance-Liefervertrags geben. Darüber hinaus kann ein Teil der Rechnung platziert und ein Teil der Rechnung entgegengenommen werden, und der endgültige Gesamtsatz kann auf 0,02 reduziert werden. Darüber hinaus diskutiert der FMZ-Beamte auch mit Binance über die Frage der Dienstleistungsrabattung.

Zusammenfassung

Der Zweck der Arbitrage ist es, einen stabilen Preisunterschied zu finden. Der Preisunterschied des Preisunterschieds ist stabiler. Daher ist der Schmetterlingsarbitrage viel weniger riskant als Cross-Periode und Future-Spot, und er kann auch manuell betrieben werden. Diese Strategie dient nur als Einführung. Bei der Erstellung im echten Bot müssen viele Fragen berücksichtigt werden.

In [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)

In [ ]:


Verwandt

Mehr