Les ressources ont été chargées... Je charge...

Les stratégies de paire de crypto-monnaie

Auteur:Le foin, Créé à: 2024-07-05 16:23:42, Mis à jour à: 2024-07-12 09:19:11

img

Les stratégies de paire de crypto-monnaie

Précédent

Récemment, nous avons vu des journaux quantifiés du Bureau mentionner qu'il est possible d'utiliser des monnaies à correlation négative pour effectuer des opérations sur des devises, en fonction des ruptures de prix. Les monnaies numériques sont essentiellement positives et négatives, et il y a souvent des marchés spéciaux, tels que les marchés indépendants des MEME, qui ne suivent pas du tout la tendance du grand tableau.

Le partage de crypto-monnaie est une stratégie de négociation basée sur le profit statistique, qui consiste à acheter et vendre simultanément deux contrats permanents de crypto-monnaie fortement corrélés afin de réaliser des bénéfices liés aux écarts de prix. Cet article explique en détail les principes de la stratégie, les mécanismes de profit, les méthodes de filtrage des espèces, les risques potentiels et les moyens d'améliorer, et fournit quelques exemples pratiques de code Python.

Les principes stratégiques

Les stratégies d'appariement dépendent de la corrélation historique entre les prix des deux monnaies numériques. Lorsque les prix des deux monnaies présentent une forte corrélation, leur évolution est en grande partie synchrone. Si, à un moment donné, le rapport des prix des deux monnaies se déplace de manière significative, il peut être considéré comme une anomalie temporaire, les prix tendant à revenir à leur niveau normal. Le marché des monnaies numériques est très dynamique et provoque généralement une réaction dynamique des autres monnaies numériques lorsque l'une des principales monnaies numériques (comme le Bitcoin) évolue fortement.

Supposons que les devises A et B aient une correlation de prix plus élevée. À un moment donné, la moyenne des ratios A/B est de 1. Si à un moment donné, la hausse des ratios A/B dépasse 0,001, c'est-à-dire supérieure à 1,001, alors les transactions peuvent être effectuées de la manière suivante: Opérer plus B, Opérer plus A. En revanche, lorsque le rapport de prix A/B est inférieur à 0,999, Opérer plus A, Opérer plus B.

La clé du profit réside dans le gain de la différence lorsque les prix deviennent normaux. Puisque les déviations sont généralement de courte durée, les traders peuvent faire une mise à l'échelle lorsque les prix reviennent à l'équilibre et en tirer profit.

Préparez les données

Introduisez une bibliothèque

Ces codes peuvent être utilisés directement, il est préférable de télécharger un Anancoda et de le déboguer dans un ordinateur portable Jupyer.

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

Obtenez toutes les paires de transactions en cours

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

Fonction de téléchargement de la ligne K

La fonctionnalité principale de GetKlines est d'obtenir des données historiques de la ligne K des transactions spécifiées sur les contrats permanents de l'échange Binance et de les stocker dans un cadre de données Panda. Les données de la ligne K comprennent des informations sur les prix d'ouverture, les prix les plus élevés, les prix les plus bas, les prix de clôture, les volumes de transactions. Cette fois, nous utilisons principalement les données sur les prix de clôture.

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

Télécharger les données

Les données sont assez volumineuses et pour un téléchargement plus rapide, seules les données de ligne K horaires des 3 derniers mois sont disponibles.

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

Moteur de retouche

Définir un objet Exchange pour la réévaluation ultérieure

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)

Analyse de la pertinence pour les devises sélectionnées

Le calcul de la corrélation est une méthode de statistique utilisée pour mesurer les relations linéaires entre deux variables. Le calcul de la corrélation le plus couramment utilisé est le calcul des coefficients de Pearson. Voici les principes, formules et méthodes de calcul de la corrélation.

  • 1Indique que les deux variables sont toujours liées en même temps. Lorsqu'une variable est augmentée, l'autre variable augmente également proportionnellement. Plus on est proche de 1, plus la relation est forte.
  • -1Les deux variables sont toujours inverses. Plus elles sont proches de -1, plus elles sont négatives.
  • 0Indique une corrélation sans fil et aucune relation linéaire entre les deux variables.

Les coefficients de Pearson sont déterminés en calculant l'écart de conjugaison et l'écart-type des deux variables.

