3
konzentrieren Sie sich auf
1444
Anhänger

Detaillierte Erklärung der Handelsstrategie für digitale Währungspaare

Erstellt in: 2024-07-05 16:23:42, aktualisiert am: 2024-11-05 17:42:06
comments   3
hits   5800

Detaillierte Erklärung der Handelsstrategie für digitale Währungspaare

Detaillierte Erklärung der Handelsstrategie für digitale Währungspaare

Einführung

Kürzlich habe ich Buus quantitatives Tagebuch gesehen, in dem erwähnt wurde, dass man negativ korrelierte Währungen zur Auswahl von Währungen verwenden und Positionen eröffnen kann, um auf der Grundlage von Preisunterschieden Gewinne zu erzielen. Digitale Währungen sind grundsätzlich positiv korreliert, und nur wenige Währungen sind negativ korreliert. Sie haben oft besondere Marktbedingungen, wie beispielsweise die unabhängigen Marktbedingungen der MEME-Münze vor einiger Zeit, die dem Trend des Marktes überhaupt nicht folgten. Herausfiltern und bleiben Sie auch nach dem Durchbruch noch lange auf diesen Währungen, mit dieser Methode können unter bestimmten Marktbedingungen Gewinne erzielt werden. Die gängigste Methode im Bereich des quantitativen Handels ist jedoch die Verwendung einer positiven Korrelation für den Paarhandel. In diesem Artikel wird diese Strategie kurz vorgestellt.

Beim Handel mit Kryptowährungspaaren handelt es sich um eine auf statistischer Arbitrage basierende Handelsstrategie, die darauf abzielt, durch den gleichzeitigen Kauf und Verkauf von zwei zeitlich unbefristeten Kontrakten mit hoher Korrelation zwischen zwei Kryptowährungen Gewinne aus Preisabweichungen zu erzielen. Dieser Artikel stellt die Grundsätze der Strategie, den Gewinnmechanismus, die Methode zur Währungsprüfung, potenzielle Risiken und Verbesserungsmöglichkeiten vor und bietet einige praktische Python-Codebeispiele.

Strategieprinzip

Paarhandelsstrategien basieren auf der historischen Korrelation zwischen den Preisen zweier Kryptowährungen. Wenn zwei Währungen stark korreliert sind, bewegen sich ihre Preise ungefähr synchron. Weicht das Preisverhältnis zwischen den beiden zu einem bestimmten Zeitpunkt erheblich ab, kann davon ausgegangen werden, dass es sich um eine vorübergehende Anomalie handelt und die Preise tendenziell wieder auf ein normales Niveau zurückkehren. Der Markt für digitale Währungen ist stark vernetzt. Wenn eine wichtige digitale Währung (wie Bitcoin) erheblichen Schwankungen unterliegt, löst dies normalerweise eine Kettenreaktion unter anderen digitalen Währungen aus. Einige Währungen weisen möglicherweise eine sehr offensichtliche positive Korrelation auf, und diese Korrelation kann auch anhalten, weil sie zu denselben Investmentinstituten, denselben Market Makern und demselben Kurs gehören. Einige Währungen sind negativ korreliert, es gibt jedoch weniger negativ korrelierte Währungen, und da sie alle vom allgemeinen Markttrend beeinflusst werden, zeigen sie häufig konsistente Markttrends.

Nehmen wir an, dass Münze A und Münze B eine hohe Preiskorrelation aufweisen. Zu einem bestimmten Zeitpunkt beträgt der Durchschnittswert des A/B-Preisverhältnisses 1. Wenn das Preisverhältnis A/B zu einem bestimmten Zeitpunkt um mehr als 0,001, also mehr als 1,001, vom Anstieg abweicht, können Sie auf folgende Weise handeln: Öffnen Sie eine Long-Position auf B und eine Short-Position auf A. . Im Gegenteil, wenn das A/B-Preisverhältnis niedriger als 0,999 ist: Eröffnen Sie eine Long-Position auf A und eine Short-Position auf B.

Der Schlüssel zur Rentabilität liegt in den Preisdifferenzgewinnen, die sich ergeben, wenn die Preise abweichen und sich wieder normalisieren. Da Preisabweichungen in der Regel nur von kurzer Dauer sind, können Händler ihre Positionen schließen, wenn die Preise zum Mittelwert zurückkehren, und von der Differenz profitieren.

