Mari kita teruskankandungan kali terakhiruntuk menerangkan.
Fungsi Tambahan Ketiga:
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)
}
}
}
}
Apabila pembinaLeeksReaper()
adalah membina objek,balanceAccount()
fungsi yang ditambahkan kepada objek digunakan untuk mengemas kini maklumat aset akaun yang disimpan dalamself.account
, iaitu untuk membina sifataccount
Perkiraan dan cetak nilai pulangan secara berkala. Kemudian, mengikut maklumat aset akaun terkini, nisbah baki simbol mata wang spot (saldo kedudukan spot) dikira, dan apabila ambang offset dicetuskan, pesanan kecil ditutup untuk membuat simbol (posisi) kembali ke keadaan seimbang. Tunggu untuk tempoh masa tertentu untuk melaksanakan perdagangan, dan kemudian batalkan semua pesanan yang belum selesai, dan pelaksanaan fungsi dalam pusingan seterusnya, baki akan dikesan lagi dan pemprosesan yang sesuai akan dilakukan.
Mari kita lihat kod pernyataan fungsi ini dengan pernyataan:
Pertama sekali, pernyataan pertamavar account = exchange.GetAccount()
menyatakan pembolehubah tempatanaccount
, memanggilexchange.GetAccount()
fungsi dalam antara muka FMZ API, mendapatkan data terkini akaun semasa dan menetapkannya kepada pembolehubahaccount
. Kemudian, menilai pembolehubahaccount
; jika nilai pembolehubah adalahnull
(yang akan berlaku apabila ia gagal untuk mendapatkan pembolehubah, seperti masa lapang, rangkaian, platform antara muka pengecualian, dan lain-lain), ia akan kembali secara langsung (mengikutif (!account ){...}
di sini).
Kenyataanself.account = account
adalah untuk menetapkan pembolehubah tempatanaccount
kepada atributaccount
objek yang dibina untuk merakam maklumat akaun terkini dalam objek yang dibina.
Kenyataanvar now = new Date().getTime()
menyatakan pembolehubah tempatannow
, dan memanggilgetTime()
fungsi objek masa & tarikh bahasa JavaScript untuk mengembalikan cap masa semasa, dan menetapkan cap masa kepada pembolehubahnow
.
Kodnya:if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)) {...}
menilai perbezaan antara stempel masa semasa dan stempel masa terakhir yang direkodkan; jika nilai melebihi parameterCalcNetInterval * 1000
, ia bermakna ia telah melebihiCalcNetInterval * 1000
Milisaat (CalcNetInterval
detik) dari kemas kini terakhir kepada sekarang, yang merealisasikan fungsi mencetak pulangan secara berkala.self.orderBook.Bids.length > 0
(data mendalam, yang mesti sah dalam senarai pesanan beli sebagai maklumat tahap).
Apabila syarat pernyataan self.preCalc = now
untuk mengemas kini pembolehubah stempel masaself.preCalc
dari keuntungan terakhir yang dicetak pada cap masa semasanow
Di sini, statistik keuntungan menggunakan kaedah pengiraan nilai bersih, kod adalah:var net = _N(account.Balance + account.FrozenBalance + self.orderBook.Bids[0].Price * (account.Stocks + account.FrozenStocks))
, iaitu menukar mata wang kepada aset (mata wang kutipan) mengikut harga beli 1 semasa, dan kemudian menambahkannya bersama-sama dengan jumlah aset dalam akaun dan menetapkannya kepada pembolehubah tempatan yang dinyatakannet
Tentukan sama ada nilai bersih keseluruhan semasa adalah konsisten dengan nilai bersih keseluruhan terakhir yang direkodkan:
if (net != self.preNet) {
self.preNet = net
LogProfit(net)
}
Jika tidak konsisten, iaitunet != self.preNet
adalah benar, mengemas kini atributself.preNet
yang mencatat nilai bersih dengannet
Kemudian, cetak jumlah data nilai bersihnet
kepada carta lengkung keuntungan bot Platform Dagangan Kuantum FMZ (anda boleh menyoalLogProfit
fungsi dalam dokumentasi FMZ API).
Jika pencetakan biasa pulangan tidak dicetuskan, kemudian meneruskan proses berikut: rekodaccount.Stocks
(simbol mata wang yang sedia ada pada masa ini dalam akaun) danaccount.Balance
(aset sedia ada semasa dalam akaun) dalamself.btc
danself.cny
. Mengira nisbah offset dan menetapkan ia, yang direkodkan dalamself.p
.
self.p = self.btc * self.prices[self.prices.length-1] / (self.btc * self.prices[self.prices.length-1] + self.cny)
Algoritma ini juga sangat mudah, iaitu untuk mengira berapa peratusan nilai mata wang semasa dalam jumlah nilai bersih akaun.
Jadi bagaimana anda menilai apabila baki mata wang (posisi) dicetuskan?
Di sini pemaju menggunakan 50% ke atas dan ke bawah 2 mata peratusan sebagai penyangga; jika ia melebihi penyangga, melaksanakan baki, iaitu apabilaself.p < 0.48
Jika anda fikir jumlah mata wang adalah kecil, setiap kali harga meningkat sebanyak 0.01, meletakkan tiga pesanan kecil.self.p > 0.52
, jika anda fikir jumlah mata wang adalah besar, menunggu pesanan kecil menjual 1 harga di pasaran. Akhirnya, menunggu untuk tempoh masa tertentu, mengikut tetapan parameterSleep(BalanceTimeout)
, dan batalkan semua pesanan.
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"
}
}
}
Fungsi yang ditambahkan keempat:
Ini adalah bahagian utama strategi, yang paling penting.self.poll = function() {...}
fungsi adalah logik utama keseluruhan strategi. kita juga bercakap tentang ia dalam artikel sebelumnya.main( )
fungsi, mula untuk melaksanakan; sebelum memasukiwhile
gelung tak terhingga, kita gunakanvar reaper = LeeksReaper()
untuk membina objek pemanen keuntungan, dan kemudianReaper.poll()
dipanggil secara kitaran dalammain()
function.
Peraturanself.poll
fungsi mula untuk melaksanakan, dan melakukan beberapa persediaan sebelum setiap gelung;self.numTick++
meningkatkan jumlah;self.updateTrades()
mengemas kini rekod perdagangan terkini di pasaran dan mengira data yang berkaitan yang digunakan;self.updateOrderBook()
mengemas kini data pasaran (buku pesanan) dan mengira data yang relevan;self.balanceAccount()
memeriksa baki mata wang (posisi).
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
Seterusnya, kita perlu menilai sama ada pasaran jangka pendek semasa adalah lembu atau beruang.
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
}
Adakah anda ingatself.updateOrderBook()
fungsi dalam artikel sebelumnya, di mana kita menggunakan algoritma purata tertimbang untuk membina siri masaprices
Sepotong kod ini menggunakan tiga fungsi baru, iaitu_.min
, _.max
, slice
, yang juga sangat mudah difahami.
_.min
: Fungsi adalah untuk mencari minimum dalam array parameter.
_.max
: Fungsi adalah untuk mencari maksimum dalam array parameter.
slice
: Fungsi ini adalah fungsi ahli objek array JavaScript. Ia adalah untuk memintas dan mengembalikan sebahagian daripada array mengikut indeks. Sebagai contoh:
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]
}
Di sini, syarat untuk menilai sama ada ia adalah pasaran lembu atau pasaran beruang adalah:
self.numTick > 2
mesti benar, iaitu, jika ledakan harga berlaku dalam pusingan pengesanan baru, ia mesti dicetuskan selepas sekurang-kurangnya tiga pusingan pengesanan, dan mengelakkan pemicu pada mulanya.self.prices
, iaitu perbezaan antara data terkini dan harga maksimum atau minimum dalamself.prices
array dalam julat sebelumnya harus memecahkan melaluiburstPrice
.Jika semua syarat adalah benar, tandabull
ataubear
sebagaitrue
, dan menetapkan nilai kepada pembolehubahtradeAmount
, dan merancang pertukaran kuda.
Kemudian, untuk parameterBurstThresholdVol
, berdasarkanself.vol
diperbaharui dan dikira pada tahun sebelumnya.self.updateTrades()
fungsi, ia diputuskan sama ada untuk mengurangkan intensiti dagangan (untuk mengurangkan jumlah dagangan yang dirancang).
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
}
Seterusnya, menilai sama ada isyarat dagangan dan jumlah dagangan memenuhi keperluan:
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
}
Selepas keputusan di atas, melaksanakanvar tradePrice = bull ? self.bidPrice : self.askPrice
Mengikut sama ada ia adalah pasaran beruang atau pasaran lembu, tetapkan harga dagangan dan menetapkan nilai dengan harga pesanan penghantaran yang sepadan.
Akhirnya, masukkanwhile
gelung; satu-satunya keadaan berhenti dan pecah gelung adalahtradeAmount >= MinStock
, iaitu jumlah dagangan yang dirancang adalah kurang daripada jumlah dagangan minimum.
Dalam gelung, mengikut keadaan pasaran lembu semasa atau keadaan pasaran beruang, melaksanakan pesanan. dan mencatat ID pesanan dalam pembolehubahorderId
Bunuh dia.Sleep(200)
untuk menunggu selama 200 milidetik selepas meletakkan pesanan dalam setiap pusingan. gelung kemudian menilai sama adaorderId
adalah benar (jika pesanan gagal, ID pesanan tidak akan dikembalikan, dan keadaan self.tradeOrderId
.
Mengisytiharkan pembolehubahorder
untuk menyimpan data pesanan dengan nilai awalnull
. Kemudian, gunakan gelung untuk mendapatkan data pesanan dengan ID, dan menentukan sama ada pesanan berada dalam status pesanan menunggu; jika ia berada dalam status pesanan menunggu, membatalkan pesanan dengan ID; jika ia tidak berada dalam status pesanan menunggu, ia akan keluar dari gelung pengesanan.
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
}
}
}
Kemudian, lakukan proses berikut:
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
}
}
Apabila aliran program pecah keluar dariwhile (tradeAmount >= MinStock) {...}
gelung, ia bermaksud bahawa pelaksanaan proses perdagangan harga pecah telah selesai.
Melakukanself.numTick = 0
, iaitu, set semulaself.numTick
kepada 0.
Pelaksanaan terakhir pembinaLeeksReaper()
mengembalikanself
objek, iaitu, apabilavar reaper = LeeksReaper()
, objek dikembalikan kereaper
.
Setakat ini, kami telah menganalisis bagaimanaLeeksReaper()
constructor membina objek ini keuntungan harvester, pelbagai kaedah objek, dan proses pelaksanaan fungsi logik utama. selepas membaca artikel, saya fikir anda akan mempunyai pemahaman yang lebih jelas tentang proses algoritma strategi frekuensi tinggi.