Je ne sais pas si je peux le faire.

Parmi eux:

  • (\rho_{X,Y}) est le coefficient de Pearson des variables (X) et (Y)
  • (\text{cov}(X,Y) est la différence de cov de X et de Y.
  • (\sigma_X) et (\sigma_Y) sont respectivement les écarts standards de (X) et (Y).

Bien sûr, il n'est pas nécessaire de se soucier de la façon dont cela est calculé. Vous pouvez calculer la corrélation de toutes les pièces en utilisant une ligne de code Python.

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

Les 20 paires de devises les plus pertinentes ont été sélectionnées en fonction de leur pertinence. Les résultats sont les suivants:

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

Le code correspondant est le suivant:

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)

Vérification par réévaluation

Le code de réévaluation spécifique est le suivant. La stratégie de démonstration consiste principalement à observer le rapport entre les prix des deux crypto-monnaies (IOTA et ZIL) et à effectuer des transactions en fonction des changements de ce rapport. Les étapes spécifiques sont les suivantes:

  1. Initialement

    • Définition de la paire de transactions (pair_a = IOTA, pair_b = ZIL)
    • Créer un objet d'échangeeLe solde initial est de 10 000 $ et les frais de transaction sont de 0,02%;
    • Calcul du ratio de prix moyen initialavg
    • Définir une valeur de transaction initialevalue = 1000
  2. Traitement itératif des données de prix

    • Données sur les prix à chaque momentdf_close
    • Calculer la déviation du ratio des prix actuels par rapport à la moyennediff
    • La valeur des transactions est calculée en fonction de la déviationaim_valuePour chaque déviation de 0.01, une valeur est échangée. Les opérations d'achat et de vente sont décidées en fonction de la situation actuelle du compte et des prix.
    • Si la déviation est trop grande, exécutez la vente.pair_aet acheterpair_bJe ne peux pas le faire.
    • Si le décalage est trop faible, effectuer l'achatpair_aet vendupair_bJe ne peux pas le faire.
  3. Les moyennes ajustées

    • Mise à jour du ratio de prix moyenavgLes prix sont en hausse et les prix sont en hausse.
  4. Mettre à jour les comptes et enregistrements

    • Pour mettre à jour les informations sur les avoirs et le solde des comptes d'échange.
    • Enregistrez l'état des comptes à chaque étape (tous les actifs, les actifs détenus, les frais de transaction, les positions en bourse et en bourse) jusqu'à ce que vous ayez atteint un niveau de rentabilité.res_list
  5. Résultats

    • Je vaisres_listConvertissez en un cadre de donnéesresIl est également possible de consulter le site officiel de l'organisation pour une analyse plus approfondie et une démonstration.
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);

Le résultat est plutôt idéal. Le calcul de la corrélation actuelle est basé sur des données futures et n'est donc pas très précis. Cet article divise également les données en deux parties, selon la corrélation du calcul précédent et le résultat de la corrélation ultérieure.

img

Risques potentiels et améliorations

Bien que les stratégies de négociation de paires puissent être rentables en théorie, il existe des risques en pratique: les correlations entre les devises peuvent changer avec le temps et entraîner une défaillance de la stratégie; les écarts de prix peuvent s'intensifier dans des conditions de marché extrêmes, entraînant des pertes plus importantes; la liquidité faible de certaines devises peut rendre les transactions difficiles à exécuter ou coûteuses; les frais de traitement générés par des transactions fréquentes peuvent éroder les bénéfices.

Pour réduire les risques et améliorer la stabilité de la stratégie, les mesures d'amélioration suivantes peuvent être envisagées: recalculer régulièrement la corrélation entre les devises, ajuster les paires de transactions en temps opportun; mettre en place des points de stop-loss et de stop-loss pour contrôler les pertes maximales d'une seule transaction; négocier plusieurs paires de devises en même temps, afin de disperser les risques.

Conclusions

Une stratégie de trading de paire de devises numériques permet de réaliser des profits en exploitant la correlation entre les prix des devises et en opérant des opérations d'effet de levier lorsque les prix s'écartent. Cette stratégie a une plus grande faisabilité théorique. Un code source de stratégie simple basé sur la stratégie sera ensuite publié.


Plus de

77924998Cela vaut la peine d'être étudié.

Les haricots 888Le chef de l'équipe travaille plus de temps.