avatar of 发明者量化-小小梦 发明者量化-小小梦
Seguir Mensajes Privados
4
Seguir
1271
Seguidores

Diseño de estrategia de cobertura de spot de moneda digital (2)

Creado el: 2021-07-30 16:36:48, Actualizado el: 2023-09-20 10:36:43
comments   5
hits   2474

Diseño de estrategia de cobertura de spot de moneda digital (2)

Diseño de estrategia de cobertura de spot de moneda digital (2)

En el artículo anterior, implementamos una estrategia de cobertura simple. A continuación, aprenderemos cómo mejorar esta estrategia. Los cambios de estrategia no serán importantes, pero los detalles de los cambios requieren atención. Las definiciones de algunas partes del código han cambiado respecto a antes y es necesario comprenderlas.

La necesidad de actualizar esta estrategia

  • Cambiar el modo de apalancamiento del objeto de intercambio al contado Este cambio solo se relaciona con el trading real. Algunas bolsas al contado tienen interfaces de apalancamiento al contado, que también están encapsuladas en FMZ. Para los objetos de intercambio que se han encapsulado directamente en FMZ y admiten el apalancamiento al contado, puede cambiar el modo directamente.
  • Se agregó visualización de gráfico de propagación Agregue la visualización del gráfico de propagación, porque solo dibujaA交易所->B交易所B交易所->A交易所Dibuje la línea horizontal que desencadena la propagación. Nosotros utilizamos directamente画线类库La ventaja es que es simple y fácil de usar. Aquí también aprenderemos a usar FMZ.模版类库Función.
  • Función de cobertura unidireccional Este cambio es bastante significativo porque es difícil revertir completamente la diferencia de precios entre las dos bolsas en transacciones de cobertura específicas. La mayoría de las veces, el precio en un exchange es consistentemente más alto que el precio en otro exchange. En este momento, si todos nuestros activos están cubiertos (es decir, las monedas están todas en los intercambios con precios bajos y el dinero está todo en los intercambios con precios altos). La cobertura de riesgos ha llegado a su fin y ya no es posible confiar en las fluctuaciones de precios para obtener beneficios. En este momento, la estrategia debe ser tal que puedas perder un poco de dinero para cubrir las monedas (dejar que las monedas vuelvan a existir en un intercambio con un precio alto), y luego puedes continuar cubriéndote y obtener ganancias cuando el precio La diferencia se hace mayor nuevamente.
  • Modificar de forma interactiva parámetros como las líneas de spread de cobertura Agregue funciones interactivas a la estrategia y podrá modificar la línea de activación del spread en tiempo real.
  • Organice la información de la barra de estado y muéstrela en forma de tabla Organice los datos que se mostrarán para facilitar su observación.

A continuación, implementemos estos diseños uno por uno.

Cambiar el modo de apalancamiento del objeto de intercambio al contado

Tomando el trading spot de Binance como ejemplo, cambie al modo de apalancamiento spot usando el códigoexchanges[i].IO, pasar parámetrostrade_normalCambie a posición por posición apalancada y pasetrade_super_marginCambiar a posición completa apalancada, no se admite el backtesting. Esto sólo se utiliza en el comercio real.

existirmainLa fase de preparación al inicio de la función se incrementa:

    // 切换杠杆模式
    for (var i = 0 ; i < exchanges.length ; i++) {   // 遍历检测所有添加的交易所对象
        if (exchanges[i].GetName() == "Binance" && marginType != 0) {   // 如果当前i索引代表的交易所对象是币安现货,并且策略界面参数marginType选择的不是「普通币币」选项,执行切换
            if (marginType == 1) {
                Log(exchanges[i].GetName(), "设置为杠杆逐仓")
                exchanges[i].IO("trade_normal")
            } else if (marginType == 2) {
                Log(exchanges[i].GetName(), "设置为杠杆全仓")
                exchanges[i].IO("trade_super_margin")
            }
        }
    }

