Ejemplo de diseño de la estrategia dYdX

El autor:- ¿ Por qué?, Creado: 2022-11-07 10:59:29, Actualizado: 2023-09-15 21:03:43

img

En respuesta a la demanda de muchos usuarios, la plataforma FMZ ha accedido recientemente a dYdX, un intercambio descentralizado. Alguien que tenga estrategias puede disfrutar del proceso de adquisición de moneda digital dYdX. Solo quería escribir una estrategia de negociación estocástica hace mucho tiempo, no importa si obtiene ganancias. Así que a continuación nos reunimos para diseñar una estrategia de intercambio estocástica, sin importar si la estrategia funciona bien o no, solo aprendemos el diseño de la estrategia.

Diseño de la estrategia de negociación estocástica

Vamos a tener una lluvia de ideas! Se planea diseñar una estrategia de colocar órdenes al azar con indicadores y precios aleatorios. Poner órdenes no es más que ir largo o ir corto, sólo apostando a la probabilidad. Luego usaremos el número aleatorio 1 ~ 100 para determinar si ir largo o ir corto.

Condición para hacer el largo: número aleatorio 1~50. Condición para el cortocircuito: número aleatorio 51~100.

Por lo tanto, tanto ir largo como ir corto son 50 números. A continuación, pensemos en cómo cerrar la posición, ya que es una apuesta, entonces debe haber un criterio para ganar o perder. Establecemos un criterio para stop de ganancia y pérdida fijos en la transacción. Stop de ganancia para ganar, stop de pérdida para perder. En cuanto a la cantidad de stop de ganancia y pérdida, en realidad es el impacto de la relación de ganancia y pérdida, oh sí!

El comercio no es libre de costos, hay suficiente deslizamiento, comisiones, etc. para tirar nuestra tasa de ganancia de comercio estocástico hacia el lado de menos del 50%. Así que, ¿cómo diseñar continuamente? ¿Qué tal diseñar un multiplicador para aumentar la posición? ya que es una apuesta, entonces la probabilidad de perder por 8 ~ 10 veces en una fila de operaciones aleatorias debe ser baja. Así que la primera transacción fue diseñada para colocar una pequeña cantidad de órdenes, lo más pequeño posible. Luego, si pierdo, voy a aumentar la cantidad de órdenes y seguir colocando órdenes al azar.

Está bien, la estrategia está diseñada de manera simple.

Código fuente diseñado:

var openPrice = 0 
var ratio = 1
var totalEq = null 
var nowEq = null 

function cancelAll() {
    while (1) {
        var orders = _C(exchange.GetOrders)
        if (orders.length == 0) {
            break
        }
        for (var i = 0 ; i < orders.length ; i++) {
            exchange.CancelOrder(orders[i].Id, orders[i])
            Sleep(500)
        }
        Sleep(500)
    }
}

