How to Exploit Brainless Selling Bots with a High-Frequency Strategy in 80 Lines of Code
Tags: code, strategy, robot, fmzquant
Published: 2024-05-29 03:23:49

### Opportunity Observation
Recently, I found that Binance has a currency STORJ market is very strange unintentionally when I was watching the market, the trading volume is very large, and the trading frequency is very fast, the specific one-minute K-line of the following chart, we can see that the trading volume of each minute are consistent, and the minute K-line can be seen in a long lower shadow line.

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

Observe with Binance 1-second K-line, I found out the end of the story, someone is marketed 10,000-20,000 STORJs every 5-7s, regardless of the cost, and smashing a small hole in the K-line directly, while the price recovers in the short term. This operation was obviously caused by a robot on an iceberg commission. This selling operation lasted for a very long time, totaling an estimated $10 million level, and in many cases caused slippage of up to 0.1%, which means that the executor of this strategy lost tens of thousands of dollars in slippage on the trade only. But with such a mechanical operation and active trading, there was a clear opportunity for market making scalping.

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

A simple change to the original spot HF strategy, and in a few minutes I got this bot that specializes in exploiting this brainless sale of iceberg commissions.

### Strategy Idea
Since the market sells in market price every few seconds, we just need to find the 10k depth in the buy order book and hang the order in front of it. So that when the iceberg sells, a high probability that the market-making robot just can receive, and at this time the transaction is very active, the momentary price decline also triggered some buy orders. By the same token, hanging sell orders can be thrown in the trend, so repeated operations. The frequency of transactions is very high, even if each time the yield is not large, the total return is also quite substantial. Of course, the premise of everything is to have a low-fee account, if the buying and selling fees both are 0.1%, then the space is not enough to pay the fees.

### Strategy Performance
The strategy is performing as follows, at first, none of the profits were printing, so I changed it this afternoon, and print out the profits, the crazy selling robots have changed the volume to about 5000 at a time, so it's past the optimal time for arbitrage. I'm probably making 100-200U per hour at first, the key is risk free and low cost. On the flip side, the iceberg commission actually has a lot of skills, if you know how to write a strategy, you can spend ten minutes on FMZ to write the iceberg commission strategy that observes the depth of the buy order to decide the size and price of the order, observes the size of the active buy order to adjust the size of the pending order and take up the market monitoring and other characteristics, saving tens of thousands of dollars easily.

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

### Strategy Source Code
The strategy code is very simple, only 80 lines, which is suitable for beginners, here are some of the parameters such as order precision and so on written fixed in the program, you can change the parameters as follows. It is recommended to save it, in case of any exchange trading pairs or the traders are out of control, you can fell free to charge them some interest at any time.

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

```
function CancelPendingOrders() {
    var orders = _C(exchange.GetOrders)
    for (var j = 0; j < orders.length; j++) {
        exchange.CancelOrder(orders[j].Id, orders[j])
    }
}

function onexit(){
    CancelPendingOrders()
}

function GetPrice(Type, Depth) {
    var sumAmount = 0
    var checkAmount = Type == "Buy" ? CheckBuyAmount : CheckSellAmount
    var deep = Type == "Buy" ? Depth.Bids : Depth.Asks
    for(var i = 0; i < Math.min(20, deep.length); i++) {
        if(Type == "Buy"  && deep[i].Price == lastBuyPrice && buyId){
            sumAmount += deep[i].Amount - amountBuy //Subtract your own pending orders here
        }else if(Type == "Sell"  && deep[i].Price == lastSellPrice && sellId){
            sumAmount += deep[i].Amount - amountSell
        }else{
            sumAmount += deep[i].Amount
        }
        if(sumAmount >= checkAmount){
            return deep[i].Price
        }
    }
    return deep[19].Price
}

function OnTick() {
    var depth = _C(exchange.GetDepth)
    var buyPrice = _N(Math.min(GetPrice("Buy", depth) + 0.0001, depth.Asks[0].Price-0.0001) , 4) //Guaranteed at the market
    var sellPrice = _N(Math.max(GetPrice("Sell", depth) - 0.0001, depth.Bids[0].Price+0.0001), 4)
    LogStatus('buy_price:'+buyPrice, '  sell price: '+sellPrice)
    if ((sellPrice - buyPrice) < DiffPrice) {
        buyPrice = 0
    }
    if(sellPrice != lastSellPrice && sellId){
        exchange.CancelOrder(sellId);
        sellId = 0
        lastSellPrice = 0
    }
    if(buyPrice != lastBuyPrice && buyId){
        exchange.CancelOrder(buyId);
        buyId = 0
        lastBuyPrice = 0
    }   
    var acc = _C(exchange.GetAccount)
    if(account.Stocks+account.FrozenStocks != acc.Stocks+acc.FrozenStocks){
        LogProfit((acc.Stocks+acc.FrozenStocks)*depth.Bids[0].Price+acc.Balance+acc.FrozenBalance - 2000)
        Log('free '+acc.Stocks, ' lock: '+ acc.FrozenStocks, ' total: ' , (acc.Stocks+acc.FrozenStocks)*depth.Bids[0].Price+acc.Balance+acc.FrozenBalance)
    }
    account = acc
    amountBuy = _N(Math.min(account.Balance / buyPrice - 0.1, Amount), 0)
    amountSell = _N(account.Stocks, 0)
    if (sellPrice > 0 && amountSell > 40 && sellId == 0) {
        sellId = exchange.Sell(_N(sellPrice,4), amountSell)
        lastSellPrice = sellPrice
    }
    if (buyPrice>0 && amountBuy > 40 && buyId == 0) {
        buyId = exchange.Buy(_N(buyPrice,4), amountBuy)
        lastBuyPrice = buyPrice
    }
    Sleep(Interval)
}
var account = {Stocks:0, FrozenStocks:0, Balance:0, FrozenBalance:0}
var buyId = 0
var sellId = 0
var lastBuyPrice = 0
var lastSellPrice = 0
var amountSell = 0
var amountBuy = 0
var log_account_time = 0
function main() {
    CancelPendingOrders()
    while (true) {
        OnTick()
    }
}
```

From: https://blog.mathquant.com/2023/12/25/how-to-exploit-brainless-selling-bots-with-a-high-frequency-strategy-in-80-lines-of-code.html