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 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.
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
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) # 获取所有的正在交易的交易对
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
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')
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)
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.
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:
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.
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)
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:
Initialement:
e
Le solde initial est de 10 000 $ et les frais de transaction sont de 0,02%;avg
。value = 1000
。Traitement itératif des données de prix:
df_close
。diff
。aim_value
Pour 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.pair_a
et acheterpair_b
Je ne peux pas le faire.pair_a
et vendupair_b
Je ne peux pas le faire.Les moyennes ajustées:
avg
Les prix sont en hausse et les prix sont en hausse.Mettre à jour les comptes et enregistrements:
res_list
。Résultats:
res_list
Convertissez en un cadre de donnéesres
Il 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.
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.
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é.
77924998Cela vaut la peine d'être étudié.
Les haricots 888Le chef de l'équipe travaille plus de temps.