WEB3DEV

Cover image for Arbitragem Triangular Automatizada de Criptos em 4 etapas
Banana Labs
Banana Labs

Posted on • Atualizado em

Arbitragem Triangular Automatizada de Criptos em 4 etapas

Crie seu próprio algoritmo para arbitragem em trading com Python.

Introdução

A arbitragem tira vantagem da diferença dos preços dos ativos no mercado. A arbitragem tem sido tradicionalmente feita no mercado forex por muitos anos, mas dada a volatilidade no mercado de criptomoedas, ela também pode ser aplicada ao mercado de criptomoedas. Oportunidades de arbitragem podem existir dentro da mesma exchange ou entre exchanges.

A arbitragem triangular é uma técnica que tenta explorar a discrepância de preços em três ativos diferentes ao mesmo tempo.
Por exemplo, podemos trocar BTC por USDT, BTC por ETH e ETH de volta para USDT. Se o patrimônio líquido ao fazer esses três trades simultaneamente for lucrativo, os 3 trades serão executados simultaneamente.

Exemplo de Arbitragem Triangular (Imagem do Autor)<br>
Exemplo de Arbitragem Triangular (Imagem do Autor)

Neste artigo, analisaremos as oportunidades de arbitragem dentro da mesma exchange, em particular, mergulharemos profundamente nas abordagens de arbitragem triangular. O foco é desenvolver e implementar um algoritmo de trade que possa identificar um lucro e acionar as ordens de trade necessárias para ele.

A arbitragem é considerada um método de trade de menor risco em comparação com o trade tradicional, onde o momento da compra/venda é crucial. Também na arbitragem, o lucro/perda é conhecido imediatamente, pois todas as negociações necessárias são executadas simultaneamente.

Abordagens para Arbitragem Triangular

Existem diferentes abordagens de compra/venda dos 3 ativos para alcançar a arbitragem triangular. Neste artigo, vamos considerar duas abordagens.

Abordagem 1: COMPRAR - COMPRAR - VENDER

Abordagem COMPRA-COMPRA-VENDA da Arbitragem Triangular (Imagem do Autor)
Abordagem COMPRA-COMPRA-VENDA da Arbitragem Triangular (Imagem do Autor)

No exemplo acima, começamos com USDT como investimento inicial. Depois de realizar os 3 trades, ficamos novamente com o USDT no final. Aqui estão os trades que serão realizados:

  1. Compre Bitcoin (BTC) com Tether (USDT)
  2. Compre Ethereum (ETH) com Bitcoin (BTC)
  3. Vender Ethereum (ETH) por Tether (USDT)

No final do terceiro trade, podemos comparar o USDT final com o investimento inicial com o qual começamos na etapa 1. Se isso levar a um lucro substancial, os 3 trades podem ser iniciados simultaneamente.

Abordagem 2: COMPRAR - VENDA - VENDA

Abordagem COMPRA-VENDA-VENDA da Arbitragem Triangular (Imagem do Autor)<br>
Abordagem COMPRA-VENDA-VENDA da Arbitragem Triangular (Imagem do Autor)

Semelhante à primeira abordagem, os mesmos ativos são usados para verificar oportunidades de arbitragem em um fluxo diferente. No exemplo acima, os 3 trades a seguir são avaliados:

  1. Compre Ethereum (ETH) com Tether (USDT)
  2. Vender Ethereum (ETH) por Bitcoin (BTC)
  3. Vender Bitcoin (BTC) por Tether (USDT)

Algoritmo de trade — implementação em 4 etapas

Aqui está uma visão geral das diferentes etapas para implementar um algoritmo de trade com arbitragem triangular. Veremos cada uma dessas etapas em detalhes nas próximas seções.

Etapa 1: Obtenha todas as combinações de criptos válidas
Etapa 2: Realize a arbitragem triangular
Etapa 3: Coloque as ordens de negociação
Etapa 4: Junte tudo

Antes de avançar com essas etapas, precisamos inicializar a exchange para fazer a arbitragem. Selecione a exchange onde você tem uma conta para trading e a conta que suporta trade baseado em API. Neste exemplo, usei a exchange WazirX, pois tenho uma conta para trading nessa exchange.

import ccxt
from config import myconfig
exchange = ccxt.wazirx({
                         “apiKey”: myconfig.API_KEY,
                         “secret”: myconfig.API_SECRET
                       })
