Mari kita lanjutkanisi dari terakhir kaliuntuk menjelaskan.
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)
}
}
}
}
Ketika konstruktorLeeksReaper()
adalah membangun sebuah objek,balanceAccount()
fungsi yang ditambahkan ke objek digunakan untuk memperbarui informasi aset akun, yang disimpan diself.account
, yaitu untuk membangun Atributaccount
dari objek. Menghitung dan mencetak nilai pengembalian secara teratur. Kemudian, sesuai dengan informasi aset akun terbaru, rasio saldo simbol mata uang spot (saldo posisi spot) dihitung, dan ketika ambang offset dipicu, pesanan kecil ditutup untuk membuat simbol (posisi) kembali ke keadaan seimbang. Tunggu untuk periode waktu tertentu untuk mengeksekusi perdagangan, dan kemudian batalkan semua pesanan yang tertunda, dan pelaksanaan fungsi pada putaran berikutnya, saldo akan terdeteksi lagi dan pemrosesan yang sesuai akan dilakukan.
Mari kita lihat kode dari pernyataan fungsi ini dengan pernyataan:
Pertama, pernyataan pertamavar account = exchange.GetAccount()
menyatakan variabel lokalaccount
, memanggilexchange.GetAccount()
fungsi di antarmuka FMZ API, mendapatkan data terbaru dari rekening current dan menugaskannya ke variabelaccount
. Kemudian, menilai variabelaccount
; jika nilai variabel adalahnull
(yang akan terjadi ketika gagal untuk mendapatkan variabel, seperti timeout, jaringan, platform interface exception, dll), itu akan kembali langsung (yang sesuai denganif (!account ){...}
di sini).
Pernyataanself.account = account
adalah untuk menetapkan variabel lokalaccount
untuk atributaccount
dari objek yang dibangun untuk mencatat informasi akun terbaru di objek yang dibangun.
Pernyataanvar now = new Date().getTime()
menyatakan variabel lokalnow
, dan memanggilgetTime()
fungsi objek waktu & tanggal dari bahasa JavaScript untuk mengembalikan timestamp saat ini, dan menetapkan timestamp ke variabelnow
.
Kode:if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)) {...}
menilai perbedaan antara timestamp saat ini dan timestamp terakhir yang tercatat; jika nilai melebihi parameterCalcNetInterval * 1000
, berarti telah melebihiCalcNetInterval * 1000
Milisekund (CalcNetInterval
detik) dari pembaruan terakhir hingga saat ini, yang mewujudkan fungsi mencetak pengembalian secara teratur.self.orderBook.Bids.length > 0
(data mendalam, yang harus valid dalam daftar pesanan pembelian sebagai informasi tingkat).
Ketika kondisi pernyataan self.preCalc = now
untuk memperbarui variabel timestampself.preCalc
dari hasil cetak terakhir pada tanggal dan waktu saat ininow
Di sini, statistik laba menggunakan metode perhitungan nilai bersih, kode adalah:var net = _N(account.Balance + account.FrozenBalance + self.orderBook.Bids[0].Price * (account.Stocks + account.FrozenStocks))
, yaitu mengubah mata uang menjadi aset (mata uang kutipan) sesuai dengan harga beli 1 saat ini, dan kemudian menambahkannya bersama dengan jumlah aset di rekening dan menugaskannya ke variabel lokal yang dinyatakannet
Tentukan apakah nilai bersih total saat ini konsisten dengan nilai bersih total terakhir yang tercatat:
if (net != self.preNet) {
self.preNet = net
LogProfit(net)
}
Jika tidak konsisten, yaitunet != self.preNet
adalah benar, update atributself.preNet
yang mencatat nilai bersih dengannet
Kemudian, cetak total data nilai bersihnet
ke grafik kurva keuntungan dari bot Platform Trading FMZ Quant (Anda dapat menanyakanLogProfit
fungsi dalam dokumentasi FMZ API).
Jika pencetakan reguler pengembalian tidak dipicu, maka melanjutkan proses berikut: catatanaccount.Stocks
(simbol mata uang yang tersedia saat ini di akun) danaccount.Balance
(aktif yang tersedia saat ini di akun) diself.btc
danself.cny
Menghitung rasio offset dan menugaskannya, yang dicatat dalamself.p
.
self.p = self.btc * self.prices[self.prices.length-1] / (self.btc * self.prices[self.prices.length-1] + self.cny)
Algoritma juga sangat sederhana, yaitu menghitung berapa persen nilai mata uang saat ini dalam total nilai bersih akun.
Jadi bagaimana Anda menilai ketika saldo mata uang (posisi) dipicu?
Di sini pengembang menggunakan 50% ke atas dan ke bawah 2 poin persentase sebagai buffer; jika melebihi buffer, mengeksekusi saldo, yaitu ketikaself.p < 0.48
Jika Anda berpikir jumlah mata uang kecil, setiap kali harga meningkat sebesar 0,01, menempatkan tiga pesanan kecil.self.p > 0.52
, jika Anda berpikir jumlah mata uang yang besar, menunggu pesanan kecil menjual 1 harga di pasar.Sleep(BalanceTimeout)
, dan membatalkan 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:
Inilah bagian inti dari strategi, yang paling penting.self.poll = function() {...}
fungsi adalah logika utama dari seluruh strategi. kita juga berbicara tentang hal itu di artikel sebelumnya. dimain( )
fungsi, mulai untuk menjalankan; sebelum memasukiwhile
loop tak terbatas, kita menggunakanvar reaper = LeeksReaper()
untuk membangun obyek profit harvester, dan kemudianReaper.poll()
disebut secara siklis dalammain()
function.
Peraturanself.poll
fungsi mulai dijalankan, dan melakukan beberapa persiapan sebelum setiap loop;self.numTick++
meningkatkan jumlahnya;self.updateTrades()
memperbarui catatan perdagangan terbaru di pasar dan menghitung data terkait yang digunakan;self.updateOrderBook()
memperbarui data pasar (buku pesanan) dan menghitung data yang relevan;self.balanceAccount()
memeriksa saldo mata uang (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
Selanjutnya, kita perlu menilai apakah pasar jangka pendek saat ini adalah banteng 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
}
Apakah Anda ingatself.updateOrderBook()
fungsi dalam artikel sebelumnya, di mana kita menggunakan algoritma rata-rata tertimbang untuk membangun deret waktuprices
Bagian kode ini menggunakan tiga fungsi baru, yaitu_.min
, _.max
, slice
, yang juga sangat mudah dimengerti.
_.min
: Fungsi adalah untuk menemukan minimum dalam array parameter.
_.max
: Fungsi adalah untuk menemukan maksimum dalam array parameter.
slice
: Fungsi ini adalah fungsi anggota dari objek array JavaScript. Ini adalah untuk mencegat dan mengembalikan bagian dari array sesuai dengan indeks. Misalnya:
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, kondisi untuk menilai apakah itu adalah pasar bull atau pasar bear adalah:
self.numTick > 2
harus benar, yaitu, jika ledakan harga terjadi dalam putaran baru deteksi, itu harus dipicu setelah setidaknya tiga putaran deteksi, dan menghindari pemicu di awal.self.prices
, yaitu perbedaan antara data terbaru dan harga maksimum atau minimum diself.prices
array di kisaran sebelumnya harus menembusburstPrice
.Jika semua kondisi benar, tandabull
ataubear
sebagaitrue
, dan menetapkan nilai untuk variabeltradeAmount
, dan rencanakan pertukaran kuda.
Kemudian, untuk parameterBurstThresholdVol
, berdasarkanself.vol
diperbarui dan dihitung pada tahun sebelumnya.self.updateTrades()
fungsi, diputuskan apakah untuk mengurangi intensitas perdagangan (untuk mengurangi volume perdagangan yang direncanakan).
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
}
Selanjutnya, menilai apakah sinyal perdagangan dan volume perdagangan memenuhi persyaratan:
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
}
Setelah putusan di atas, eksekusivar tradePrice = bull ? self.bidPrice : self.askPrice
Berdasarkan apakah itu adalah pasar beruang atau pasar banteng, tetapkan harga perdagangan dan menetapkan nilai dengan harga pesanan pengiriman yang sesuai.
Akhirnya, masukkanwhile
lingkaran; satu-satunya kondisi berhenti dan istirahat lingkaran adalahtradeAmount >= MinStock
, yaitu volume perdagangan yang direncanakan kurang dari volume perdagangan minimum.
Dalam loop, sesuai dengan kondisi pasar bull saat ini atau kondisi pasar bear, mengeksekusi order. dan mencatat ID order dalam variabelorderId
Eksekusi.Sleep(200)
untuk menunggu selama 200 milidetik setelah menempatkan pesanan di setiap putaran. loop kemudian menilai apakahorderId
adalah benar (jika order gagal, order ID tidak akan dikembalikan, dan kondisi self.tradeOrderId
.
Mengisyaratkan variabelorder
untuk menyimpan data pesanan dengan nilai awal darinull
Kemudian, gunakan loop untuk mendapatkan data pesanan dengan ID, dan menentukan apakah pesanan berada dalam status pesanan yang sedang menunggu; jika berada dalam status pesanan yang sedang menunggu, batalkan pesanan dengan ID; jika tidak berada dalam status pesanan yang sedang menunggu, itu akan keluar dari loop deteksi.
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
}
}
Ketika aliran program pecah keluar dariwhile (tradeAmount >= MinStock) {...}
loop, itu berarti bahwa pelaksanaan proses perdagangan harga ledakan selesai.
Eksekusiself.numTick = 0
, yaitu, resetself.numTick
ke 0.
Eksekusi terakhir konstruktorLeeksReaper()
mengembalikanself
objek, yaitu, ketikavar reaper = LeeksReaper()
, objek dikembalikan kereaper
.
Sejauh ini, kami telah menganalisis bagaimanaLeeksReaper()
setelah membaca artikel ini, saya pikir Anda akan memiliki pemahaman yang lebih jelas tentang proses algoritma strategi frekuensi tinggi.