La estrategia aquí solo agrega el código para cambiar el modo de apalancamiento de moneda a moneda para Binance spot, por lo que el cambio establecido en los parámetros de la estrategia solo es válido para Binance spot.

Se agregó visualización de gráfico de propagación

Es muy sencillo utilizar las plantillas de dibujo incluidas. La plantilla que utilizamos se llama画线类库. Podrás buscarlo y obtenerlo directamente en la plaza de estrategia de la plataforma FMZ.

Diseño de estrategia de cobertura de spot de moneda digital (2)

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

Diseño de estrategia de cobertura de spot de moneda digital (2)

Haga clic en el botón para copiar esta biblioteca de plantillas a su propia biblioteca de estrategias.

Diseño de estrategia de cobertura de spot de moneda digital (2)

Luego, en la página de edición de políticas, puedes verificar la biblioteca de plantillas que necesitas en la columna de plantillas. Después de marcar la casilla y guardar la política, esta política hará referencia a esta plantilla. Aquí simplemente explicamos brevemente el uso de la biblioteca de plantillas. Esta estrategia ya ha hecho referencia a esta plantilla, por lo que no es necesario repetir la operación. Después de copiar esta estrategia en Strategy Square, podrás verla en la columna de plantilla de la página de edición de estrategia.画线类库Ya citado.

Aprendemos principalmente a utilizar画线类库Función para dibujar la gráfica.

Diseño de estrategia de cobertura de spot de moneda digital (2)

Estamos planeandoA->BLa diferencia de precio,B->ASe dibujan la diferencia de precio y la línea de activación de la diferencia de precio. Es necesario dibujar dos curvas (la diferencia de precio actual de A a B y de B a A) y dos líneas horizontales (líneas de diferencia de precio de activación), como se muestra en la figura de arriba.

Porque necesitamos diseñar una cobertura unilateral,A->ByB->ALa línea de activación es diferente. El diseño del artículo anterior ya no se puede utilizar. 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
      }

Solo hay un diferencial de activacióntargetDiffPrice。 Entonces aquí necesitamos modificar el código, primero modificar los parámetros.

Diseño de estrategia de cobertura de spot de moneda digital (2)

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

De esta manera, la línea de activación de la diferencia de precio cambia respecto a la anterior.targetDiffPriceUno, se convirtió en dostargetDiffPriceA2BtargetDiffPriceB2A。 A continuación, puede utilizar la función de dibujo de líneas de la biblioteca de dibujo de líneas para dibujar estos datos en el gráfico.

        // 画图
        $.PlotHLine(targetDiffPriceA2B, "A->B")  // 该函数第一个参数是水平线在Y轴方向上的值,第二个参数是显示文本
        $.PlotHLine(targetDiffPriceB2A, "B->A")

Cuando la estrategia esté en ejecución, aparecerá un gráfico como éste.

Diseño de estrategia de cobertura de spot de moneda digital (2)

A continuación, dibuje la curva de spread en tiempo real para evitar sobregirar. Coloque el código para dibujar curvas de datos de diferencia de precios en tiempo real en la verificación de saldo.

        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)  // 画实时差价曲线
            $.PlotLine("B2A", depthB.Bids[0].Price - depthA.Asks[0].Price)  // 第一个参数是曲线名称,第二个参数是曲线当前时刻的值,即当前时刻Y轴方向上的值
        }

De esta manera, con solo 4 líneas de código de dibujo, la estrategia puede mostrar un gráfico cuando se está ejecutando.

Función de cobertura unidireccional

