How to analyze cabbage harvesters (2)

Author: The Little Dream, Created: 2020-11-16 10:03:52, Updated: 2023-09-26 21:05:07

img

How to analyze cabbage harvesters (2)

And thenUp and BackI'm not going to lie.

The third function added:

    self.balanceAccount = function() {
        var account = exchange.GetAccount()
        if (!account) {
            return
        }
        self.account = account
        var now = new Date().getTime()
        if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)) {
            self.preCalc = now
            var net = _N(account.Balance + account.FrozenBalance + self.orderBook.Bids[0].Price * (account.Stocks + account.FrozenStocks))
            if (net != self.preNet) {
                self.preNet = net
                LogProfit(net)
            }
        }
        self.btc = account.Stocks
        self.cny = account.Balance
        self.p = self.btc * self.prices[self.prices.length-1] / (self.btc * self.prices[self.prices.length-1] + self.cny)
        var balanced = false
        
        if (self.p < 0.48) {
            Log("开始平衡", self.p)
            self.cny -= 300
            if (self.orderBook.Bids.length >0) {
                exchange.Buy(self.orderBook.Bids[0].Price + 0.00, 0.01)
                exchange.Buy(self.orderBook.Bids[0].Price + 0.01, 0.01)
                exchange.Buy(self.orderBook.Bids[0].Price + 0.02, 0.01)
            }
        } else if (self.p > 0.52) {
            Log("开始平衡", self.p)
            self.btc -= 0.03
            if (self.orderBook.Asks.length >0) {
                exchange.Sell(self.orderBook.Asks[0].Price - 0.00, 0.01)
                exchange.Sell(self.orderBook.Asks[0].Price - 0.01, 0.01)
                exchange.Sell(self.orderBook.Asks[0].Price - 0.02, 0.01)
            }
        }
        Sleep(BalanceTimeout)
        var orders = exchange.GetOrders()
        if (orders) {
            for (var i = 0; i < orders.length; i++) {
                if (orders[i].Id != self.tradeOrderId) {
                    exchange.CancelOrder(orders[i].Id)
                }
            }
        }
    }

Construction of functionsLeeksReaper()When you build an object, you add to it.balanceAccount()The function is to update the account asset information, storeself.accountIt's the same thing with the object you're building.accountProperties: ‧ Timely calculation of the return value and printing‧ Next, based on the latest account asset information, calculate the cash balance ratio (cash position balance) and, when the deviation of the threshold is triggered, make a small order settlement to return the coin (position) to balance. Wait for a certain time to trade, then cancel all pending orders, the next round of execution of the function will again detect the balance and make the corresponding processing.

Let's look at the code for this function word for word: First, the first sentence.var account = exchange.GetAccount()This is a local variable.accountIt also calls the Inventor API.exchange.GetAccount()The function, which gets the latest data for the current account, assigns a value to the current account.accountVariable. Then judge.accountThis variable, if the variable isnullThe value (e.g. timeout, network, exchange interface abnormality etc. failure to obtain) is returned directly (corresponding)if (!account){...}I'm not sure.

self.account = accountThis is a local variable.accountIt's the value of the object you're building.accountAttributes are used to record the most recent account information in the constructed object.

var now = new Date().getTime()This statement is a local variable.nowThe time and date objects are called in JavaScript.getTime()The function returns the current time frame.nowVariable.