Vorbereiten der Daten

Importieren Sie die entsprechende Bibliothek

Diese Codes können direkt verwendet werden, am besten laden Sie jedoch Anancoda herunter und debuggen es in einem Jupyer-Notebook. Enthält direkt Pakete für häufig verwendete Datenanalysen.

import requests
from datetime import date,datetime
import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import requests, zipfile, io
%matplotlib inline

Alle gehandelten Handelspaare abrufen

Info = requests.get('https://fapi.binance.com/fapi/v1/exchangeInfo')
b_symbols = [s['symbol'] for s in Info.json()['symbols'] if s['contractType'] == 'PERPETUAL' and s['status'] == 'TRADING' and s['quoteAsset'] == 'USDT']
b_symbols = list(filter(lambda x: x[-4:] == 'USDT', [s.split('_')[0] for s in b_symbols]))
b_symbols = [x[:-4] for x in b_symbols]
print(b_symbols) # 获取所有的正在交易的交易对

K-Line-Funktion herunterladen

Die Hauptfunktion der GetKlines-Funktion besteht darin, die historischen K-Line-Daten des unbefristeten Vertrags des angegebenen Handelspaares von der Binance-Börse abzurufen und diese Daten in einem Pandas DataFrame zu speichern. Zu den K-Line-Daten zählen Eröffnungskurs, Höchstkurs, Tiefstkurs, Schlusskurs, Handelsvolumen und weitere Informationen. Dieses Mal verwenden wir hauptsächlich Schlusskursdaten.

def GetKlines(symbol='BTCUSDT',start='2020-8-10',end='2024-7-01',period='1h',base='fapi',v = 'v1'):
    Klines = []
    start_time = int(time.mktime(datetime.strptime(start, "%Y-%m-%d").timetuple()))*1000 + 8*60*60*1000
    end_time =  min(int(time.mktime(datetime.strptime(end, "%Y-%m-%d").timetuple()))*1000 + 8*60*60*1000,time.time()*1000)
    intervel_map = {'m':60*1000,'h':60*60*1000,'d':24*60*60*1000}
    while start_time < end_time:
        time.sleep(0.3)
        mid_time = start_time+1000*int(period[:-1])*intervel_map[period[-1]]
        url = 'https://'+base+'.binance.com/'+base+'/'+v+'/klines?symbol=%s&interval=%s&startTime=%s&endTime=%s&limit=1000'%(symbol,period,start_time,mid_time)
        res = requests.get(url)
        res_list = res.json()
        if type(res_list) == list and len(res_list) > 0:
            start_time = res_list[-1][0]+int(period[:-1])*intervel_map[period[-1]]
            Klines += res_list
        if type(res_list) == list and len(res_list) == 0:
            start_time = start_time+1000*int(period[:-1])*intervel_map[period[-1]]
        if mid_time >= end_time:
            break
    df = pd.DataFrame(Klines,columns=['time','open','high','low','close','amount','end_time','volume','count','buy_amount','buy_volume','null']).astype('float')
    df.index = pd.to_datetime(df.time,unit='ms')
    return df

Daten herunterladen

Die Datenmenge ist relativ groß. Um den Download zu beschleunigen, wurden nur die stündlichen K-Line-Daten der letzten drei Monate abgerufen. df_close enthält Schlusskursdaten für alle Währungen

start_date = '2024-04-01'
end_date   = '2024-07-05'
period = '1h'
df_dict = {}

for symbol in b_symbols:   
    print(symbol)
    if symbol in df_dict.keys():
        continue
    df_s = GetKlines(symbol=symbol+'USDT',start=start_date,end=end_date,period=period)
    if not df_s.empty:
        df_dict[symbol] = df_s
df_close = pd.DataFrame(index=pd.date_range(start=start_date, end=end_date, freq=period),columns=df_dict.keys())
for symbol in symbols:
    df_close[symbol] = df_dict[symbol].close
df_close = df_close.dropna(how='all')

Backtesting-Engine

Definiert ein Exchange-Objekt für den folgenden Backtest

