Estratégia de hedge spot de criptomoedas (2)

Autora:Ninabadass, Criado: 2022-04-14 16:17:46, Atualizado: 2022-04-15 14:16:23

Estratégia de hedge spot de criptomoedas (2)

No artigo anterior, implementamos uma estratégia de hedge simples juntos, e então vamos aprender como atualizar a estratégia. A estratégia não apresenta muitas modificações, mas os pormenores das alterações requerem atenção: as definições de alguns lugares do código foram modificadas, em comparação com as anteriores, que devem ser entendidas especificamente.

Requisitos para melhorar a estratégia

  • Mudança de modo de margem do objeto de troca spot A modificação está relacionada apenas com o bot. Algumas plataformas spot têm interfaces de margem spot, que também são encapsuladas no FMZ. Para os objetos de troca que são diretamente encapsulados no FMZ e suportam margem spot, você pode mudar diretamente o modo.
  • Adicionar mais gráfico de expansão Para adicionar mais gráfico de exibição de spread, e nós apenas traçar as curvas de spread deA->BeB->A, bem como as linhas de disparo horizontal, podemos usar diretamente ochart plot libraryA vantagem é a simplicidade e a facilidade de utilização.template library together.
  • Função da cobertura unilateral Esta modificação é relativamente grande, porque é difícil reverter completamente o spread de preço entre as duas plataformas durante a negociação de hedge específica. Na maioria das vezes, o preço em uma plataforma é consistentemente maior do que o preço em outra plataforma. Neste momento, se nossos ativos estiverem totalmente hedgeados (isto é, todos os símbolos de moeda estão na plataforma com os preços mais baixos e os ativos estão todos na plataforma com os preços mais altos). O hedge está estagnado e não é mais possível depender da volatilidade do spread para obter lucro. Neste momento, você precisa fazer a estratégia de hedge e retornar os símbolos de moeda perdendo apenas uma pequena quantidade de ativos (deixe os símbolos de moeda retornarem à plataforma com os preços mais altos novamente). Quando o spread de preço se torna maior novamente, você pode continuar a hedge e obter lucros.
  • Modificar interativamente parâmetros como linha de cobertura spread
    Adicionar a função interativa à estratégia, de modo a modificar a linha de desencadeamento de spread em tempo real.
  • Gerenciar as informações da barra de estado e exibi-las no formato de tabela Organizar e gerir os dados que precisam ser exibidos, para uma observação conveniente.

Em seguida, vamos realizar essas ideias de design uma a uma.

Mudança de modo de margem do objeto de troca spot

Para mudar para o modo de margem spot, use o códigoexchanges[i].IO, importar o parâmetrotrade_normalpara mudar para margem isolada e importartrade_super_marginpara mudar para a margem cruzada, que não é suportada em backtest.

No âmbito da preparação no início domainFunção, adicionar:

    // switch the margin mode 
    for (var i = 0 ; i < exchanges.length ; i++) {   // traverse and detect all exchange objects added
        if (exchanges[i].GetName() == "Binance" && marginType != 0) {   // if the exchange object represented by the current index i is Binance Spot, and the parameter marginType on the strategy interface is not selected as the "common spot" option, execute the switch
            if (marginType == 1) {
                Log(exchanges[i].GetName(), "set to isolated margin")
                exchanges[i].IO("trade_normal")
            } else if (marginType == 2) {
                Log(exchanges[i].GetName(), "set to cross margin")
                exchanges[i].IO("trade_super_margin")
            }
        }
    }

A estratégia aqui apenas adiciona o código para alternar o modo de margem spot do Binance Spot, então a configuração de comutação nos parâmetros da estratégia só funciona para o Binance Spot.

Adicionar mais gráfico de expansão

Usando os modelos de gráficos encapsulados é muito simples.chart plot LibraryPode procurá-lo diretamente na plataforma da Praça da FMZ.

img

Ou pode clicar diretamente no link:https://www.fmz.com/strategy/27293para pular para a página de cópia do modelo.

img

Clique no botão e você pode facilmente copiar o modelo para sua própria biblioteca de estratégia.

img

Em seguida, na página de edição de estratégia, você pode verificar a biblioteca de modelos a ser usada na coluna de modelo. Salve a estratégia depois de verificá-la, e a estratégia usará esse modelo. Esta é apenas uma breve descrição do uso da biblioteca de modelos. Uma vez que a estratégia já fez referência a este modelo, não há necessidade de repetir a operação. Quando você copia o código de estratégia no quadrado, você pode ver quechart plot Libraryfoi referenciado na barra de modelos da página de edição da estratégia.

