O recurso está a ser carregado... Carregamento...

Estratégias de negociação de pacotes de moedas digitais

Autora:Ervas daninhas, Criado: 2024-07-05 16:23:42, Atualizado: 2024-07-12 09:19:11

img

Estratégias de negociação de pacotes de moedas digitais

Introdução

Recentemente, vi o diário de quantificação do BoE mencionar que é possível usar moedas com correlações negativas para negociar, com base na ruptura do diferencial de preço para abrir negócios e obter lucros. As moedas digitais são basicamente positivas, negativas são algumas moedas, muitas vezes com mercados especiais, como o mercado independente das moedas MEME do passado, que não seguem completamente a tendência da grande disquete, selecionando essas moedas e fazendo mais após a ruptura, esse modo pode ser lucrativo em determinadas circunstâncias.

A negociação de parcerias de moeda digital é uma estratégia de negociação baseada em lucro estatístico, que consiste em comprar e vender simultaneamente dois contratos perpétuos de moeda digital altamente relacionados para obter lucros com o desvio de preço. Este artigo descreve em detalhes os princípios da estratégia, o mecanismo de lucro, o método de filtragem de moedas, os riscos potenciais e suas melhorias e fornece alguns exemplos práticos de código Python.

Princípios estratégicos

A estratégia de negociação de parceria depende da correlação histórica entre os preços de duas moedas digitais. Quando os preços das duas moedas apresentam uma correlação forte, seus movimentos de preços são quase sincronizados. Se o rácio de preços das duas for significativamente desviado em algum momento, pode ser considerado uma anomalia temporária, com o preço tendendo a voltar ao normal. O mercado de moedas digitais tem uma alta interação e, quando uma das principais moedas digitais (como o Bitcoin) apresenta grandes flutuações, geralmente provoca uma reação de interação de outras moedas digitais.

Suponha que as moedas A e B tenham uma alta correlação de preço. Se, em algum momento, o rácio de preço A/B tiver um valor médio de 1, se, em algum momento, o rácio de preço A/B tiver um desvio superior a 0,001, ou seja, superior a 1,001, a transação pode ser feita da seguinte forma: abrir mais B, abrir mais A. Por outro lado, quando o rácio de preço A/B for inferior a 0,999, abrir mais A, abrir mais B.

A chave para o lucro é o ganho do diferencial quando o desvio de preço retorna ao normal. Como o desvio de preço geralmente é curto, os traders podem estabilizar quando o preço retorna ao valor médio e lucrar com o diferencial.

Preparação de dados

Introduzir a biblioteca correspondente

Esses códigos podem ser usados diretamente, prefiro baixar um Anancoda e depurar em um notebook 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

Obtenha todos os pares de transações que estão sendo 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) # 获取所有的正在交易的交易对

Funções para baixar K-strings

A função principal do GetKlines é obter dados de linha K históricos de contratos permanentes de negociações especificadas do Bitcoin Exchange e armazená-los em um DataFrame Panda. Os dados de linha K incluem informações sobre preços de abertura, preços máximos, preços mínimos, preços de fechamento, volumes de transações.

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

Baixe dados

O volume de dados é relativamente grande, e para um download mais rápido, apenas os dados da linha K das últimas 3 horas foram obtidos.df_close contém dados de preços de fechamento de todas as moedas.

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

Motores de requalificação

Define um objeto do Exchange para a próxima revisão

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álise de correlação

O cálculo da correlação é um método em estatística usado para medir a relação linear entre duas variáveis. O método de cálculo da correlação mais usado é o coeficiente de correlação de Pearson. A seguir estão os princípios, fórmulas e métodos de implementação do cálculo da correlação.

  • 1Indica que as duas variáveis estão sempre em mudança simultânea. Quando uma variação aumenta, a outra variação aumenta proporcionalmente. Quanto mais perto de 1 a relação é mais forte.
  • -1A correlação é negativa, e as duas variáveis são sempre inversas. Quanto mais perto de -1 a correlação é negativa.
  • 0Indica a relação sem fio, sem relação linear entre as duas variáveis.

