Анализ стратегии "пожирателя прибыли" (2)

Автор:Нинабадасс., Создано: 2022-04-26 15:57:02, Обновлено: 2022-04-26 15:57:53

Анализ стратегии "пожирателя прибыли" (2)

Давайте продолжим.Содержание последнегообъяснить.

Третья дополнительная функция:

    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("start to balance", 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("start to balance", 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)
                }
            }
        }
    }

Когда конструкторLeeksReaper()создает объект,balanceAccount()Функция, добавленная к объекту, используется для обновления информации об активах счета, которая хранится вself.account, то есть, чтобы построить атрибутaccountПросчитывать и печатать регулярно значение возврата. Затем, согласно последней информации о активах счета, рассчитывается соотношение баланса спотовых валютных символов (спотовый баланс позиции), и когда запускается порог смещения, закрываются небольшие ордера, чтобы вернуть символы (позиции) в равновесное состояние. Подождите определенный период времени для выполнения торговли, а затем отмените все ожидающие ордера и выполните функцию в следующем раунде, баланс будет снова обнаружен и будет произведена соответствующая обработка.

Давайте посмотрим на код этого указания функции по указанию: Во-первых, первое утверждение.var account = exchange.GetAccount()объявляет локальную переменнуюaccount, называетexchange.GetAccount()функция в FMZ API интерфейс, получить последние данные текущего счета и назначить его переменнойaccount. Тогда, судить переменнуюaccount; если значение переменной:null(что произойдет, когда не удастся получить переменную, такую как тайм-аут, сеть, исключение интерфейса платформы и т. д.), он вернется непосредственно (соответствующееif (!account ){...}здесь).

Заявлениеself.account = accountэто назначить локальную переменнуюaccountк атрибутуaccountпостроенного объекта для записи последней учетной информации в построенном объекте.

Заявлениеvar now = new Date().getTime()объявляет локальную переменнуюnow, и звонитgetTime()функция объекта времени и даты языка JavaScript для возвращения текущего временного знака и присвоения временного знака переменнойnow.