Aqui aprendemos principalmente como utilizar as funções dochart plot librarypara tramar.

img

Planejamos traçar os spreads deA->BeB->APrecisamos traçar duas curvas (atualmente, os spreads de A para B e B para A), e duas linhas horizontais (linhas de gatilho de spread), como mostrado na figura acima.

Porque queremos projetar uma cerca unilateral, as linhas de gatilho deA->BeB->Aserá diferente, e não podemos usar o desenho no artigo anterior. No artigo anterior:

      var targetDiffPrice = hedgeDiffPrice
      if (diffAsPercentage) {
          targetDiffPrice = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentage
      }

Só há uma propagação desencadeada.targetDiffPrice- Não. Portanto, aqui precisamos modificar o código, e precisamos modificar os parâmetros primeiro.

img

Em seguida, modifique o código:

        var targetDiffPriceA2B = hedgeDiffPriceA2B
        var targetDiffPriceB2A = hedgeDiffPriceB2A
        if (diffAsPercentage) {
            targetDiffPriceA2B = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentageA2B
            targetDiffPriceB2A = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentageB2A
        }

Assim, a linha de gatilho de propagação mudou da anteriortargetDiffPricepara dois, ou seja,targetDiffPriceA2BetargetDiffPriceB2A- Não. Em seguida, você pode usar a função de gráfico gráfico da biblioteca gráfico gráfico para desenhar os dados no gráfico.

        // plot
        $.PlotHLine(targetDiffPriceA2B, "A->B")  // the first parameter of the function is the value of the horizontal line in the Y-axis direction, and the second parameter is the display text
        $.PlotHLine(targetDiffPriceB2A, "B->A")

Quando a estratégia é executada, o gráfico será exibido assim.

img

Em seguida, desenhe a curva de variação em tempo real; para evitar a sobrecarga, coloque o código que traça as curvas de variação em tempo real na detecção do saldo. s

        if (ts - lastKeepBalanceTS > keepBalanceCyc * 1000) {
            nowAccs = _C(updateAccs, exchanges)
            var isBalance = keepBalance(initAccs, nowAccs, [depthA, depthB])
            cancelAll()
            if (isBalance) {
                lastKeepBalanceTS = ts
                if (isTrade) {
                    var nowBalance = _.reduce(nowAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
                    var initBalance = _.reduce(initAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
                    LogProfit(nowBalance - initBalance, nowBalance, initBalance, nowAccs)
                    isTrade = false 
                }                
            }

            $.PlotLine("A2B", depthA.Bids[0].Price - depthB.Asks[0].Price)  // plot real-time spread curves
            $.PlotLine("B2A", depthB.Bids[0].Price - depthA.Asks[0].Price)  // the first parameter is the curve name, and the second parameter is the curve value at the current moment, that is, the value in the Y-axis direction at the current moment
        }

O código de traçagem só precisa de 4 linhas para permitir a estratégia com uma exibição de gráfico durante a execução.

Função da vedação unilateral

Como mencionado acima, o número da linha de desencadeamento do spread foi alterado para dois, que controlam, respectivamente, o desencadeador da cobertura deA->BeB->A. Desta forma, o algoritmo de preço da ordem anterior não pode ser utilizado, e o método de adição de preço de slide para o preço de mercado é usado em vez disso.

        if (depthA.Bids[0].Price - depthB.Asks[0].Price > targetDiffPriceA2B && Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount) >= minHedgeAmount) {          // A->B market condition satisfied             
            var priceSell = depthA.Bids[0].Price - slidePrice
            var priceBuy = depthB.Asks[0].Price + slidePrice
            var amount = Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount)
            if (nowAccs[0].Stocks > minHedgeAmount && nowAccs[1].Balance * 0.8 / priceSell > minHedgeAmount) {
                amount = Math.min(amount, nowAccs[0].Stocks, nowAccs[1].Balance * 0.8 / priceSell, maxHedgeAmount)
                Log("triggerA->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[1].Balance * 0.8 / priceSell, nowAccs[0].Stocks)  // prompt message
                hedge(exB, exA, priceBuy, priceSell, amount)
                cancelAll()
                lastKeepBalanceTS = 0
                isTrade = true 
            }            
        } else if (depthB.Bids[0].Price - depthA.Asks[0].Price > targetDiffPriceB2A && Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount) >= minHedgeAmount) {   // B->A market condition satisfied 
            var priceBuy = depthA.Asks[0].Price + slidePrice
            var priceSell = depthB.Bids[0].Price - slidePrice
            var amount = Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount)
            if (nowAccs[1].Stocks > minHedgeAmount && nowAccs[0].Balance * 0.8 / priceBuy > minHedgeAmount) {
                amount = Math.min(amount, nowAccs[1].Stocks, nowAccs[0].Balance * 0.8 / priceBuy, maxHedgeAmount)
                Log("triggerB->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[0].Balance * 0.8 / priceBuy, nowAccs[1].Stocks)  // prompt message
                hedge(exA, exB, priceBuy, priceSell, amount)
                cancelAll()
                lastKeepBalanceTS = 0
                isTrade = true 
            }            
        }