if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)) {...}This code determines the difference between the current time stamp and the last time stamp recorded if it exceeds the parameter.CalcNetInterval * 1000This means that the number of users has increased since the last update.CalcNetInterval * 1000MilisecondsCalcNetIntervalSeconds), which enables timed printing of earnings, and is also limited in terms of the price at which the earnings are calculated.self.orderBook.Bids.length > 0This condition ((depth data, the payroll list must have valid ranking information) ≠ When this if statement condition is triggered, executeself.preCalc = nowUpdate the time stamp variable for the most recent printed earningsself.preCalcThe current timelinenowThe earnings statistics here are based on the net worth calculation method, which is coded asvar net = _N(account.Balance + account.FrozenBalance + self.orderBook.Bids[0].Price * (account.Stocks + account.FrozenStocks))This is the conversion of a currency into money at the current purchase price (the "currency") and the local variable that is assigned to the declaration, together with the number of money in the account.net◦ Judging whether the current total net worth is consistent with the last recorded total net worth:

            if (net != self.preNet) {
                self.preNet = net
                LogProfit(net)
            }

If it doesn't match,net != self.preNetI mean, really.netVariable updates are attributes used to record net worthself.preNetAnd then print this.netTotal net worth data to inventors on the earnings curve chart of the Quantitative Trading Platform Robot (WEB can be consulted in the FMZ API documentationLogProfitThis function) ⋅

If you don't trigger the timed printing revenue, then continue with the following process, and you'll get the result.account.Stocks(How many coins are available in the current account)account.Balance(current account available money) recorded inself.btcself.cny❖ Calculate the deviation ratio and assign a record of the deviationself.p

self.p = self.btc * self.prices[self.prices.length-1] / (self.btc * self.prices[self.prices.length-1] + self.cny)

The algorithm is also very simple, it calculates the current value of the coin as a percentage of the total net worth of the account.

So, what is the determination of when to trigger the currency's (position) balance? The authors here buffer at 50% up and down by 2 percentage points, exceeding the buffer zone execution balance, i.e.self.p < 0.48The currency balance deviation is triggered by the belief that there is a shortage of coins, and the price increases by 0.01 each time a position is purchased in the market, placing three slips.self.p > 0.52If you think that you have more, you sell a note in the marketplace.Sleep(BalanceTimeout)I'm not sure if I'll be able to make it.

        var orders = exchange.GetOrders()                  # 获取当前所有挂单,存在orders变量
        if (orders) {                                      # 如果获取当前挂单数据的变量orders不为null
            for (var i = 0; i < orders.length; i++) {      # 循环遍历orders,逐个取消订单
                if (orders[i].Id != self.tradeOrderId) {
                    exchange.CancelOrder(orders[i].Id)     # 调用exchange.CancelOrder,根据orders[i].Id取消订单
                }
            }
        }

The fourth function added:

The key part of the strategy, the big game, is coming up.self.poll = function() {...}The function is the main logic of the whole strategy, and we talked about it in the previous article, in themain()The function starts executing, enterswhileBefore the death cycle, we usedvar reaper = LeeksReaper()So we built a cabbage harvester object, and we put it in a box.main()Loop calls in functionsreaper.poll()This is the function to be called.

self.pollThe function starts to execute, doing some preparation before each cycle, and then the function starts to execute.self.numTick++I'm not sure what to do.self.updateTrades()Updates the most recent market transaction records and calculates the relevant usage data.self.updateOrderBook()Updating the discounted (or low) order data and calculating the relevant data.self.balanceAccount()Check the balance of the coin.

        var burstPrice = self.prices[self.prices.length-1] * BurstThresholdPct   # 计算爆发价格
        var bull = false             # 声明牛市标记的变量,初始为假
        var bear = false             # 声明熊市标记的变量,初始为假
        var tradeAmount = 0          # 声明交易数量变量,初始为0

The next step is to decide whether the current short-term market is bull or bear.

        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
            tradeAmount = self.cny / self.bidPrice * 0.99
        } 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
            tradeAmount = self.btc
        }

Remember, in the previous article,self.updateOrderBook()So what's the function, where we're using a weighted average algorithm to construct a sequence of time in the order that we're going to do it?pricesArrays. Three new functions are used in this code._.min_.maxsliceThe three functions are also very well understood.

  • _.min: function is the smallest value in the parameter array to be found.

  • _.max: function is to find the largest value in the array of parameters.

  • slice: This is a member function of a JavaScript array object that returns a portion of the array that is indexed, for example:

    function main() {
        // index     .. -8 -7 -6 -5 -4 -3 -2 -1
        var arr = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
        Log(arr.slice(-5, -1))    // 会截取 4 ~ 1 这几个元素,返回一个新数组:[4,3,2,1]
    }
    

    img

The conditions for judging a bear or a cow are:

  • self.numTick > 2To be established, that is, to be triggered at least three rounds of testing before a new round of testing price is triggered, to avoid triggering at the beginning.
  • Price sequenceself.pricesThe last data, which is the latest data, is the data of theself.pricesThe maximum or minimum price difference in the previous range in the array must be broken.burstPriceThe price of this explosion.

If all conditions are met, markbullOrbear, fortrue, and givetradeAmountVariable assignment, planned hip hop deals.

And then, based on the previousself.updateTrades()Updated, calculated in the functionself.vol, for the parametersBurstThresholdVolDecide whether to reduce the volume of transactions (i.e. reduce the amount of planned transactions).

        if (self.vol < BurstThresholdVol) {
            tradeAmount *= self.vol / BurstThresholdVol   // 缩减计划交易量,缩减为之前量的self.vol / BurstThresholdVol 倍
        }
        
        if (self.numTick < 5) {
            tradeAmount *= 0.8      // 缩减为计划的80%
        }
        
        if (self.numTick < 10) {    // 缩减为计划的80%
            tradeAmount *= 0.8
        }

The next step is to determine whether the trading signal or volume meets the requirements:

        if ((!bull && !bear) || tradeAmount < MinStock) {   # 如果非牛市并且也非熊市,或者计划交易的量tradeAmount小于参数设置的最小交易量MinStock,poll函数直接返回,不做交易操作
            return
        }

