Explore High-frequency Strategy Design from the Magic Change of LeeksReaper
Tags: leeksreaper, strategy, fmzquant, trading
Published: 2024-05-06 09:09:35

In previous articles, we have analyzed the idea and code implementation of the high-frequency strategy of the original spot version LeeksReaper.

LeeksReaper Strategy Analysis(1)（https://www.fmz.com/bbs-topic/9725）
LeeksReaper Strategy Analysis(2)（https://www.fmz.com/bbs-topic/9733）

Many users of the digital currency pay more attention to the strategy of the printmoney leader.The strategy of the print money leader is traded in the Binance USDT contract. It can be seen from observation and analysis of many followers that this high-frequency strategy is similar to the principle of LeeksReaper (leader Xiaocao also said that the principle of high-frequency strategies is similar). But there must be something subtle to achieve a stable winning rate and an appropriate profit and loss ratio.

Therefore, I could not help but make the magic change. Although the strategy effect of the magic change was much worse than the strategies of the leaders. It is also a learning practice for high-frequency strategies. FMZer who are interested in shall discuss and learn together.

### LeeksReaper after the magic change
```
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)
    }
}
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rpupsun7cq9cyq5bun4u.png)

### The idea of strategy modification
The strategy is to plan to trade in the Binance USDT contract market, which supports one-way positions. Therefore, the strategy is modified according to the characteristics of one-way position (one-way position is more convenient to modify the strategy) , we do not consider closing the position, we only consider the sell and purchase. The idea is closer to the spot version of the LeeksReaper.

The strategy basically retains the original criterion of short-term price trend breakthrough, which is controlled by the parameter burstThresholdPCT, according to which to judge whether the short-term price is bull or bear.

The strategy eliminates some of the original modules, such as the balance module. The larger change is the makers in the order book, waiting for transaction.
It is expected is to open a position at a lower cost in a chaotic long/short game, follow the short-term trend, and close the position when the short-term trend reverses and continue to open the position with a reverse pending order.

The strategy is short and simple because it removed other useless code. Although strategy is a strategy that does not make money, or even lose money, but as FMZer who are learning high-frequency strategy, observing the behavior of high-frequency strategy, observing the micro-laws of the market is a model that can be used. Program trading and quantitative trading need a lot of practice, experience, theory as a basis.

### Strategy optimization
At present, no good direction for optimization has been found.
Someone who are interested can leave your comments and discuss together.

Strategy from: https://www.fmz.com/strategy/260806

This strategy is only for learning, the real bot may have losses when the market is not very optimistic.

From: https://blog.mathquant.com/2022/11/07/explore-high-frequency-strategy-design-from-the-magic-change-of-leeksreaper.html