Код:if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)) {...}оценивает разницу между текущей временной меткой и последней записанной; если значение превышает параметрCalcNetInterval * 1000, это означает, что он превысилCalcNetInterval * 1000миллисекунды (CalcNetIntervalПоскольку цена покупки 1 на рынке должна быть использована при расчете прибыли, условие также ограничено условиемself.orderBook.Bids.length > 0(глубинные данные, которые должны быть действительны в списке заказов на покупку в качестве информации уровня).

Когда условие команды if запускается, выполняетсяself.preCalc = nowдля обновления переменной временной меткиself.preCalcот последней печатной прибыли на текущую датуnowЗдесь статистика прибыли использует метод расчета чистой стоимости, код:var net = _N(account.Balance + account.FrozenBalance + self.orderBook.Bids[0].Price * (account.Stocks + account.FrozenStocks)), то есть конвертировать валюту в актив (валюту котировки) в соответствии с текущей ценой покупки 1, а затем сложить ее вместе с суммой актива на счете и отнести ее к заявленной местной переменной.net. Определить, соответствует ли текущая общая чистая стоимость последней зафиксированной общей чистая стоимость:

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

Если это несовместимо, то естьnet != self.preNetэто верно, обновление атрибутаself.preNetкоторый записывает чистую стоимость сnetЗатем напечатать данные общая чистая стоимостьnetк графику кривой прибыли бота FMZ Quant Trading Platform (вы можете запроситьLogProfitфункция в документации FMZ API).

Если регулярное печать возвращения не запускается, то продолжить следующий процесс: записьaccount.Stocks(текущие доступные валютные символы на счете) иaccount.Balance(текущие доступные активы на счете) вself.btcиself.cnyВычислить соотношение смещения и назначить его, который записывается вself.p.

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

Алгоритм также очень прост, который рассчитывает, сколько процентов стоимости текущей валюты в общей чистой стоимости счета.

Так как вы оцениваете, когда валютный баланс (позиция) запускается? Здесь разработчик использует 50% вверх и вниз 2 процентных пункта в качестве буфера; если он превышает буфер, выполнять баланс, то есть, когдаself.p < 0.48Если вы думаете, что сумма валюты мала, каждый раз, когда цена увеличивается на 0,01, разместите три небольших ордера.self.p > 0.52, если вы думаете, что сумма валюты большая, ожидать небольшие заказы продать 1 цена на рынке.Sleep(BalanceTimeout), и отменить все заказы.

        var orders = exchange.GetOrders()                  # obtain all the current pending orders, and save them in the variable orders"
        if (orders) {                                      # if the variable "orders", which obtains all the current pending orders, is not null
            for (var i = 0; i < orders.length; i++) {      # use the loop to traverse "orders", and cancel the orders one by one 
                if (orders[i].Id != self.tradeOrderId) {
                    exchange.CancelOrder(orders[i].Id)     # call "exchange.CancelOrder", and cancel orders by "orders[i].Id"
                }
            }
        }

Четвертая добавленная функция:

Вот основная часть стратегии, главный момент.self.poll = function() {...}Мы также говорили об этом в предыдущей статье.main( )функция, начать выполнять; перед входом вwhileбесконечный цикл, мы используемvar reaper = LeeksReaper()чтобы построить объект сборщика прибыли, а затемReaper.poll()называется циклично вmain() function.

Вself.pollфункция начинает выполнять, и делает некоторые приготовления перед каждым циклом;self.numTick++увеличивает количество;self.updateTrades()обновляет последние данные о торговле на рынке и рассчитывает используемые соответствующие данные;self.updateOrderBook()обновляет данные рынка (книги заказов) и рассчитывает соответствующие данные;self.balanceAccount()проверяет баланс валюты (позиции).

        var burstPrice = self.prices[self.prices.length-1] * BurstThresholdPct   # calculate the burst price 
        var bull = false             # declare the variable marked by the bull market; the initial value is false
        var bear = false             # declare the variable marked by the bear market; the initial value is false
        var tradeAmount = 0          # declare the variable of trading amount; the initial value is 0

Далее, нам нужно судить, является ли текущий краткосрочный рынок быком или медведем.

        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
        }

Ты помнишь...self.updateOrderBook()Функция в предыдущей статье, в которой мы использовали алгоритм взвешенной средней для построения временных рядовpricesЭтот кусок кода использует три новые функции, а именно:_.min, _.max, slice, которые также очень легко понять.

  • _.min: Функция состоит в том, чтобы найти минимум в массиве параметров.

  • _.max: Функция состоит в том, чтобы найти максимум в массиве параметров.

  • slice: Эта функция является функцией члена объекта массива JavaScript. Она должна перехватывать и возвращать часть массива в соответствии с индексом. Например:

    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))    // it will intercept several elements from 4 to 1, and return a new array: [4,3,2,1]
    }
    

При этом условия для определения бычьего или медвежьего рынка следующие:

  • self.numTick > 2Должен быть истинным, то есть, если взрыв цены произойдет в новом раунде обнаружения, он должен быть вызван после по крайней мере трех раундов обнаружения и избежать запуска в начале.
  • Последние данные в цепочке ценself.prices, то есть разница между последними данными и максимальной или минимальной ценой вself.pricesмассив в предыдущем диапазоне должен прорваться черезburstPrice .

Если все условия верны, отметьтеbullилиbearкакtrue, и присвоить значение переменнойtradeAmount, и планирую сделку.

Затем, для параметраBurstThresholdVol, основываясь наself.volобновлен и рассчитан в предыдущемself.updateTrades()В соответствии с этой функцией принимается решение о сокращении интенсивности торговли (сокращении планируемого объема торговли).

        if (self.vol < BurstThresholdVol) {
            tradeAmount *= self.vol / BurstThresholdVol   // reduce the planned trading volume, and reduce it to the previous volume multiplied by "self.vol / BurstThresholdVol" 
        }
        
        if (self.numTick < 5) {
            tradeAmount *= 0.8      // reduced to 80% of the plan 
        }
        
        if (self.numTick < 10) {    // reduced to 80% of the plan
            tradeAmount *= 0.8
        }