Enter fullscreen mode Exit fullscreen mode

O pacote ccxt suporta várias exchanges e caso você tenha uma conta em qualquer uma das outras exchanges, você pode obter o mesmo código funcionando apenas alterando o nome da exchange no trecho acima. Consulte esta página para obter a lista de exchanges suportadas pelo ccxt.

Etapa 1: Obtenha todas as combinações de criptos válidas

Precisamos de uma moeda base com o investimento inicial em nossa conta de trade para começar. Aqui consideramos o USDT como a moeda base. Observe que até moedas fiduciárias como INR ou USD podem ser consideradas como a moeda base.

Existem centenas de criptomoedas suportadas pela exchange e, portanto, podemos derivar diferentes combinações para realizar a arbitragem triangular. Podemos codificar um conjunto limitado de combinações ou permitir que o código considere todas as combinações possíveis disponíveis na exchange. O trecho de código abaixo implementa a segunda abordagem de identificar todas as combinações de arbitragem possíveis.

Existem 543 ativos cripto suportados por esta exchange no momento da redação deste artigo.

markets = exchange.fetchMarkets()
market_symbols = [market['symbol'] for market in markets]
Enter fullscreen mode Exit fullscreen mode

output

Em seguida, extraia todas as combinações possíveis para aplicar as abordagens COMPRA-COMPRA-VENDA e COMPRA-VENDA-VENDA de arbitragem triangular.

def get_crypto_combinations(market_symbols, base):
    combinations = []
    for sym1 in market_symbols:   
        sym1_token1 = sym1.split('/')[0]
        sym1_token2 = sym1.split('/')[1]   
        if (sym1_token2 == base):
            for sym2 in market_symbols:
                sym2_token1 = sym2.split('/')[0]
                sym2_token2 = sym2.split('/')[1]
                if (sym1_token1 == sym2_token2):
                    for sym3 in market_symbols:
                        sym3_token1 = sym3.split('/')[0]
                        sym3_token2 = sym3.split('/')[1]
                        if((sym2_token1 == sym3_token1) and (sym3_token2 == sym1_token2)):
                            combination = {
                                'base':sym1_token2,
                                'intermediate':sym1_token1,
                                'ticker':sym2_token1,
                            }
                            combinations.append(combination)
    return combinations

wx_combinations_usdt = get_crypto_combinations(market_symbols,'USDT')
Enter fullscreen mode Exit fullscreen mode

Existem 63 combinações diferentes de arbitragem que o código conseguiu identificar.

output

Por exemplo: Se um algoritmo COMPRA-COMPRA-VENDA deve ser aplicado na primeira entrada, então:

  1. Compre BTC (intermediário) por USDT (base)
  2. Compre XRP (ticker) por BTC (intermediário)
  3. Vender XRP (ticker) por USDT (base)

Se este trade circular pode levar a um lucro, então é bom executar os 3 trades simultaneamente.

Etapa 2: Realizar arbitragem triangular

Extraia os preços dos três ativos da exchange e identifique o preço final após realizar as três conversões de compra/venda.

def check_buy_buy_sell(scrip1, scrip2, scrip3,initial_investment):

    ## SCRIP1
    investment_amount1 = initial_investment
    current_price1 = fetch_current_ticker_price(scrip1)
    final_price = 0
    scrip_prices = {}

    if current_price1 is not None:
        buy_quantity1 = round(investment_amount1 / current_price1, 8)
        time.sleep(1)
        ## SCRIP2
        investment_amount2 = buy_quantity1     
        current_price2 = fetch_current_ticker_price(scrip2)
        if current_price2 is not None:
            buy_quantity2 = round(investment_amount2 / current_price2, 8)
            time.sleep(1)
            ## SCRIP3
            investment_amount3 = buy_quantity2     
            current_price3 = fetch_current_ticker_price(scrip3)
            if current_price3 is not None:
                sell_quantity3 = buy_quantity2
                final_price = round(sell_quantity3 * current_price3,3)
                scrip_prices = {scrip1 : current_price1, scrip2 : current_price2, scrip3 : current_price3}

    return final_price, scrip_prices
Enter fullscreen mode Exit fullscreen mode