Uma vez que os preços de compra e venda são divididos em dois dados, os preços de venda e de compra são divididos em dois.hedgeA função também precisa de ser modificada.

function hedge(buyEx, sellEx, priceBuy, priceSell, amount) {
    var buyRoutine = buyEx.Go("Buy", priceBuy, amount)
    var sellRoutine = sellEx.Go("Sell", priceSell, amount)
    Sleep(500)
    buyRoutine.wait()
    sellRoutine.wait()
}

Há também alguns ajustes menores baseados nestas modificações, que não serão descritos aqui.

Modificar interativamente parâmetros como linha de cobertura spread

Adicionar interação à estratégia, para que a estratégia possa modificar a linha de gatilho de propagação em tempo real. Primeiro, adicione controles interativos à estratégia na página de edição de estratégia.

img

Houve dois controles adicionados, um chamado A2B e o outro chamado B2A. Depois de inserir um valor na caixa de entrada de controle, clique no botão à direita da caixa de entrada. Um comando será enviado para a estratégia imediatamente, por exemplo: inserir o valor123na caixa de entrada, clique noA2BO botão, e um comando será enviado para a estratégia imediatamente.

A2B:123

Projetar código de detecção e processamento interativo no código de estratégia.

        // interaction 
        var cmd = GetCommand()   // every time when the loop is operated here, it will detect whether an interactive command is sent; if no, return null string 
        if (cmd) {               // interactive command detected, such as A2B:123
            Log("received command:", cmd)
            var arr = cmd.split(":")   // split out the interactive control name and the value in the input box; arr[0] means A2B, and arr[1] means 123
            if (arr[0] == "A2B") {     // judge whether the triggered interactive control is A2B
                Log("modify parameterA2B,", diffAsPercentage ? "parameter of spread ratio:" : "parameter of spread:", arr[1])
                if (diffAsPercentage) {
                    hedgeDiffPercentageB2A = parseFloat(arr[1])     // modify the spread trigger line 
                } else {
                    hedgeDiffPriceA2B = parseFloat(arr[1])          // modify the spread trigger line 
                }
            } else if (arr[0] == "B2A") {           // detected the triggered control is B2A 
                Log("modify parameterB2A,", diffAsPercentage ? "parameter of spread ratio:" : "parameter of spread:", arr[1])
                if (diffAsPercentage) {
                    hedgeDiffPercentageA2B = parseFloat(arr[1])
                } else {
                    hedgeDiffPriceB2A = parseFloat(arr[1])
                }
            }
        }

Gerenciar as informações da barra de estado e exibi-las no formato de tabela

Faça com que a exibição dos dados da barra de estado seja mais regulada e fácil de observar.

        var tbl = {
            "type" : "table", 
            "title" : "data", 
            "cols" : ["platform", "Currency", "frozenCurrrency", "quoteCurrency", "frozenQuoteCurrency", "triggerSpread", "currentSpread"], 
            "rows" : [], 
        }
        tbl.rows.push(["A:" + exA.GetName(), nowAccs[0].Stocks, nowAccs[0].FrozenStocks, nowAccs[0].Balance, nowAccs[0].FrozenBalance, "A->B:" + targetDiffPriceA2B, "A->B:" + (depthA.Bids[0].Price - depthB.Asks[0].Price)])
        tbl.rows.push(["B:" + exB.GetName(), nowAccs[1].Stocks, nowAccs[1].FrozenStocks, nowAccs[1].Balance, nowAccs[1].FrozenBalance, "B->A:" + targetDiffPriceB2A, "B->A:" + (depthB.Bids[0].Price - depthA.Asks[0].Price)])

        LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")

img

Teste de retrocesso

O backtest é apenas um teste da estratégia, como uma função de detecção preliminar. Muitos bugs podem realmente ser testados no estágio de backtest. Não é necessário se preocupar muito com os resultados do backtest. Eventualmente, a estratégia ainda precisa ser testada no ambiente real com bots reais.

img

img

Código fonte da estratégia:https://www.fmz.com/strategy/302834


Mais.