Como se mencionó anteriormente, la línea de activación de la diferencia de precio se ha transformado en dos, controlandoA->BEl gatillo de la coberturaB->ALa cobertura se activa. De esta manera, no se puede utilizar el algoritmo de precio de orden anterior y en su lugar se utiliza el método de precio de mercado más deslizamiento.

        if (depthA.Bids[0].Price - depthB.Asks[0].Price > targetDiffPriceA2B && Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount) >= minHedgeAmount) {          // A -> B 盘口条件满足            
            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("触发A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[1].Balance * 0.8 / priceSell, nowAccs[0].Stocks)  // 提示信息
                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 盘口条件满足
            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("触发B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[0].Balance * 0.8 / priceBuy, nowAccs[1].Stocks)  // 提示信息
                hedge(exA, exB, priceBuy, priceSell, amount)
                cancelAll()
                lastKeepBalanceTS = 0
                isTrade = true 
            }            
        }

Dado que los precios de compra y venta se separan en dos datos, la función de coberturahedgeTambién es necesario modificarlo.

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 estos cambios, en los que no entraré aquí. Puedes consultar el código para obtener más detalles.

Modificar de forma interactiva parámetros como las líneas de spread de cobertura

Agregue interactividad a la estrategia para que esta pueda modificar la línea de activación del spread en tiempo real. Este es un requisito de diseño para una estrategia semiautomática, que también se implementa aquí como demostración didáctica. El diseño de la interacción de la estrategia también es muy sencillo. Primero, agregue controles interactivos a la estrategia en la página de edición de la estrategia.

Diseño de estrategia de cobertura de spot de moneda digital (2)

Se añaden dos controles, uno llamado A2B y otro llamado B2A. Después de ingresar un valor en el cuadro de entrada de control, haga clic en el botón en el lado derecho del cuadro de entrada. Se enviará inmediatamente una instrucción a la estrategia, por ejemplo: ingrese un valor en el cuadro de entrada123, haga clicA2BEste botón enviará inmediatamente instrucciones a la estrategia.

A2B:123

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

        // 交互
        var cmd = GetCommand()   // 每次循环执行到这里时,都检测有没有交互指令过来,没有则返回空字符串
        if (cmd) {               // 检测到有交互指令,例如:A2B:123
            Log("接收到命令:", cmd)
            var arr = cmd.split(":")   // 拆分出交互控件名称和输入框中的值,arr[0]就是A2B,arr[1]就是123
            if (arr[0] == "A2B") {     // 判断触发的交互控件是不是A2B
                Log("修改A2B的参数,", diffAsPercentage ? "参数为差价百分比" : "参数为差价:", arr[1])
                if (diffAsPercentage) {
                    hedgeDiffPercentageB2A = parseFloat(arr[1])     // 修改触发差价线
                } else {
                    hedgeDiffPriceA2B = parseFloat(arr[1])          // 修改触发差价线
                }
            } else if (arr[0] == "B2A") {           // 检测到触发的控件是B2A     
                Log("修改B2A的参数,", diffAsPercentage ? "参数为差价百分比" : "参数为差价:", arr[1])
                if (diffAsPercentage) {
                    hedgeDiffPercentageA2B = parseFloat(arr[1])
                } else {
                    hedgeDiffPriceB2A = parseFloat(arr[1])
                }
            }
        }

Organice la información de la barra de estado y muéstrela en forma de tabla

Haga que los datos de la barra de estado estén más organizados y sean más fáciles de observar.

        var tbl = {
            "type" : "table", 
            "title" : "数据", 
            "cols" : ["交易所", "币", "冻结币", "计价币", "冻结计价币", "触发差价", "当前差价"], 
            "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) + "`")

Diseño de estrategia de cobertura de spot de moneda digital (2)

Prueba retrospectiva

El backtesting es solo una prueba de estrategia y una detección preliminar de funciones. Muchos errores pueden ser realmente detectados durante la etapa de backtesting. No es necesario prestar demasiada atención a los resultados de las pruebas retrospectivas. La estrategia final aún debe probarse en un entorno real.

Diseño de estrategia de cobertura de spot de moneda digital (2)

Diseño de estrategia de cobertura de spot de moneda digital (2)

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