Os coeficientes de correlação de Pearson determinam a correlação de duas variáveis, calculado o diferencial de conexão e o diferencial padrão. A fórmula é a seguinte:

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

Entre eles:

  • (\rho_{X,Y}) é o coeficiente de correlação de Pearson das variáveis (X) e (Y).
  • (\text{cov}(X,Y) é a diferença de conjuntos de (X) e (Y).
  • (\sigma_X) e (\sigma_Y) são os desvios padrão de (X) e (Y), respectivamente.

Claro, sem se preocupar muito com a forma como é calculado, pode-se calcular a correlação de todas as moedas usando a linha de código Python 1. Como mostra o gráfico de calor de correlação, o vermelho representa a correlação positiva, o azul representa a correlação negativa, e a cor é mais profunda.

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

Os 20 pares de moedas mais relevantes foram selecionados em função da relevância. Os resultados são os seguintes.

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

O código correspondente é o seguinte:

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)

Re-verificação

O código de retorno específico é o seguinte. A principal observação da estratégia de demonstração é o rácio de preços das duas criptomoedas (IOTA e ZIL) e a negociação é feita com base nas mudanças desse rácio.

  1. Inicialização

    • Definição de pares de transações (pair_a = IOTA, pair_b = ZIL)
    • Criar um objeto de trocaeO saldo inicial é de US$ 10.000 e a taxa de transação é de 0,02%;
    • Cálculo do índice de preço médio inicialavg
    • Definir um valor de transação inicialvalue = 1000
  2. Processamento iterativo de dados de preços

    • Os dados de preços em todos os pontos do tempodf_close
    • Calcular o desvio da taxa de preços atual em relação à médiadiff
    • Calculação do valor da transação de acordo com o desvioaim_value, para cada desvio de 0.01, negocia um valor. E decide a compra e venda de operações com base no atual estado de estoque e preço da conta.
    • Se o desvio for muito grande, execute a venda.pair_ae comprarpair_bO que é que você está a fazer?
    • Se o desvio for muito pequeno, faça a compra.pair_ae venderpair_bO que é que você está a fazer?
  3. Ajuste da média

    • Atualização do índice de preço médioavgA partir de agora, o preço do produto será mais acessível e mais barato.
  4. Atualizar contas e registros

    • Atualize as informações sobre a sua conta de bolsa e o seu saldo.
    • Registre o estado da conta de cada passo (total de ativos, ativos mantidos, taxas de transação, posições múltiplas e vazias) atéres_list
  5. Resultado de saída

    • O que é isso?res_listConverter para dataframeresO site do Facebook do Facebook, que é o site oficial do Facebook, é o site oficial do Facebook do Facebook.
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);

O resultado é ideal. O cálculo da correlação atual é feito com dados futuros, por isso não é muito preciso. Este artigo também divide os dados em duas partes, com base na correlação do cálculo anterior e no teste posterior.

img

Riscos potenciais e melhorias

Embora a estratégia de negociação de pares possa ser lucrativa na teoria, existem alguns riscos na prática: a correlação entre as moedas pode mudar com o tempo, o que pode fazer com que a estratégia falhe; em condições de mercado extremas, os desvios de preço podem aumentar, causando grandes perdas; a baixa liquidez de algumas moedas pode tornar as transações difíceis de serem executadas ou aumentar os custos; os custos de manutenção gerados pela troca frequente podem corroer os lucros.

Para reduzir o risco e melhorar a estabilidade da estratégia, as seguintes melhorias podem ser consideradas: recalcular periodicamente a correlação entre as moedas, ajustando os pares de negociação em tempo hábil; definir stop-loss e stop-loss para controlar o máximo de perdas em uma única transação; negociar vários pares de moedas ao mesmo tempo, diversificando o risco.

Conclusões

A estratégia de negociação de pacotes de moedas digitais é uma estratégia de lucro que utiliza a correlação entre os preços das moedas para obter lucros quando os preços se desviam. A estratégia tem uma maior viabilidade teórica. Um código de código de estratégia simples baseado na estratégia será lançado em seguida.


Mais.

77924998O que você acha que vale a pena estudar?

Feijão 888O chefe de gabinete trabalha mais tempo.