Die Ressourcen sind geladen. Beförderung...

Die Kryptowährungs-Paarungsstrategie wird weiter erläutert

Schriftsteller:Das Gras, Erstellt: 2024-07-05 16:23:42, aktualisiert: 2024-07-12 09:19:11

img

Die Kryptowährungs-Paarungsstrategie wird weiter erläutert

Vorwort

Vor kurzem sah ich in dem Quantifizierungsjournal des Buo, dass man mit negativen Korrelationen handeln kann, um einen Gewinn zu erzielen. Digitale Währungen sind im Wesentlichen positiv korreliert, nur wenige sind negativ korreliert. Es gibt oft spezielle Märkte, wie zum Beispiel die MEME-Münzen, die in der Vergangenheit völlig unabhängig waren.

Der Kryptowährungspaarhandel ist eine auf statistischem Gewinn basierende Handelsstrategie, bei der Profit aus der Preisdifferenz erzielt wird, indem gleichzeitig zwei stark verknüpfte Kryptowährungspermanente gekauft und verkauft werden. In diesem Artikel werden die Grundsätze, die Gewinnmechanismen, die Methoden zur Auswahl von Münzen, die potenziellen Risiken und die Möglichkeiten zur Verbesserung dieser Methode und einige praktische Python-Codebeispiele beschrieben.

Die Strategie

Die Pairing-Trading-Strategie beruht auf der historischen Korrelation zwischen den Preisen der beiden digitalen Währungen. Wenn die Preise der beiden Währungen stark korrelieren, sind ihre Kursbewegungen weitgehend synchronisiert. Wenn zu einem bestimmten Zeitpunkt eine signifikante Abweichung des Preisverhältnisses zwischen den beiden auftritt, kann dies als eine temporäre Abweichung angesehen werden, bei der die Preise zu normalen Niveaus zurückkehren.

Nehmen wir an, dass die Währungen A und B eine höhere Preisverknüpfung aufweisen. Zu einem bestimmten Zeitpunkt ist der durchschnittliche Wert der A/B-Preisquote 1. Wenn die A/B-Preisquote zu einem bestimmten Zeitpunkt von mehr als 0.001 abweicht, also mehr als 1.001, kann der Handel in folgender Weise durchgeführt werden:

Der Schlüssel zum Gewinn liegt in der Differenzgewinnung, wenn der Preis abweicht und wieder normal wird. Da der Preis abweicht, ist es normalerweise kurzfristig.

Bereitstellung der Daten

Einführung der entsprechenden Bibliothek

Diese Codes können direkt genutzt werden, vorzugsweise durch das Herunterladen von Anancoda und Debugging in einem Jupyer Notebook.

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

Erhalten Sie alle Transaktionspaare.

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) # 获取所有的正在交易的交易对

Funktionen zum Herunterladen von K-Linien

Die Hauptfunktion der GetKlines-Funktion ist es, historische K-Linien-Daten zu bestimmten Transaktionen auf dauerhafte Verträge von Bitcoin-Börsen zu erhalten und diese Daten in einem Pandas-Datensatz zu speichern. Die K-Linien-Daten enthalten Informationen wie Öffnungspreis, Höchstpreis, Mindestpreis, Schließpreis, Volumen der Transaktionen. Diesmal verwenden wir hauptsächlich Daten zum Schließpreis.

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ß und nur für die letzten 3 Monate wurden K-Stunden-Liniendaten für schnelleres Herunterladen erhalten.

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')

Wiederholungsmaschine

Definition eines Exchange-Objekts für die nächste Nachprüfung

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)

Relevanz-Analyse für die Auswahl der Währungen

Die Korrelationsrechnung ist eine Methode in der Statistik, die verwendet wird, um die lineare Beziehung zwischen zwei Variablen zu messen. Die am häufigsten verwendeten Korrelationsrechnungsmethoden sind die Pearson-Korrelationskoeffizienten. Hier sind die Grundsätze, Formeln und Implementierungsmethoden für die Korrelationsrechnung.

  • 1Bezeichnet eine vollständig positive Korrelation, wobei die beiden Variablen stets synchron verändert werden. Wenn eine Variable zunimmt, steigt die andere Variable proportional. Je näher man 1 ist, desto stärker ist die Korrelation.
  • -1Beide Variablen sind immer umgekehrt verändert. Je näher man -1 steht, desto stärker ist die negative Korrelation.
  • 0Das bedeutet, dass es keine lineare Beziehung zwischen den beiden Variablen gibt.

Die Pearson-Relationschaftskoeffizienten werden durch die Berechnung des Koeffizientenunterschieds und des Standardunterschieds der beiden Variablen ermittelt.

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

