Discusión sobre el diseño de estrategias de alta frecuencia Magicamente modificado cosechador de ganancias

El autor:No lo sé., Creado: 2022-04-25 11:49:11, Actualizado: 2022-04-25 12:04:06

Discusión sobre el diseño de estrategias de alta frecuencia Magicamente modificado cosechador de ganancias

En los artículos anteriores, analizamos las ideas y la implementación de código de la versión spot original de la estrategia de cosechadora de ganancias de alta frecuencia.

Análisis de la cosechadora de ganancias (1) Análisis de la cosechadora de beneficios (2)

Muchos usuarios en el círculo de criptomonedas cuantitativas están muy preocupados por la estrategia desarrollada por un maestro llamadoImprimir dineroLa estrategia deImprimir dineroA partir de la observación y el análisis de muchos seguidores, se puede ver que la estrategia de alta frecuencia es similar al principio de la cosechadora de ganancias (el maestro Xiaocao también dijo que el principio de la estrategia de alta frecuencia es similar a la cosechadora de ganancias). Pero debe haber cierta sutileza que permita que una estrategia tenga una tasa de ganancia estable y una proporción apropiada de ganancias y pérdidas.

Por lo tanto, estaba tan emocionado que no pude evitar modificar mágicamente la estrategia, incluso el resultado y efecto de la estrategia mágicamente modificada no era nada frente a las estrategias desarrolladas por los maestros.

La cosechadora de beneficios mágicamente modificada

var TickInterval = 100

function LeeksReaper() {
    var self = {}
    self.numTick = 0
    self.lastTradeId = 0
    self.vol = 0
    self.askPrice = 0
    self.bidPrice = 0
    self.orderBook = {
        Asks: [],
        Bids: []
    }
    self.prices = []
    self.tradeOrderId = 0
    self.account = null
    self.buyPrice = 0
    self.sellPrice = 0
    self.state = 0
    self.depth = null

    self.updateTrades = function() {
        var trades = _C(exchange.GetTrades)
        if (self.prices.length == 0) {
            while (trades.length == 0) {
                trades = trades.concat(_C(exchange.GetTrades))
            }
            for (var i = 0; i < 15; i++) {
                self.prices[i] = trades[trades.length - 1].Price
            }
        }
        self.vol = 0.7 * self.vol + 0.3 * _.reduce(trades, function(mem, trade) {
            // Huobi not support trade.Id
            if ((trade.Id > self.lastTradeId) || (trade.Id == 0 && trade.Time > self.lastTradeId)) {
                self.lastTradeId = Math.max(trade.Id == 0 ? trade.Time : trade.Id, self.lastTradeId)
                mem += trade.Amount
            }
            return mem
        }, 0)

    }
    self.updateOrderBook = function() {
        var orderBook = _C(exchange.GetDepth)
        self.depth = orderBook
        self.buyPrice = orderBook.Bids[pendingLevel].Price
        self.sellPrice = orderBook.Asks[pendingLevel].Price
        self.orderBook = orderBook
        if (orderBook.Bids.length < 3 || orderBook.Asks.length < 3) {
            return
        }
        self.bidPrice = orderBook.Bids[0].Price * 0.618 + orderBook.Asks[0].Price * 0.382 + 0.01
        self.askPrice = orderBook.Bids[0].Price * 0.382 + orderBook.Asks[0].Price * 0.618 - 0.01
        self.prices.shift()
        self.prices.push(_N((orderBook.Bids[0].Price + orderBook.Asks[0].Price) * 0.15 +
            (orderBook.Bids[1].Price + orderBook.Asks[1].Price) * 0.1 +
            (orderBook.Bids[2].Price + orderBook.Asks[2].Price) * 0.1 +
            (orderBook.Bids[3].Price + orderBook.Asks[3].Price) * 0.075 +
            (orderBook.Bids[4].Price + orderBook.Asks[4].Price) * 0.05 +
            (orderBook.Bids[5].Price + orderBook.Asks[5].Price) * 0.025))
    }

    self.updateAccount = function() {
        var account = exchange.GetAccount()
        if (!account) {
            return
        }
        self.account = account
        LogProfit(parseFloat(account.Info.totalWalletBalance), account)
    }

    self.CancelAll = function() {
        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)
            }
            Sleep(100)
        }
    }

    self.poll = function() {
        self.numTick++
        self.updateTrades()
        self.updateOrderBook()
        var pos = _C(exchange.GetPosition)

        var burstPrice = self.prices[self.prices.length - 1] * burstThresholdPct
        var bull = false
        var bear = false
        LogStatus(_D(), "\n", 'Tick:', self.numTick, 'self.vol:', self.vol, ', lastPrice:', self.prices[self.prices.length - 1], ', burstPrice: ', burstPrice)

        if (self.numTick > 2 && (
                self.prices[self.prices.length - 1] - _.max(self.prices.slice(-6, -1)) > burstPrice ||
                self.prices[self.prices.length - 1] - _.max(self.prices.slice(-6, -2)) > burstPrice && self.prices[self.prices.length - 1] > self.prices[self.prices.length - 2]
            )) {
            bull = true
        } else if (self.numTick > 2 && (
                self.prices[self.prices.length - 1] - _.min(self.prices.slice(-6, -1)) < -burstPrice ||
                self.prices[self.prices.length - 1] - _.min(self.prices.slice(-6, -2)) < -burstPrice && self.prices[self.prices.length - 1] < self.prices[self.prices.length - 2]
            )) {
            bear = true            
        }

        if (pos.length != 0) {
            if (pos[0].Type == PD_LONG) {
                self.state = 1
            } else {
                self.state = 2
            }
        } else {
            self.state = 0
        }


        if ((!bull && !bear)) {
            return
        }

        if (bull) {
            var price = (self.state == 0 || self.state == 1) ? self.buyPrice : self.depth.Bids[coverPendingLevel].Price
            var amount = (self.state == 0 || self.state == 1) ? pendingAmount : pos[0].Amount
            exchange.SetDirection("buy")
            exchange.Buy(price, amount)
        } else if (bear) {
            var price = (self.state == 0 || self.state == 2) ? self.sellPrice : self.depth.Asks[coverPendingLevel].Price
            var amount = (self.state == 0 || self.state == 2) ? pendingAmount : pos[0].Amount
            exchange.SetDirection("sell")
            exchange.Sell(price, amount)                    
        }
        self.numTick = 0
        Sleep(TickInterval)
        self.CancelAll()
        self.updateAccount()
    }

    while (!self.account) {
        self.updateAccount()
        Sleep(500)
    }
    Log("self.account:", self.account)

    return self
}

