En la carga de los recursos... Cargando...

Estrategias de operaciones para el emparejamiento de monedas digitales

El autor:Las hierbas, Creado: 2024-07-05 16:23:42, Actualizado: 2024-07-12 09:19:11

img

Estrategias de operaciones para el emparejamiento de monedas digitales

Preámbulo

Recientemente, se ha visto en el diario de cuantificación de BUE la mención de que se puede operar con monedas con correlación negativa para obtener ganancias en función de la ruptura de la diferencia de precios. Las monedas digitales son básicamente positivas, negativas son pocas monedas, que a menudo tienen mercados especiales, como el mercado independiente de monedas MEME de hace un tiempo, que no siguen el movimiento del disco grande, seleccionan estas monedas, y después de la ruptura, hacen más, esta manera puede ser rentable en ciertas circunstancias.

La negociación de moneda digital es una estrategia de negociación basada en el beneficio estadístico, que consiste en comprar y vender simultáneamente dos contratos perpetuos de moneda digital altamente correlacionados para obtener ganancias por desviación de precios. Este artículo explica en detalle los principios de la estrategia, los mecanismos de ganancia, el método de selección de monedas, los riesgos potenciales y cómo mejorarlos, y ofrece algunos ejemplos prácticos de código Python.

Principios estratégicos

Las estrategias de negociación de emparejamiento dependen de la correlación histórica entre los precios de las dos monedas digitales. Cuando los precios de las dos monedas presentan una correlación fuerte, su movimiento de precios es prácticamente sincronizado. Si en un momento dado se producen desviaciones significativas en la relación de precios de las dos monedas, se puede considerar que es una anomalía temporal y que los precios tienden a volver a su nivel normal.

Supongamos que las monedas A y B tienen una alta correlación de precios. En un momento dado, el valor medio de la relación de precios A/B es de 1. Si en un momento dado, la relación de precios A/B se desvía más de 0.001, es decir, más de 1.001, entonces se puede negociar de la siguiente manera: abrir una posición con más de B, abrir una posición con menos de A. Por el contrario, cuando la relación de precios A/B es inferior a 0.999, abrir una posición con más de A, abrir una posición con menos de B.

La clave de la rentabilidad está en la ganancia de la diferencia cuando el precio se desvía a la normalidad. Dado que la desviación del precio suele ser breve, los operadores pueden estabilizarse cuando el precio vuelve a la media y obtener ganancias, ganando la diferencia.

Preparación de datos

Introducción de las bibliotecas correspondientes

Estos códigos se pueden usar directamente, lo mejor es descargar un Anancoda y deshacerlo en el notebook de 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

Obtener todos los pares de transacciones que están siendo negociados

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

Función de descarga de la línea K

La función principal de GetKlines es obtener datos históricos de la línea K de los contratos perpetuos de los intercambios binarios y almacenarlos en un DataFrame de Pandas. Los datos de la línea K incluyen información sobre el precio de apertura, el precio máximo, el precio mínimo, el precio de cierre, el volumen de transacciones. En este caso, usamos principalmente datos sobre el precio de cierre.

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

Descarga de datos

El volumen de datos es relativamente grande y sólo se obtienen datos de línea K de las últimas 3 horas para una descarga más rápida.

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

El motor de repetición

Define un objeto de Exchange para su siguiente revisión

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)

Análisis de correlación para seleccionar monedas

El cálculo de la correlación es un método en estadística para medir la relación lineal entre dos variables. El método de cálculo de la correlación más comúnmente utilizado es el coeficiente de Pearson. A continuación se presentan los principios, fórmulas y métodos de cálculo de la correlación.

  • 1Indica que las dos variables están siempre en cambio simultáneo. Cuando una variable aumenta, la otra variable también aumenta proporcionalmente. Cuanto más cerca de 1 se encuentre, más fuerte será la correlación.
  • -1Indica una correlación totalmente negativa, y las dos variables siempre cambian en sentido inverso. Cuanto más cerca de -1 se encuentre, mayor será la correlación negativa.
  • 0Indica la correlación inalámbrica y no hay una relación lineal entre las dos variables.

Los coeficientes de Pearson determinan la correlación de las dos variables mediante el cálculo de la diferencia de coincidencia y la diferencia estándar. La fórmula es la siguiente:

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