Sie sind:

  • ( \rho_{X,Y}) ist die Pearson-Relative der Variablen (X) und (Y).
  • (\text{cov}(X,Y) ist die Koeffizientdifferenz von (X) und (Y).
  • (\sigma_X) und (\sigma_Y) sind die Standardabweichungen von (X) und (Y) bzw.;

Natürlich kann man mit Hilfe von Python 1-Zeile Code die Relevanz aller Währungen berechnen, ohne sich so sehr darum zu kümmern, wie sie berechnet wird. Wie die Relativitätsthermographie zeigt, ist die Vertretung in Rot positiv relevant, die Vertretung in Blau negativ relevant, und je tiefer die Farben sind, desto stärker ist die Relevanz.

img

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

Nach Relevanz wurden die Top-20 der relevantesten Währungspaare ausgewählt.

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:

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)

Nachprüfen

Der spezifische Rückrufcode ist folgender: Die Hauptbeobachtung der Demonstrationsstrategie ist der Preisverhältnis der beiden Kryptowährungen (IOTA und ZIL) und die Transaktionen werden nach Veränderungen dieses Verhältnisses durchgeführt. Die spezifischen Schritte sind folgende:

  1. Einführung

    • Definition von Transaktionspaaren (pair_a = IOTA-Paare, pair_b = ZIL-Paare)
    • Erstellen eines AustauschobjektseDer Anfangsbetrag beträgt 10.000 US-Dollar und die Transaktionsgebühr beträgt 0,02%.
    • Berechnung des anfänglichen Durchschnittspreisanteilsavg
    • Setzen Sie einen anfänglichen Transaktionswertvalue = 1000
  2. Iderative Bearbeitung von Preisdaten

    • Preise zu jedem Zeitpunktdf_close
    • Berechnung der Abweichung des aktuellen Preisanteils vom Durchschnittdiff
    • Transaktionswert nach Abweichung berechnetaim_valueFür jede Abweichung von 0.01 wird ein Wert gehandelt.
    • Wenn die Abweichungen zu groß sind, dann verkaufen Sie.pair_aund kaufenpair_bSie ist ein guter Freund.
    • Wenn die Abweichung zu klein ist, dann kaufen Sie.pair_aund verkaufenpair_bSie ist ein guter Freund.
  3. Anpassung der Durchschnitte

    • Das durchschnittliche Preisverhältnis aktualisiertavgDer Preis wird von den Kunden angezeigt, um den aktuellen Preisverhältnis zu reflektieren.
  4. Akten und Aufzeichnungen aktualisieren

    • Aktien- und Bilanzinformationen für Börsenkonten werden aktualisiert.
    • Erfasst den Kontozustand für jeden Schritt (Gesamtvermögen, Halten, Transaktionsgebühren, Multi- und Leerpositionen) bisres_list
  5. Ausgabe der Ergebnisse

    • Wir werdenres_listUmgewandelt in einen DatenschaltflächenresDas ist ein großes Problem, das wir uns stellen müssen, um es zu analysieren und zu zeigen.
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);

Es wurden insgesamt vier Gruppen von Währungen getestet, und das Ergebnis ist relativ ideal. Die Berechnung der aktuellen Korrelation wird mit Zukunftsdaten durchgeführt, so dass sie nicht sehr genau ist.

img

Potenzielle Risiken und Verbesserungsmöglichkeiten

Obwohl die Pairing-Handelsstrategie theoretisch profitabel ist, bestehen in der Praxis Risiken: Die Wechselbeziehungen zwischen den Währungen können sich mit der Zeit ändern und die Strategie versagen; bei extremen Marktbedingungen können die Preisverzerrungen sich verschärfen und zu größeren Verlusten führen; die geringe Liquidität bestimmter Währungen kann dazu führen, dass die Transaktionen schwierig sind oder die Kosten steigen; die Aufwandsgebühren, die durch häufige Transaktionen entstehen, können die Gewinne erodieren.

Um Risiken zu reduzieren und die Stabilität der Strategie zu verbessern, können folgende Verbesserungsmaßnahmen in Betracht gezogen werden: regelmäßige Umrechnung der Korrelation zwischen den Währungen, rechtzeitige Anpassung der Paare; Einstellung von Stop-Loss und Stop-Spotpunkten, um den maximalen Verlust eines einzelnen Handels zu kontrollieren; gleichzeitige Handel von mehreren Währungspaaren, um das Risiko zu verteilen.

Schlussfolgerung

Die Kryptowährungspaarungs-Handelsstrategie erzielt einen Gewinn, indem sie die Korrelation der Preise der Währungen nutzt, um bei einer Abweichung der Preise zu profitieren. Die Strategie hat eine hohe theoretische Durchführbarkeit. Ein einfacher, realer Strategie-Sourcecode basierend auf der Strategie wird dann veröffentlicht.


Mehr

77924998Was ist mit den Quellen, die es wert sind?

Weizen 888Zhang, der Chef der Überstunden - Ha-ha-ha!