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.account
It's the same thing with the object you're building.account
Properties: ‧ 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.account
It 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.account
Variable. Then judge.account
This variable, if the variable isnull
The value (e.g. timeout, network, exchange interface abnormality etc. failure to obtain) is returned directly (corresponding)if (!account){...}
I'm not sure.
self.account = account
This is a local variable.account
It's the value of the object you're building.account
Attributes are used to record the most recent account information in the constructed object.
var now = new Date().getTime()
This statement is a local variable.now
The time and date objects are called in JavaScript.getTime()
The function returns the current time frame.now
Variable.
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 * 1000
This means that the number of users has increased since the last update.CalcNetInterval * 1000
MilisecondsCalcNetInterval
Seconds), 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 > 0
This condition ((depth data, the payroll list must have valid ranking information) ≠ When this if statement condition is triggered, executeself.preCalc = now
Update the time stamp variable for the most recent printed earningsself.preCalc
The current timelinenow
The 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.preNet
I mean, really.net
Variable updates are attributes used to record net worthself.preNet
And then print this.net
Total net worth data to inventors on the earnings curve chart of the Quantitative Trading Platform Robot (WEB can be consulted in the FMZ API documentationLogProfit
This 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.btc
,self.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.48
The 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.52
If 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, enterswhile
Before 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.poll
The 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?prices
Arrays. Three new functions are used in this code._.min
,_.max
,slice
The 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]
}
The conditions for judging a bear or a cow are:
self.numTick > 2
To 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.self.prices
The last data, which is the latest data, is the data of theself.prices
The maximum or minimum price difference in the previous range in the array must be broken.burstPrice
The price of this explosion.If all conditions are met, markbull
Orbear
, fortrue
, and givetradeAmount
Variable assignment, planned hip hop deals.
And then, based on the previousself.updateTrades()
Updated, calculated in the functionself.vol
, for the parametersBurstThresholdVol
Decide 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.askPrice
Depending 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 awhile
The only way to stop the loop is to jump out.tradeAmount >= MinStock
The 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.orderId
Is 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 dataorder
The initial assignment isnull
The 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 = 0
I'm going to reset it.self.numTick
This is 0.
LeeksReaper()
The final execution of the constructor functionself
The 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.
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.
Inventors quantify - small dreamsIn 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.
Inventors quantify - small dreamsI'm sorry, this article is mainly for beginners about the execution process, a bunch of nonsense is really eye-catching, you just ignore it.
Inventors quantify - small dreams great !~
Inventors quantify - small dreamsThe original cabbage harvester had a balance module that could be considered for removal.
Inventors quantify - small dreamsIt's not polite
Inventors quantify - small dreams♪ Oh, my ♪
Inventors quantify - small dreamsThis 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.
Inventors quantify - small dreamsThe principle should be pretty much the same.