Давайте продолжим.Содержание последнегообъяснить.
Третья дополнительная функция:
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
(глубинные данные, которые должны быть действительны в списке заказов на покупку в качестве информации уровня).
Когда условие команды 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
является истинным (если заказ не выполняется, идентификатор заказа не будет возвращен, и условие 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()
После прочтения статьи, я думаю, у вас будет более ясное понимание процесса алгоритма высокочастотного стратегии.