Estrategia de cobertura al contado de criptomonedas (2)

El autor:No lo sé., Creado: 2022-04-14 16:17:46, Actualizado: 2022-04-15 14:16:23

Estrategia de cobertura al contado de criptomonedas (2)

En el artículo anterior, implementamos una estrategia de cobertura simple juntos, y luego aprenderemos cómo actualizar la estrategia. La estrategia no presenta muchas modificaciones, pero los detalles de las modificaciones requieren atención: se han modificado las definiciones de algunos lugares del código, en comparación con las anteriores, que deben entenderse específicamente.

Requisitos para actualizar la estrategia

  • Cambiar el modo de margen del objeto de intercambio spot La modificación está relacionada solo con el bot. Algunas plataformas spot tienen interfaces de margen spot, que también están encapsuladas en FMZ. Para los objetos de intercambio que están directamente encapsulados en FMZ y soportan el margen spot, puede cambiar directamente el modo.
  • Añadir más gráfico de dispersión Para añadir más gráfico de exhibición de la propagación, y sólo trazamos las curvas de propagación deA->ByB->A, así como las líneas de disparo horizontal, podemos utilizar directamente elchart plot libraryLa ventaja es la simplicidad y facilidad de uso.template library together.
  • Función de la cobertura unilateral Esta modificación es relativamente grande, ya que es difícil revertir completamente el diferencial de precios entre las dos plataformas durante el comercio de cobertura específica. La mayoría de las veces, el precio en una plataforma es consistentemente más alto que el precio en otra plataforma. En este momento, si nuestros activos han sido completamente cubiertos (es decir, todos los símbolos de moneda están en la plataforma con los precios más bajos, y los activos están todos en la plataforma con los precios más altos). La cobertura está estancada, y ya no es posible depender de la volatilidad de la propagación para obtener ganancias. En este momento, debe hacer la estrategia para cubrir y devolver los símbolos de moneda solo perdiendo una pequeña cantidad de activos (deje que los símbolos de moneda vuelvan a la plataforma con los precios más altos nuevamente). Cuando el precio se extienda de nuevo, puede continuar cubirindo y obteniendo ganancias.
  • Modificar de forma interactiva parámetros como la línea de cobertura de la propagación
    Añadir la función interactiva a la estrategia, para modificar la línea de disparo de la propagación en tiempo real.
  • Administrar la información de la barra de estado y mostrarla en el formato de tabla Organizar y gestionar los datos que deben mostrarse, para una observación conveniente.

A continuación, vamos a realizar esas ideas de diseño una por una.

Cambiar el modo de margen del objeto de intercambio spot

Para cambiar al modo de margen al contado, use el códigoexchanges[i].IO, importar el parámetrotrade_normalel cambio al margen aislado y la importacióntrade_super_marginpara cambiar al margen cruzado, que no es compatible en backtest. Eso solo se puede usar en bots.

En la preparación al comienzo de lamainfunción, añadir:

    // 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")
            }
        }
    }

La estrategia aquí solo agrega el código para cambiar el modo de margen al contado de Binance Spot, por lo que la configuración del interruptor en los parámetros de la estrategia solo funciona para Binance Spot.

Añadir más gráfico de dispersión

El uso de las plantillas de gráficos encapsulados es muy simple.chart plot LibraryPuedes buscarlo directamente en la plataforma de la Plaza de FMZ.

img

O puedes hacer clic directamente en el enlace:https://www.fmz.com/strategy/27293para saltar a la página de copia de la plantilla.

img

Haga clic en el botón y puede copiar fácilmente la plantilla a su propia biblioteca de estrategias.

img

Luego, en la página de edición de la estrategia, puede verificar la biblioteca de plantillas a utilizar en la columna de la plantilla. Guarde la estrategia después de comprobarla, y la estrategia utilizará esta plantilla. Esta es solo una breve descripción del uso de la biblioteca de plantillas. Dado que la estrategia ya ha hecho referencia a esta plantilla, no es necesario repetir la operación. Cuando copia el código de estrategia en Square, puede ver quechart plot Libraryse ha hecho referencia en la barra de plantillas de la página de edición de estrategias.

Aquí aprendemos principalmente cómo utilizar las funciones de lachart plot librarypara planear.

img

Planeamos trazar las diferencias deA->ByB->ANecesitamos trazar dos curvas (actualmente, los spreads de A a B y B a A), y dos líneas horizontales (líneas de disparador de dispersión), como se muestra en la figura anterior.

Debido a que queremos diseñar un seto de un solo lado, las líneas de disparo deA->ByB->Aserá diferente, y no podemos usar el diseño en el artículo anterior. En el artículo 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ólo hay una propagación activadatargetDiffPrice¿ Qué pasa? Por lo tanto, aquí tenemos que modificar el código, y tenemos que modificar los parámetros primero.

img

Luego, modifique el 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
        }

Por lo tanto, la línea de disparo de propagación ha cambiado de la anteriortargetDiffPricea dos, es decir,targetDiffPriceA2BytargetDiffPriceB2A¿ Qué pasa? A continuación, puede utilizar la función de trazado de gráficos de la biblioteca de gráficos para dibujar los datos en el 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")

Cuando la estrategia se ejecuta, el gráfico se mostrará de esta manera.

img

A continuación, dibuje la curva de diferenciación en tiempo real; para evitar el dibujo excesivo, coloque el código que traza las curvas de diferenciación en tiempo real en la detección de saldo. el

        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
        }

El código de trazado solo necesita 4 líneas para permitir la estrategia con una pantalla de gráfico durante la ejecución.

Función del seto de un solo lado

Como se ha mencionado anteriormente, el número de líneas de activación del diferencial se ha cambiado a dos, que controlan respectivamente el activador de cobertura deA->ByB->ADe esta manera, no se puede utilizar el algoritmo de precio de pedido anterior, y se utiliza en su lugar el método de agregar el precio de deslizamiento al precio de mercado.

        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 
            }            
        }

Dado que los precios de compra y venta se dividen en dos piezas de datos, elhedgeLa función también necesita 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()
}

También hay algunos ajustes menores basados en estas modificaciones, que no se describirán aquí.

Modificar de forma interactiva parámetros como la línea de cobertura de la propagación

Añadir interacción a la estrategia, para que la estrategia pueda modificar la línea de disparo de propagación en tiempo real. El diseño de la estrategia de interacción también es muy simple. Primero, añadir controles interactivos a la estrategia en la página de edición de la estrategia.

img

Se agregaron dos controles, uno llamado A2B y el otro llamado B2A. Después de introducir un valor en el cuadro de entrada de control, haga clic en el botón a la derecha del cuadro de entrada.123En el cuadro de entrada, haga clic enA2Bbotón, y una orden será enviada a la estrategia inmediatamente.

A2B:123

Diseñar código de detección y procesamiento interactivo en el código de estrategia.

        // 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])
                }
            }
        }

Administrar la información de la barra de estado y mostrarla en el formato de tabla

Hacer que la muestra de datos de la barra de estado sea más regulada y 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

Prueba de retroceso

La prueba de retroceso es sólo una prueba de la estrategia, como una función de detección preliminar. Muchos errores pueden ser probados en la etapa de prueba de retroceso. No es necesario preocuparse demasiado por los resultados de la prueba de retroceso.

img

img

Código fuente de la estrategia:https://www.fmz.com/strategy/302834


Más.