function main() {
    LogProfitReset()
    exchange.SetPrecision(pricePrecision, amountPrecision)
    exchange.SetContractType("swap")
    var reaper = LeeksReaper()  
    while (true) {
        reaper.poll()
        Sleep(100)
    }
}

img

Idea de modificación

La estrategia está planeada para operar en el mercado de contratos de Binance USDT, que admite posiciones unidireccionales. Por lo tanto, la estrategia se modifica y diseña de acuerdo con las características de las posiciones unidireccionales (las posiciones unidireccionales son más convenientes para la modificación de la estrategia), y solo necesita considerar la compra y venta, no necesita pensar en cerrar posiciones. Esta forma de pensar también está más cerca de la versión al contado de la cosechadora de ganancias.

La estrategia mantiene básicamente el criterio original de ruptura de tendencia de precios a corto plazo y el rango de ruptura de precios a corto plazo está controlado por el parámetroburstThresholdPct. Según el criterio para determinar si el precio a corto plazo esbullo bienbear.

La estrategia elimina algunos módulos del original, como el módulo de balance. Una modificación bastante grande es cambiar la colocación de órdenes a órdenes pendientes en el libro de pedidos y esperando su ejecución. Se espera que abra posiciones a un coste relativamente bajo en un mercado caótico con un fuerte juego largo corto, siga la tendencia a corto plazo y cierre posiciones cuando la tendencia a corto plazo se invierta, y luego continúe con las órdenes pendientes y las posiciones abiertas a la inversa.

La estrategia elimina otro código inútil, por lo que es muy corta y simple. Aunque la estrategia es una estrategia no rentable, incluso con pérdidas, es un modelo muy fácil y útil para que un FMZer aprenda estrategias de alta frecuencia, observe las acciones de estrategias de alta frecuencia, observe las reglas microscópicas del mercado, etc. El comercio programado y cuantitativo debe basarse en mucha práctica, experiencia y teorías.

Corre en el bot

img

Se puede ver que es más difícil abrir y cerrar posiciones cuando la situación del mercado no es activa.

Optimización de la estrategia

En la actualidad, no se ha encontrado una buena dirección de optimización. Los estudiantes interesados pueden hablar activamente y discutirlo juntos.

Dirección estratégica:https://www.fmz.com/strategy/260806

La estrategia es sólo para el estudio; cuando el mercado es plano, ejecutarlo en el bot podría hacer pérdidas.


Más.