Da mesma forma, a abordagem COMPRA-VENDA-VENDA também precisa ser implementada. Apenas um trecho do código é fornecido aqui para evitar congestionamento de código. Consulte o repositório git vinculado no final do artigo para obter o código executável completo.

Calcule o lucro/perda na realização dessa arbitragem triangular considerando a corretagem da exchange para cada transação e o lucro mínimo esperado do trade.

def check_profit_loss(total_price_after_sell,initial_investment,transaction_brokerage, min_profit):
    apprx_brokerage = transaction_brokerage * initial_investment/100 * 3
    min_profitable_price = initial_investment + apprx_brokerage + min_profit
    profit_loss = round(total_price_after_sell - min_profitable_price,3)
    return profit_loss
Enter fullscreen mode Exit fullscreen mode

Etapa 3 - Coloque as ordens de trade

Aqui está o código para executar os três trades na exchange. Se o trade de preço de mercado não for suportado pela exchange, um trade de preço limite precisa ser executado. Às vezes, as ordens de preço limite podem fazer com que a ordem do trade fique presa se o preço flutuar antes da execução da ordem.

def place_buy_order(scrip, quantity, limit):
    order = exchange.create_limit_buy_order(scrip, quantity, limit)
    return order

def place_sell_order(scrip, quantity, limit):
    order = exchange.create_limit_sell_order(scrip, quantity, limit)
    return order 

def place_trade_orders(type, scrip1, scrip2, scrip3, initial_amount, scrip_prices):
    final_amount = 0.0
    if type == 'BUY_BUY_SELL':
        s1_quantity = initial_amount/scrip_prices[scrip1]
        place_buy_order(scrip1, s1_quantity, scrip_prices[scrip1])

        s2_quantity = s1_quantity/scrip_prices[scrip2]
        place_buy_order(scrip2, s2_quantity, scrip_prices[scrip2])

        s3_quantity = s2_quantity
        place_sell_order(scrip3, s3_quantity, scrip_prices[scrip3])

    elif type == 'BUY_SELL_SELL':
        s1_quantity = initial_amount/scrip_prices[scrip1]
        place_buy_order(scrip1, s1_quantity, scrip_prices[scrip1])

        s2_quantity = s1_quantity
        place_sell_order(scrip2, s2_quantity, scrip_prices[scrip2])

        s3_quantity = s2_quantity * scrip_prices[scrip2]
        place_sell_order(scrip3, s3_quantity, scrip_prices[scrip3])

    return final_amount
Enter fullscreen mode Exit fullscreen mode

Etapa 4 - Juntando tudo

Envolva as etapas acima em um único pacote e execute-o para todas as combinações possíveis.

Para cada combinação execute os 3 passos abaixo
(Exemplo: Comprar — BTC/USDT, vender — ETH/BTC, vender — ETH/USDT)

  1. Identifique o preço final de venda após realizar os 3 trades
  2. Calcule o lucro/perda ao fazer essas transações
  3. Coloque as 3 ordens do trade se as transações levarem ao lucro desejado
def perform_triangular_arbitrage(scrip1, scrip2, scrip3, arbitrage_type,initial_investment, 
                               transaction_brokerage, min_profit):
    final_price = 0.0
    if(arbitrage_type == 'BUY_BUY_SELL'):
        # Check this combination for triangular arbitrage: scrip1 - BUY, scrip2 - BUY, scrip3 - SELL
        final_price, scrip_prices = check_buy_buy_sell(scrip1, scrip2, scrip3,initial_investment)

    elif(arbitrage_type == 'BUY_SELL_SELL'):
        # Check this combination for triangular arbitrage: scrip1 - BUY, scrip2 - SELL, scrip3 - SELL
        final_price, scrip_prices = check_buy_sell_sell(scrip1, scrip2, scrip3,initial_investment)

    profit_loss = check_profit_loss(final_price,initial_investment, transaction_brokerage, min_profit)

    if profit_loss>0:
        print(f"PROFIT-{datetime.now().strftime('%H:%M:%S')}:"\
              f"{arbitrage_type}, {scrip1},{scrip2},{scrip3}, Profit/Loss: {round(final_price-initial_investment,3)} ")
        place_trade_orders(arbitrage_type, scrip1, scrip2, scrip3, initial_investment, scrip_prices)