After passing the above judgement, executevar tradePrice = bull ? self.bidPrice : self.askPriceDepending on whether it's a bear market or a bull market, set the transaction price and assign the corresponding bid price.

Finally, we get into awhileThe only way to stop the loop is to jump out.tradeAmount >= MinStockThe amount of planned transactions is less than the minimum amount of transactions. In the loop, execute the following order according to the current bull market or bear market status; and record the single ID in the variableorderId◎ After ordering each cycleSleep(200)Wait for 200 milliseconds.orderIdIs true (if the condition is true, the if condition will not be triggered if the order ID is not returned if the order fails); if true, the order ID is assigned toself.tradeOrderId

Declare a variable to store order dataorderThe initial assignment isnullThe loop then retrieves the order data for this ID and determines whether the order is in the pending state, if it is in the pending state, cancel the order for this ID, if it is not in the pending state, skip this detection loop.

                var order = null           // 声明一个变量用于保存订单数据
                while (true) {             // 一个while循环
                    order = exchange.GetOrder(orderId)    // 调用GetOrder查询订单ID为 orderId的订单数据
                    if (order) {                          // 如果查询到订单数据,查询失败order为null,不会触发当前if条件
                        if (order.Status == ORDER_STATE_PENDING) {   // 判断订单状态是不是正在挂单中
                            exchange.CancelOrder(orderId)            // 如果当前正在挂单,取消该订单
                            Sleep(200)
                        } else {                                     // 否则执行break跳出当前while循环
                            break
                        }
                    }
                }

The following process is followed:

                self.tradeOrderId = 0              // 重置self.tradeOrderId
                tradeAmount -= order.DealAmount    // 更新tradeAmount,减去提单的订单已经成交的数量
                tradeAmount *= 0.9                 // 减小下单力度
                if (order.Status == ORDER_STATE_CANCELED) {     // 如果订单已经是取消了
                    self.updateOrderBook()                      // 更新订单薄等数据
                    while (bull && self.bidPrice - tradePrice > 0.1) {   // 牛市时,更新后的提单价格超过当前交易价格0.1就减小交易力度,略微调整交易价格
                        tradeAmount *= 0.99
                        tradePrice += 0.1
                    }
                    while (bear && self.askPrice - tradePrice < -0.1) {  // 熊市时,更新后的提单价格超过当前交易价格0.1就减小交易力度,略微调整交易价格
                        tradeAmount *= 0.99
                        tradePrice -= 0.1
                    }
                }

When the program process jumps outwhile (tradeAmount >= MinStock) {...}This cycle indicates that the execution of this price burst transaction process is complete. Executionself.numTick = 0I'm going to reset it.self.numTickThis is 0.

LeeksReaper()The final execution of the constructor functionselfThe object returns, which isvar reaper = LeeksReaper()I'm going to give it back to you.reaper

So farLeeksReaper()We have analyzed how the constructor functions construct this Cabbage Harvester object as well as the various methods of the Cabbage Harvester object, the execution process of the main logic functions, and we believe that after reading this article you should have a clearer understanding of this high-frequency strategy algorithm process.


More

xukittyThank you, Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr. Dr.

mattzhang1988He said a bunch of nonsense.

CyndiYY1024There is a bit of confusion about why it is necessary to keep the currency and money in balance, and if the balance is not reached, you have to buy and sell. After the Balance Timeout, the order is canceled again, no longer balanced, but goes to the next burst link.

The power of DamascusWhere's the next commandment?

EddieIn the cloud fog that I saw earlier, I used an FMZ and re-watched it again. Monitoring price fluctuations, detecting price bursts, following the direction of the trend, calculating the percentage of the hacks using the size of the transaction as a reference, performing hacks. Did I not say that, Dream General?

xukittyPlease tell me, how will the balance account (s) process evolve if we remove the balance account (s)?

xukittyThanks to Dreamz, FMZ is a real treasure trove.

printbtcI don't know.

How are you?What's this parameter called BurstThresholdVol? How do I set it?

evan1987It's full of details, and I've watched it for an hour and can barely understand the details.

rootmeI'm going to try to write a celery harvester that's the same as print money.

The Little DreamIn an article, Grasshopper said that high-frequency requires a market environment. Strategically, cabbage harvesters and Grasshopper's high-frequency robots have a lot in common.

The Little DreamI'm sorry, this article is mainly for beginners about the execution process, a bunch of nonsense is really eye-catching, you just ignore it.

The Little Dream great !~

The Little DreamThe original cabbage harvester had a balance module that could be considered for removal.

The Little DreamIt's not polite

The Little Dream♪ Oh, my ♪

The Little DreamThis is a policy parameter, which is set by humans, look at the policy, the article in detail, and you will know what this variable controls.

The Little DreamThe principle should be pretty much the same.