function main() {
    if (isReset) {
        _G(null)
        LogReset(1)
        LogProfitReset()
        LogVacuum()
        Log("reset all data", "#FF0000")
    }

    exchange.SetContractType(ct)

    var initPos = _C(exchange.GetPosition)
    if (initPos.length != 0) {
        throw "Strategy starts with a position!"
    }
    
    exchange.SetPrecision(pricePrecision, amountPrecision)
    Log("set the pricePrecision", pricePrecision, amountPrecision)
    
    if (!IsVirtual()) {
        var recoverTotalEq = _G("totalEq")
        if (!recoverTotalEq) {
            var currTotalEq = _C(exchange.GetAccount).Balance   // equity
            if (currTotalEq) {
                totalEq = currTotalEq
                _G("totalEq", currTotalEq)
            } else {
                throw "failed to obtain initial interest"
            }
        } else {
            totalEq = recoverTotalEq
        }
    } else {
        totalEq = _C(exchange.GetAccount).Balance
    }
    
    while (1) {
        if (openPrice == 0) {
            // Update account information and calculate profits
            var nowAcc = _C(exchange.GetAccount)
            nowEq = IsVirtual() ? nowAcc.Balance : nowAcc.Balance  // equity
            LogProfit(nowEq - totalEq, nowAcc)
            
            var direction = Math.floor((Math.random()*100)+1)   // 1~50 , 51~100
            var depth = _C(exchange.GetDepth)
            if (depth.Asks.length <= 2 || depth.Bids.length <= 2) {
                Sleep(1000)
                continue 
            }
            if (direction > 50) {
                // long
                openPrice = depth.Bids[1].Price
                exchange.SetDirection("buy")
                exchange.Buy(Math.abs(openPrice) + slidePrice, amount * ratio)
            } else {
                // short
                openPrice = -depth.Asks[1].Price
                exchange.SetDirection("sell")
                exchange.Sell(Math.abs(openPrice) - slidePrice, amount * ratio)
            }       
            Log("place", direction > 50 ? "buying order" : "selling order", ", price:", Math.abs(openPrice))
            continue
        }

        var orders = _C(exchange.GetOrders)
        if (orders.length == 0) {
            var pos = _C(exchange.GetPosition)
            if (pos.length == 0) {
                openPrice = 0
                continue
            }
            
            // Test for closing the position
            while (1) {
                var depth = _C(exchange.GetDepth)
                if (depth.Asks.length <= 2 || depth.Bids.length <= 2) {
                    Sleep(1000)
                    continue 
                }
                var stopLossPrice = openPrice > 0 ? Math.abs(openPrice) - stopLoss : Math.abs(openPrice) + stopLoss 
                var stopProfitPrice = openPrice > 0 ? Math.abs(openPrice) + stopProfit : Math.abs(openPrice) - stopProfit
                var winOrLoss = 0 // 1 win , -1 loss 
                
                // drawing the line
                $.PlotLine("bid", depth.Bids[0].Price)
                $.PlotLine("ask", depth.Asks[0].Price)
                
                // stop loss
                if (openPrice > 0 && depth.Bids[0].Price < stopLossPrice) {
                    exchange.SetDirection("closebuy")
                    exchange.Sell(depth.Bids[0].Price - slidePrice, pos[0].Amount)
                    winOrLoss = -1
                } else if (openPrice < 0 && depth.Asks[0].Price > stopLossPrice) {
                    exchange.SetDirection("closesell")
                    exchange.Buy(depth.Asks[0].Price + slidePrice, pos[0].Amount)
                    winOrLoss = -1
                }
                
                // stop profit
                if (openPrice > 0 && depth.Bids[0].Price > stopProfitPrice) {
                    exchange.SetDirection("closebuy")
                    exchange.Sell(depth.Bids[0].Price - slidePrice, pos[0].Amount)  
                    winOrLoss = 1
                } else if (openPrice < 0 && depth.Asks[0].Price < stopProfitPrice) {
                    exchange.SetDirection("closesell")
                    exchange.Buy(depth.Asks[0].Price + slidePrice, pos[0].Amount)
                    winOrLoss = 1
                }
                
                // Test the pending orders
                Sleep(2000)
                var orders = _C(exchange.GetOrders)                
                if (orders.length == 0) {
                    pos = _C(exchange.GetPosition)
                    if (pos.length == 0) {
                        if (winOrLoss == -1) {
                            ratio++
                        } else if (winOrLoss == 1) {
                            ratio = 1
                        }
                        break
                    }                    
                } else {
                    // cancel pending orders
                    cancelAll()
                    Sleep(2000)
                    pos = _C(exchange.GetPosition)
                    // update the position after cancellation, and check it again
                    if (pos.length == 0) {
                        if (winOrLoss == -1) {
                            ratio++
                        } else if (winOrLoss == 1) {
                            ratio = 1
                        }
                        break
                    }    
                }
                
                var tbl = {
                    "type" : "table", 
                    "title" : "info", 
                    "cols" : ["totalEq", "nowEq", "openPrice", "bid1Price", "ask1Price", "ratio", "pos.length"], 
                    "rows" : [], 
                }
                tbl.rows.push([totalEq, nowEq, Math.abs(openPrice), depth.Bids[0].Price, depth.Asks[0].Price, ratio, pos.length])
                tbl.rows.push(["pos", "type", "amount", "price", "--", "--", "--"])
                for (var j = 0 ; j < pos.length ; j++) {
                    tbl.rows.push([j, pos[j].Type, pos[j].Amount, pos[j].Price, "--", "--", "--"])
                }
                LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")
            }
        } else {
            // cancel the pending orders
            // reset openPrice
            cancelAll()
            openPrice = 0
        }
        Sleep(1000)
    }
}

Parámetros de la estrategia:

img

La estrategia necesita un nombre, vamos a llamarlo adivina el tamaño (versión dYdX) .

Prueba de retroceso

Las pruebas de retroceso son sólo para referencia, >_

img

img

img

img

La prueba de retroceso ha terminado, no hay ningún error.

Esta estrategia se utiliza para el aprendizaje y la referencia sólo, no lo use en el bot real!


Relacionados

Más.