Enter fullscreen mode Exit fullscreen mode
INVESTMENT_AMOUNT_DOLLARS = 100
MIN_PROFIT_DOLLARS = 0.5
BROKERAGE_PER_TRANSACTION_PERCENT = 0.2

while(1):
    for combination in wx_combinations_usdt:
        base = combination['base']
        intermediate = combination['intermediate']
        ticker = combination['ticker']

        s1 = f'{intermediate}/{base}'    # Eg: BTC/USDT
        s2 = f'{ticker}/{intermediate}'  # Eg: ETH/BTC
        s3 = f'{ticker}/{base}'          # Eg: ETH/USDT 

        # 1. Check triangular arbitrage for buy-buy-sell 
        perform_triangular_arbitrage(s1,s2,s3,'BUY_BUY_SELL',INVESTMENT_AMOUNT_DOLLARS,
                                  BROKERAGE_PER_TRANSACTION_PERCENT, MIN_PROFIT_DOLLARS)

        # Check triangular arbitrage for buy-sell-sell 
        perform_triangular_arbitrage(s3,s2,s1,'BUY_SELL_SELL',INVESTMENT_AMOUNT_DOLLARS,
                                  BROKERAGE_PER_TRANSACTION_PERCENT, MIN_PROFIT_DOLLARS)
        time.sleep(1) 
Enter fullscreen mode Exit fullscreen mode

Resultados

Aqui está uma amostra do resultado na execução deste código para uma iteração.

Foi considerado um investimento inicial de 100$. Com 63 combinações e 2 abordagens, um total de 126 combinações de arbitragem foram verificadas e 26 delas apresentaram lucro conforme abaixo.

amostra do resultado da arbitragem triangular para 1 iteração<br>
amostra do resultado da arbitragem triangular para 1 iteração

Observe que a tabela acima é dos logs e não dos trades reais que foram executados. Embora esta tabela mostre uma figura rósea, nem sempre pode ser um passeio tranquilo na realidade.

Por que pode ser um passeio acidentado….

  1. Como todas as três ordens precisam ser executadas simultaneamente para obter lucro, há chances de que algumas ordens não sejam executadas a tempo, devido a atrasos na rede ou problemas com a exchange. Nesse cenário, você pode ficar preso às criptomoedas e uma intervenção manual pode ser necessária.
  2. O preço da cripto considerado aqui é o preço do ticker ao vivo. Os preços podem flutuar antes que as ordens sejam executadas. A melhor abordagem seria pegar as entradas do livro de ordens e escolher o preço do ticker com base no volume.
  3. Três preços de ticker vindos da exchange são necessários simultaneamente para realizar a arbitragem triangular. Algumas exchanges definem um limite de taxa que não permite chamadas repetidas de API. Nesse caso, a API pode lançar uma exceção RateLimitExceeded (HTTP 429 Too Many Requests). Isso pode ser tratado usando um temporizador de suspensão de 1 segundo entre as chamadas de API. Mas se o preço mudar dentro desses segundos, as ordens podem não ser executadas.
  4. Algumas exchanges não permitem colocar ordens a preço de mercado (como no meu exemplo). O preço limite é obrigatório. Nesses casos, novamente há chances de que as ordens não sejam executadas devido à flutuação do preço.

Repositório do Código

Consulte este repositório git para acessar o código completo: TriangularArbitrageCryptos

Conclusão

Com base na exchange e no suporte à API que ela fornece, os algoritmos para trading podem ser ajustados ainda mais. Tente brincar com o código alterando a moeda base, usando trades de preço de mercado ou verificando outras abordagens de arbitragem.

Novamente, um disclaimer, este artigo é apenas para fins educacionais e para você entender os diferentes tipos de opções de trade disponíveis. Lembre-se de que você está competindo com vários outros bots de trade por aí. Caso você queira experimentar trades reais, primeiro certifique-se de ter construído um algoritmo de trade robusto antes de se aventurar nele para evitar perdas.

Além disso, se você estiver interessado em agrupar esse código em um aplicativo de bot de trade, use este artigo como referência: Construindo um Bot básico de Trading de Criptos em Python.

Obrigado por ler até o final :-). Boas experiências!!


Esse artigo é uma tradução de Lakshmi Ajay feita por @bananlabs. Você pode encontrar o artigo original aqui

Top comments (0)