0bps

Strategy vault / Other

Magically Modified Leek Harvester

Strategy Articles:https://www.fmz.com/bbs-topic/6611

JavaScriptOther
Author
发明者量化-小小梦
Complexity
Intermediate · 157 lines
Parameters
6

Strategy Articles:https://www.fmz.com/bbs-topic/6611

Parameters

NameDefaultWhat it controls
burstThresholdPct0.0003Price Breakout Coefficient
pendingLevel9Pending order position
pricePrecision4Price Precision
amountPrecision2Order quantity accuracy
coverPendingLevel3Close Order Level
pendingAmount0.03Order Quantity

Source JavaScript

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)
    }
}

Published by 发明者量化-小小梦 on the FMZ strategy square · last modified 2021-04-19. Collected in the Quant Trading Vault. Unvalidated research: re-test with your own data and costs before trusting it.

Build this with AgenKit

A spec is not a trading system. Paste this into your coding agent and AgenKit runs a specialist team — architecture, test-first build, risk gates, review — with paper trading on by default.

in Claude Code, Cursor, Codex & 4 more
/agenkit build a production-grade trading bot with a backtest engine, risk controls and paper trading by default from strategies/Magically-Modified-Leek-Harvester.md
  1. npx agenkit install engineering-kit in your project
  2. Paste the command into your agent and approve each phase
  3. Get tests, backtest, risk controls and a paper-trading switch

Understand it first

Before you run this, read the lesson behind the idea and how to backtest it honestly. Specs like this one are the survivors of an unknown number of trials; deflate their results accordingly.

Related specs

esc

Try , , or .

↑↓ move↵ open