Algunos de ellos son:

  • ( \rho_{X,Y}) es el coeficiente de Pearson de las variables (X) y (Y).
  • (\text{cov}(X,Y) es el diferencial de copartículas de X y Y.
  • (\sigma_X) y (\sigma_Y) son las diferencias estándar de (X) y (Y), respectivamente.

Por supuesto, sin tener que preocuparse mucho por cómo se calcula, se puede calcular la correlación de todas las monedas usando la línea 1 de código de Python. Como se muestra en el gráfico de calor de correlación, la representación roja es positiva, la representación azul es negativa, y la correlación más profunda es la más fuerte.

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

Los 20 pares de monedas más relevantes fueron seleccionados por relevancia. Los resultados fueron los siguientes. Todos ellos tienen una relevancia muy fuerte, todos por encima de 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

El código correspondiente es el siguiente:

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)

Verificación de las pruebas

El código de repetición específico es el siguiente. La principal observación de la estrategia de demostración es la proporción de precios de las dos criptomonedas (IOTA y ZIL) y realizar transacciones en función de la variación de esta proporción.

  1. Iniciación

    • Para definir las parejas de transacciones (pair_a = IOTA, pair_b = ZIL)
    • Crear un objeto de intercambioeEl saldo inicial es de US$10.000 y la tarifa de transacción es de 0.02%.
    • Calculación de la proporción de precios promedio inicialavg
    • Establece un valor de transacción inicialvalue = 1000
  2. Procesamiento iterativo de datos de precios

    • Datos de precios a través de cada punto de tiempodf_close
    • Calcula la desviación de la relación de precios actuales con respecto al promediodiff
    • El valor de la transacción se calcula según el desvíoaim_value, por cada desviación de 0.01, se negocia un valor. Y se decide la operación de compra y venta en función de la situación actual de la posesión de la cuenta y el precio.
    • Si la desviación es demasiado grande, ejecutar la ventapair_ay compraspair_b¿Cómo se hace esto?
    • Si el desvío es demasiado pequeño, ejecuta la compra.pair_ay venderpair_b¿Cómo se hace esto?
  3. La media ajustada

    • Actualización de la proporción de precios promedioavgEl precio de los productos es el mismo que el precio de los productos.
  4. Actualizar cuentas y registros

    • Actualizar la información de los activos y el saldo de las cuentas de los intercambiadores.
    • Registra el estado de las cuentas de cada paso (total de activos, activos mantenidos, gastos de transacción, posiciones multinivel y vacantes) hasta el final de la transacción.res_list
  5. Resultado de salida

    • ¿Qué es esto?res_listConvierte a un marco de datosresEn la página de Facebook de la organización, se puede leer:
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);

Los resultados de la revisión de 4 grupos de monedas son ideales. El cálculo de la correlación actual utiliza datos futuros, por lo que no es muy preciso. Este artículo también divide los datos en dos partes, según la correlación de cálculo anterior, el resultado de la revisión posterior.

img

Potenciales riesgos y mejoras

A pesar de que las estrategias de negociación en pareja pueden ser rentables en teoría, existen algunos riesgos en la práctica: la correlación entre las monedas puede cambiar con el tiempo, lo que hace que la estrategia falle; en condiciones extremas de mercado, las desviaciones de precios pueden aumentar y causar mayores pérdidas; la baja liquidez de ciertas monedas puede hacer que las transacciones sean difíciles de ejecutar o aumenten los costos; las cuotas de tramitación generadas por las transacciones frecuentes pueden erosionar las ganancias.

Para reducir el riesgo y mejorar la estabilidad de la estrategia, se pueden considerar las siguientes mejoras: recalcular periódicamente la correlación entre las monedas, ajustar los pares de operaciones en el momento oportuno; establecer puntos de stop loss y stop loss para controlar la pérdida máxima de un solo comercio; operar simultáneamente con varios pares de monedas, diversificando el riesgo.

Las conclusiones

La estrategia de negociación de la combinación de divisas digitales es rentable al aprovechar la correlación de los precios de las monedas para operar con un apalancamiento cuando los precios se desvían. La estrategia tiene una mayor viabilidad teórica. Luego se lanzará un código de fuente de una estrategia de mercado simple basada en la estrategia. Si hay más preguntas o se necesita una discusión adicional, esté bienvenido a comunicarse.


Más.

77924998¿Qué hay de la fuente de código?

Las semillas 888¡Chang trabaja horas extras!