Далее, судите, соответствуют ли торговый сигнал и объем торгов требованиям:

        if ((!bull && !bear) || tradeAmount < MinStock) {   # if it is not a bull market nor a bear market, or the planned trading volume "tradeAmount" is less than the minimum trading volume "MinStock" set by the parameter, the "poll" function returns directly without any trading operation
            return
        }

После вышесказанного приговора, исполнитеvar tradePrice = bull ? self.bidPrice : self.askPriceВ зависимости от того, является ли это медвежьим или бычьим рынком, установить торговую цену и назначить значение с соответствующей ценой заказа поставки.

Наконец, введитеwhileцикл; единственное условие остановки и выхода цикла:tradeAmount >= MinStock, то есть планируемый объем торгов меньше минимального объема торгов. В петле, в соответствии с текущим состояние бычьего рынка или состояние медвежьего рынка, выполнять заказ.orderId- Выполните.Sleep(200)Затем цикл оценивает, есть ли у вас какие-либо проблемы.orderIdявляется истинным (если заказ не выполняется, идентификатор заказа не будет возвращен, и условие if не будет задействовано). Если условие является истинным, получите идентификатор заказа и назначите егоself.tradeOrderId.

Заявление переменнойorderхранить данные о заказах с начальным значениемnull. Затем используйте петлю, чтобы получить данные заказа с идентификатором и определить, находится ли заказ в состоянии ожидания заказа; если он находится в состоянии ожидания заказа, отмените заказ с идентификатором; если он не находится в состоянии ожидания заказа, он выйдет из петли обнаружения.

                var order = null           // declare a variable to save the order data 
                while (true) {             // a while loop 
                    order = exchange.GetOrder(orderId)    // call "GetOrder" to query the order data with the ID of  orderId
                    if (order) {                          // if the order data is queried,and the query fails, the order is null, and "if" will not be triggered  
                        if (order.Status == ORDER_STATE_PENDING) {   // judge whether the current order status is pending order
                            exchange.CancelOrder(orderId)            // if the current order status is pending order, cancel the order 
                            Sleep(200)
                        } else {                                     // if not, execute "break" to break out of the while loop 
                            break
                        }
                    }
                }

Затем выполните следующий процесс:

                self.tradeOrderId = 0              // reset "self.tradeOrderId"
                tradeAmount -= order.DealAmount    // update "tradeAmount", and subtract the executed amount of the orders in the delivery order 
                tradeAmount *= 0.9                 // reduce the intensity of ordering  
                if (order.Status == ORDER_STATE_CANCELED) {     // if the order is canceled 
                    self.updateOrderBook()                      // update the data, including the order book data
                    while (bull && self.bidPrice - tradePrice > 0.1) {   // in a bull market, if the updated bid price exceeds the current trading price by 0.1, reduce the trading intensity, and slightly adjust the trading price 
                        tradeAmount *= 0.99
                        tradePrice += 0.1
                    }
                    while (bear && self.askPrice - tradePrice < -0.1) {  // in a bear market, if the updated ask price exceeds the current trading price by 0.1, reduce the trading intensity, and slightly adjust the trading price 
                        tradePrice -= 0.1
                    }
                }

Когда поток программы выходит изwhile (tradeAmount >= MinStock) {...}цикл, это означает, что выполнение процесса торговли ценовым взрывом завершено. Выполнитьself.numTick = 0, то есть, перезагрузитьself.numTickдо 0.

Последнее исполнение конструктораLeeksReaper()возвращаетselfобъектом, то есть, когдаvar reaper = LeeksReaper(), объект возвращается наreaper.

До сих пор мы проанализировали, какLeeksReaper()После прочтения статьи, я думаю, у вас будет более ясное понимание процесса алгоритма высокочастотного стратегии.


Больше