Hãy tiếp tụcnội dung của lần cuối cùngđể giải thích.
Chức năng bổ sung thứ ba:
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)
}
}
}
}
Khi người xây dựngLeeksReaper()
là xây dựng một đối tượng,balanceAccount()
chức năng được thêm vào đối tượng được sử dụng để cập nhật thông tin tài sản tài khoản, được lưu trữ trongself.account
, đó là để xây dựng thuộc tínhaccount
của đối tượng. Tính toán và in giá trị lợi nhuận thường xuyên. Sau đó, theo thông tin tài sản tài khoản mới nhất, tỷ lệ số dư của các biểu tượng tiền mặt tại chỗ (tỷ lệ số dư vị trí tại chỗ) được tính toán, và khi ngưỡng offset được kích hoạt, các lệnh nhỏ được đóng để làm cho các biểu tượng (vị trí) trở lại trạng thái cân bằng. Chờ một khoảng thời gian nhất định để thực hiện giao dịch, và sau đó hủy tất cả các lệnh đang chờ, và thực hiện chức năng trong vòng tiếp theo, số dư sẽ được phát hiện lại và xử lý tương ứng sẽ được thực hiện.
Hãy xem mã của câu lệnh hàm này theo câu lệnh:
Trước hết, câu đầu tiênvar account = exchange.GetAccount()
tuyên bố một biến địa phươngaccount
, gọi làexchange.GetAccount()
chức năng trong giao diện FMZ API, nhận dữ liệu mới nhất của tài khoản hiện tại và gán nó cho biếnaccount
. Sau đó, đánh giá các biếnaccount
; nếu giá trị biến lànull
(điều sẽ xảy ra khi nó không có được biến, chẳng hạn như thời gian hết, mạng, nền tảng giao diện ngoại lệ, vv), nó sẽ trở lại trực tiếp (tương ứng vớiif (!account ){...}
ở đây).
Tuyên bốself.account = account
là để chỉ định các biến địa phươngaccount
đến thuộc tínhaccount
của đối tượng được xây dựng để ghi lại thông tin tài khoản mới nhất trong đối tượng được xây dựng.
Tuyên bốvar now = new Date().getTime()
tuyên bố một biến địa phươngnow
, và gọi chogetTime()
chức năng của đối tượng thời gian & ngày của ngôn ngữ JavaScript để trả lại dấu thời gian hiện tại, và gán dấu thời gian cho biếnnow
.
Mã:if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)) {...}
đánh giá sự khác biệt giữa dấu giờ hiện tại và dấu giờ được ghi lại cuối cùng; nếu giá trị vượt quá tham sốCalcNetInterval * 1000
, nghĩa là nó đã vượt quáCalcNetInterval * 1000
milliseconds (CalcNetInterval
Vì giá mua 1 trên thị trường cần phải được sử dụng khi tính toán lợi nhuận, điều kiện này cũng được giới hạn trong điều kiệnself.orderBook.Bids.length > 0
(dữ liệu sâu, phải có giá trị trong danh sách lệnh mua như thông tin cấp).
Khi điều kiện của câu lệnh self.preCalc = now
để cập nhật biến timestampself.preCalc
của lợi nhuận được in cuối cùng đến thời điểm hiện tạinow
Ở đây, thống kê lợi nhuận sử dụng phương pháp tính toán giá trị ròng, mã là:var net = _N(account.Balance + account.FrozenBalance + self.orderBook.Bids[0].Price * (account.Stocks + account.FrozenStocks))
, tức là chuyển đổi tiền tệ thành tài sản (tiền tệ báo giá) theo giá mua hiện tại, sau đó cộng với số tiền tài sản trong tài khoản và gán nó cho biến địa phương được khai báonet
Xác định xem tổng giá trị ròng hiện tại có phù hợp với tổng giá trị ròng được ghi nhận cuối cùng không:
if (net != self.preNet) {
self.preNet = net
LogProfit(net)
}
Nếu không phù hợp, tức lànet != self.preNet
là true, cập nhật thuộc tínhself.preNet
ghi lại giá trị ròng vớinet
Sau đó, in tổng số dữ liệu giá trị ròngnet
đến biểu đồ đường cong lợi nhuận của bot FMZ Quant Trading Platform (bạn có thể truy vấnLogProfit
chức năng trong tài liệu API FMZ).
Nếu việc in thường xuyên của trở lại không được kích hoạt, sau đó tiếp tục quá trình sau: ghiaccount.Stocks
(tiếng biểu tượng tiền tệ hiện có trong tài khoản) vàaccount.Balance
(các tài sản hiện có trong tài khoản) trongself.btc
vàself.cny
. Tính toán tỷ lệ offset và gán nó, được ghi trongself.p
.
self.p = self.btc * self.prices[self.prices.length-1] / (self.btc * self.prices[self.prices.length-1] + self.cny)
Các thuật toán cũng rất đơn giản, đó là để tính toán bao nhiêu phần trăm của giá trị tiền tệ hiện tại trong tổng giá trị ròng của tài khoản.
Vì vậy, làm thế nào bạn đánh giá khi đồng tiền (vị trí) cân bằng được kích hoạt?
Ở đây, các nhà phát triển sử dụng 50% lên và xuống 2 điểm phần trăm như một đệm; nếu nó vượt quá đệm, thực hiện số dư, đó là khiself.p < 0.48
Nếu bạn nghĩ rằng số tiền tiền tệ là nhỏ, mỗi khi giá tăng 0.01, đặt ba lệnh nhỏ.self.p > 0.52
Cuối cùng, chờ một khoảng thời gian nhất định, theo các thiết lập tham sốSleep(BalanceTimeout)
, và hủy tất cả các đơn đặt hàng.
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"
}
}
}
Chức năng bổ sung thứ tư:
Đây là phần cốt lõi của chiến lược, điểm nổi bật.self.poll = function() {...}
Chúng tôi cũng đã nói về nó trong bài viết trước.main( )
chức năng, bắt đầu thực hiện; trước khi nhậpwhile
vòng lặp vô hạn, chúng tôi sử dụngvar reaper = LeeksReaper()
để xây dựng đối tượng thu hoạch lợi nhuận, và sau đóReaper.poll()
được gọi là chu kỳ trongmain()
function.
Cácself.poll
chức năng bắt đầu thực hiện, và thực hiện một số chuẩn bị trước mỗi vòng lặp;self.numTick++
tăng số lượng;self.updateTrades()
cập nhật hồ sơ giao dịch gần đây trên thị trường và tính toán các dữ liệu liên quan được sử dụng;self.updateOrderBook()
cập nhật dữ liệu thị trường (tổ phiếu lệnh) và tính toán các dữ liệu có liên quan;self.balanceAccount()
kiểm tra số dư tiền tệ (cơ sở).
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
Tiếp theo, chúng ta cần đánh giá liệu thị trường ngắn hạn hiện tại có tăng hay giảm.
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
}
Anh có nhớself.updateOrderBook()
chức năng trong bài viết trước, trong đó chúng tôi đã sử dụng thuật toán trung bình cân nhắc để xây dựng một chuỗi thời gianprices
Bộ mã này sử dụng ba chức năng mới, cụ thể là_.min
, _.max
, slice
, cũng rất dễ hiểu.
_.min
: Chức năng là tìm mức tối thiểu trong mảng tham số.
_.max
: Chức năng là tìm tối đa trong mảng tham số.
slice
: Chức năng này là một hàm thành viên của đối tượng mảng JavaScript. Nó là để chặn và trả lại một phần của mảng theo chỉ mục. Ví dụ:
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]
}
Ở đây, các điều kiện để đánh giá liệu đó là thị trường tăng hay thị trường giảm là:
self.numTick > 2
phải là đúng, tức là, nếu sự bùng nổ giá xảy ra trong một vòng phát hiện mới, nó phải được kích hoạt sau ít nhất ba vòng phát hiện, và tránh kích hoạt ngay từ đầu.self.prices
, tức là sự khác biệt giữa dữ liệu mới nhất và giá tối đa hoặc tối thiểu trongself.prices
mảng trong phạm vi trước đây nên phá vỡburstPrice
.Nếu tất cả các điều kiện là đúng, đánh dấubull
hoặcbear
nhưtrue
, và gán một giá trị cho biếntradeAmount
, và lên kế hoạch giao dịch ngựa.
Sau đó, cho các tham sốBurstThresholdVol
, dựa trênself.vol
được cập nhật và tính toán trong năm trướcself.updateTrades()
Các hoạt động giao dịch sẽ được thực hiện theo các quy định của các cơ quan quản lý.
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
}
Tiếp theo, đánh giá liệu tín hiệu giao dịch và khối lượng giao dịch có đáp ứng các yêu cầu không:
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
}
Sau phán quyết trên, thực thivar tradePrice = bull ? self.bidPrice : self.askPrice
Tùy thuộc vào việc đó là thị trường gấu hay thị trường tăng, đặt giá giao dịch và gán giá trị với giá lệnh giao hàng tương ứng.
Cuối cùng, nhập mộtwhile
vòng lặp; điều kiện dừng và phá vỡ duy nhất của vòng lặp làtradeAmount >= MinStock
, nghĩa là khối lượng giao dịch dự kiến thấp hơn khối lượng giao dịch tối thiểu.
Trong vòng lặp, theo trạng thái thị trường tăng hiện tại hoặc trạng thái thị trường gấu, thực hiện lệnh.orderId
- Chết đi.Sleep(200)
để chờ 200 mili giây sau khi đặt một lệnh trong mỗi vòng. vòng lặp sau đó đánh giá liệuorderId
là true (nếu lệnh thất bại, ID lệnh sẽ không được trả về, và điều kiện self.tradeOrderId
.
Xác định một biếnorder
để lưu trữ dữ liệu đơn đặt hàng với giá trị ban đầu củanull
. Sau đó, sử dụng một vòng lặp để có được dữ liệu đơn đặt hàng với ID, và xác định xem đơn đặt hàng có trong trạng thái đơn đặt hàng đang chờ không; nếu nó ở trạng thái đơn đặt hàng đang chờ, hủy đơn đặt hàng với ID; nếu nó không ở trạng thái đơn đặt hàng đang chờ, nó sẽ thoát khỏi vòng lặp phát hiện.
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
}
}
}
Sau đó, thực hiện quy trình sau:
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
}
}
Khi dòng chảy chương trình phá vỡ ra khỏiwhile (tradeAmount >= MinStock) {...}
vòng lặp, nó có nghĩa là việc thực hiện quá trình giao dịch giá bùng nổ đã hoàn thành.
Thực hiệnself.numTick = 0
, nghĩa là, thiết lập lạiself.numTick
đến 0.
Việc thực hiện cuối cùng của người xây dựngLeeksReaper()
trả vềself
đối tượng, đó là, khivar reaper = LeeksReaper()
, đối tượng được trả vềreaper
.
Cho đến nay, chúng tôi đã phân tích cáchLeeksReaper()
constructor xây dựng đối tượng thu hoạch lợi nhuận này, các phương pháp khác nhau của đối tượng, và quá trình thực hiện các chức năng logic chính. sau khi đọc bài viết, tôi nghĩ bạn sẽ có một sự hiểu biết rõ ràng hơn về quá trình thuật toán chiến lược tần số cao.