class Exchange:
    def __init__(self, trade_symbols, fee=0.0002, initial_balance=10000):
        self.initial_balance = initial_balance #初始的资产
        self.fee = fee
        self.trade_symbols = trade_symbols
        self.account = {'USDT':{'realised_profit':0, 'unrealised_profit':0, 'total':initial_balance,
                                'fee':0, 'leverage':0, 'hold':0, 'long':0, 'short':0}}
        for symbol in trade_symbols:
            self.account[symbol] = {'amount':0, 'hold_price':0, 'value':0, 'price':0, 'realised_profit':0,'unrealised_profit':0,'fee':0}
            
    def Trade(self, symbol, direction, price, amount):
        cover_amount = 0 if direction*self.account[symbol]['amount'] >=0 else min(abs(self.account[symbol]['amount']), amount)
        open_amount = amount - cover_amount
        self.account['USDT']['realised_profit'] -= price*amount*self.fee #扣除手续费
        self.account['USDT']['fee'] += price*amount*self.fee
        self.account[symbol]['fee'] += price*amount*self.fee
        if cover_amount > 0: #先平仓
            self.account['USDT']['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount  #利润
            self.account[symbol]['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount
            self.account[symbol]['amount'] -= -direction*cover_amount
            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[symbol]['hold_price'] = total_cost/total_amount
            self.account[symbol]['amount'] += direction*open_amount      
    
    def Buy(self, symbol, price, amount):
        self.Trade(symbol, 1, price, amount)
        
    def Sell(self, symbol, price, amount):
        self.Trade(symbol, -1, price, amount)
        
    def Update(self, close_price): #对资产进行更新
        self.account['USDT']['unrealised_profit'] = 0
        self.account['USDT']['hold'] = 0
        self.account['USDT']['long'] = 0
        self.account['USDT']['short'] = 0
        for symbol in self.trade_symbols:
            if not np.isnan(close_price[symbol]):
                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'] = self.account[symbol]['amount']*close_price[symbol]
                if self.account[symbol]['amount'] > 0:
                    self.account['USDT']['long'] += self.account[symbol]['value']
                if self.account[symbol]['amount'] < 0:
                    self.account['USDT']['short'] += self.account[symbol]['value']
                self.account['USDT']['hold'] += abs(self.account[symbol]['value'])
                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']['hold']/self.account['USDT']['total'],3)

Korrelationsanalyse zum Filtern von Währungen

Die Korrelationsrechnung ist ein Verfahren der Statistik, mit dem der lineare Zusammenhang zwischen zwei Variablen gemessen wird. Die am häufigsten verwendete Methode zur Korrelationsberechnung ist der Korrelationskoeffizient nach Pearson. Nachfolgend finden Sie die Prinzipien, Formeln und Implementierungsmethoden zur Korrelationsberechnung. Der Korrelationskoeffizient nach Pearson dient zur Messung der linearen Beziehung zwischen zwei Variablen und sein Wertebereich liegt zwischen -1 und 1:

  • 1 Zeigt eine perfekte positive Korrelation an, bei der sich die beiden Variablen immer synchron ändern. Wenn eine Variable zunimmt, nimmt auch die andere Variable proportional zu. Je näher der Wert bei 1 liegt, desto stärker ist die Korrelation.
  • -1 Zeigt eine perfekte negative Korrelation an, bei der sich die beiden Variablen immer in entgegengesetzte Richtungen ändern. Je näher der Wert bei -1 liegt, desto stärker ist die negative Korrelation.
  • 0 Zeigt an, dass keine lineare Korrelation vorliegt; zwischen den beiden Variablen besteht keine geradlinige Beziehung.

Der Pearson-Korrelationskoeffizient bestimmt die Korrelation zwischen zwei Variablen, indem er ihre Kovarianz und Standardabweichung berechnet. Die Formel lautet wie folgt:

[ \rho_{X,Y} = \frac{\text{cov}(X,Y)}{\sigma_X \sigma_Y} ]

In:

  • ( \rho_{X,Y} ) ist eine Variable( X ) Und ( Y ) Der Pearson-Korrelationskoeffizient.
  • ( \text{cov}(X,Y) ) Ja ( X ) Und ( Y ) Die Kovarianz von .
  • ( \sigma_X ) Und ( \sigma_Y ) Sie sind( X ) Und ( Y ) Die Standardabweichung von .

Über die Berechnung müssen Sie sich natürlich keine großen Gedanken machen. Sie können die Korrelation aller Währungen mit nur einer Zeile Python-Code berechnen. Die Abbildung zeigt eine Korrelations-Heatmap. Rot steht für positive Korrelation, Blau für negative Korrelation und je dunkler die Farbe, desto stärker die Korrelation. Es ist ersichtlich, dass große Bereiche dunkelrot sind, was bedeutet, dass die positive Korrelation der digitalen Währung sehr stark ist.

Detaillierte Erklärung der Handelsstrategie für digitale Währungspaare

import seaborn as sns
corr = df_close.corr()
plt.figure(figsize=(20, 20))
sns.heatmap(corr, annot=False, cmap='coolwarm', vmin=-1, vmax=1)
plt.title('Correlation Heatmap of Cryptocurrency Closing Prices', fontsize=20);

Basierend auf der Korrelation werden die 20 relevantesten Währungspaare ausgewählt. Die Ergebnisse sind wie folgt. Ihre Korrelationen sind sehr stark, alle über 0,99.

MANA     SAND     0.996562
ICX      ZIL      0.996000
STORJ    FLOW     0.994193
FLOW     SXP      0.993861
STORJ    SXP      0.993822
IOTA     ZIL      0.993204
         SAND     0.993095
KAVA     SAND     0.992303
ZIL      SXP      0.992285
         SAND     0.992103
DYDX     ZIL      0.992053
DENT     REEF     0.991789
RDNT     MANTA    0.991690
STMX     STORJ    0.991222
BIGTIME  ACE      0.990987
RDNT     HOOK     0.990718
IOST     GAS      0.990643
ZIL      HOOK     0.990576
MATIC    FLOW     0.990564
MANTA    HOOK     0.990563

Der entsprechende Code lautet wie folgt:

corr_pairs = corr.unstack()

# 移除自身相关性(即对角线上的值)
corr_pairs = corr_pairs[corr_pairs != 1]

sorted_corr_pairs = corr_pairs.sort_values(kind="quicksort")

# 提取最相关和最不相关的前20个币种对
most_correlated = sorted_corr_pairs.tail(40)[::-2]

print("最相关的前20个币种对:")
print(most_correlated)

Backtesting-Verifizierung

Der spezifische Backtest-Code lautet wie folgt. Die Demo-Strategie konzentriert sich auf die Beobachtung des Preisverhältnisses zweier Kryptowährungen (IOTA und ZIL) und den Handel basierend auf Änderungen dieses Verhältnisses. Die einzelnen Schritte sind wie folgt:

  1. Initialisierung

    • Definieren Sie Handelspaare (pair_a = ‚IOTA‘, pair_b = ‚ZIL‘).
    • Erstellen eines Austauschobjektse, der Anfangssaldo beträgt 10.000 $ und die Transaktionsgebühr beträgt 0,02 %.
    • Berechnung des anfänglichen Durchschnittspreisverhältnissesavg
    • Legen Sie einen anfänglichen Transaktionswert festvalue = 1000
  2. Preisdaten iterativ verarbeiten

    • Durchlaufen Sie die Preisdaten zu jedem Zeitpunktdf_close
    • Berechnet die Abweichung des aktuellen Preisverhältnisses vom Mittelwertdiff
    • Berechnen Sie den Zieltransaktionswert basierend auf der Abweichungaim_value, für jede Abweichung von 0,01 wird ein Wert gehandelt. Und entscheiden Sie auf Basis der aktuellen Kontopositionen und Preisbedingungen über Kauf- und Verkaufstransaktionen.
    • Wenn die Abweichung zu groß ist, führen Sie einen Verkauf durchpair_a und kaufenpair_b arbeiten.
    • Wenn die Abweichung zu gering ist, führen Sie einen Kauf auspair_a und verkaufenpair_b arbeiten.
  3. Angepasster Mittelwert

    • Aktualisiertes durchschnittliches Preisverhältnisavg, um das aktuelle Preisverhältnis widerzuspiegeln.
  4. Aktualisieren von Konten und Datensätzen

    • Aktualisieren Sie die Positions- und Saldeninformationen des Börsenkontos.
    • Notieren Sie den Kontostatus bei jedem Schritt (Gesamtvermögen, Bestände, Transaktionsgebühren, Long- und Short-Positionen), umres_list
  5. Ergebnisausgabe

    • Wille res_list In Datenrahmen konvertierenres, zur weiteren Analyse und Präsentation.
pair_a = 'IOTA'
pair_b = "ZIL"
e = Exchange([pair_a,pair_b], fee=0.0002, initial_balance=10000) #Exchange定义放在评论区
res_list = []
index_list = []
avg = df_close[pair_a][0] / df_close[pair_b][0]
value = 1000
for idx, row in df_close.iterrows():
    diff = (row[pair_a] / row[pair_b] - avg)/avg
    aim_value = -value * diff / 0.01
    if -aim_value + e.account[pair_a]['amount']*row[pair_a] > 0.5*value:
        e.Sell(pair_a,row[pair_a],(-aim_value + e.account[pair_a]['amount']*row[pair_a])/row[pair_a])
        e.Buy(pair_b,row[pair_b],(-aim_value - e.account[pair_b]['amount']*row[pair_b])/row[pair_b])
    if -aim_value + e.account[pair_a]['amount']*row[pair_a]  < -0.5*value:
        e.Buy(pair_a, row[pair_a],(aim_value - e.account[pair_a]['amount']*row[pair_a])/row[pair_a])
        e.Sell(pair_b, row[pair_b],(aim_value + e.account[pair_b]['amount']*row[pair_b])/row[pair_b])
    avg = 0.99*avg + 0.01*row[pair_a] / row[pair_b]
    index_list.append(idx)
    e.Update(row)
    res_list.append([e.account['USDT']['total'],e.account['USDT']['hold'],
                         e.account['USDT']['fee'],e.account['USDT']['long'],e.account['USDT']['short']])
res = pd.DataFrame(data=res_list, columns=['total','hold', 'fee', 'long', 'short'],index = index_list)
res['total'].plot(grid=True);

Insgesamt wurden vier Währungsgruppen einem Backtesting unterzogen und die Ergebnisse waren relativ optimal. Die aktuellen Korrelationsberechnungen basieren auf zukünftigen Daten und sind daher nicht sehr präzise. Auch dieser Artikel unterteilt die Daten in zwei Teile, basierend auf der berechneten Korrelation im Vordergrund und den Backtesting-Transaktionen im Hintergrund. Die Ergebnisse waren etwas abweichend, aber immer noch ziemlich gut. Die Durchführung der Überprüfung bleibt dem Benutzer überlassen.

Detaillierte Erklärung der Handelsstrategie für digitale Währungspaare

Mögliche Risiken und Verbesserungsmöglichkeiten

Obwohl die Paarhandelsstrategie theoretisch profitabel sein kann, gibt es im tatsächlichen Betrieb immer noch einige Risiken: Die Korrelation zwischen den Währungen kann sich im Laufe der Zeit ändern, was zum Scheitern der Strategie führt. Unter extremen Marktbedingungen können die Preisabweichungen zunehmen, was zu großen Verlusten führt. Die geringe Liquidität bestimmter Währungen kann die Ausführung von Transaktionen erschweren oder die Kosten erhöhen; die durch häufige Transaktionen entstehenden Gebühren können die Gewinne schmälern.

Um das Risiko zu verringern und die Stabilität der Strategie zu verbessern, können die folgenden Verbesserungsmaßnahmen in Betracht gezogen werden: regelmäßige Neuberechnung der Korrelation zwischen Währungen und rechtzeitige Anpassung der Handelspaare; Festlegung von Stop-Loss- und Take-Profit-Punkten, um den maximalen Verlust einer einzelnen Transaktion zu kontrollieren; Handeln Sie mit mehreren Münzpaaren, um das Risiko zu streuen.

abschließend

Mit der Handelsstrategie für digitale Währungspaare werden Gewinne erzielt, indem die Korrelation zwischen Währungskursen ausgenutzt und bei abweichenden Kursen Arbitragegeschäfte durchgeführt werden. Diese Strategie hat eine hohe theoretische Machbarkeit. Ein einfacher Echtzeitstrategie-Quellcode basierend auf dieser Strategie wird später veröffentlicht. Wenn Sie weitere Fragen haben oder Bedarf für eine weitere Diskussion haben, können Sie sich gerne an uns wenden.