Dalam artikel sebelumnya, kita menerapkan strategi lindung nilai sederhana bersama, dan kemudian kita akan belajar bagaimana untuk meningkatkan strategi. Ada sedikit perubahan dalam strategi, tetapi rincian perubahan perlu diperhatikan. Definisi beberapa tempat dalam kode telah dimodifikasi, dibandingkan dengan yang sebelumnya, yang perlu dipahami secara khusus.
A->B
danB->A
, serta garis pemicu penyebaran horizontal, kita dapat langsung menggunakanchart plot library
Dari sini, kita juga belajar bagaimana menggunakan fungsi FMZtemplate library
together.Selanjutnya, mari kita mewujudkan ide desain satu per satu.
Ambil Binance spot bot sebagai contoh. Untuk beralih ke mode margin spot, gunakan kodeexchanges[i].IO
, mengimpor parametertrade_normal
untuk beralih ke margin terisolasi, dan importrade_super_margin
untuk beralih ke cross margin, yang tidak didukung dalam backtest. yang hanya dapat digunakan dalam bot.
Dalam persiapan pada awalmain
fungsi, tambahkan:
// switch the margin mode
for (var i = 0 ; i < exchanges.length ; i++) { // traverse and detect all exchange objects added
if (exchanges[i].GetName() == "Binance" && marginType != 0) { // if the exchange object represented by the current index i is Binance Spot, and the parameter marginType on the strategy interface is not selected as the "common spot" option, execute the switch
if (marginType == 1) {
Log(exchanges[i].GetName(), "set to isolated margin")
exchanges[i].IO("trade_normal")
} else if (marginType == 2) {
Log(exchanges[i].GetName(), "set to cross margin")
exchanges[i].IO("trade_super_margin")
}
}
}
Strategi di sini hanya menambahkan kode untuk beralih ke mode margin spot Binance Spot, jadi pengaturan switch dalam parameter strategi hanya bekerja untuk Binance Spot.
Menggunakan templat plot yang terkapsul sangat sederhana. nama template yang kita gunakan di sini adalahchart plot Library
Anda bisa langsung mencarinya di platform Square of FMZ.
Atau Anda bisa langsung mengklik link:https://www.fmz.com/strategy/27293untuk melompat ke halaman salinan template.
Klik tombol dan Anda dapat dengan mudah menyalin template ke perpustakaan strategi Anda sendiri.
Kemudian, di halaman pengeditan strategi, Anda dapat memeriksa perpustakaan template yang akan digunakan di kolom template. Simpan strategi setelah memeriksa, dan strategi akan menggunakan template ini. Ini hanya deskripsi singkat tentang penggunaan perpustakaan template. Karena strategi telah merujuk template ini, tidak perlu mengulangi operasi. Ketika Anda menyalin kode strategi di Square, Anda dapat melihat bahwachart plot Library
telah dirujuk di bilah templat dari halaman editing strategi.
Di sini kita terutama belajar bagaimana menggunakan fungsi darichart plot library
untuk merencanakan.
Kami berencana untuk merencanakan penyebaranA->B
danB->A
, dan garis pemicu spread. kita perlu memetakan dua kurva (saat ini, spread dari A ke B dan B ke A), dan dua garis horizontal (line pemicu spread), seperti yang ditunjukkan pada gambar di atas.
Karena kita ingin merancang pager satu sisi, garis pemicu dariA->B
danB->A
akan berbeda, dan kita tidak bisa menggunakan desain dalam artikel sebelumnya.
Dalam artikel sebelumnya:
var targetDiffPrice = hedgeDiffPrice
if (diffAsPercentage) {
targetDiffPrice = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentage
}
Hanya ada satu penyebaran yang dipicutargetDiffPrice
Aku tidak tahu.
Oleh karena itu, di sini kita perlu memodifikasi kode, dan kita perlu memodifikasi parameter pertama.
Kemudian, ubah kode:
var targetDiffPriceA2B = hedgeDiffPriceA2B
var targetDiffPriceB2A = hedgeDiffPriceB2A
if (diffAsPercentage) {
targetDiffPriceA2B = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentageA2B
targetDiffPriceB2A = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentageB2A
}
Dengan demikian, garis pemicu spread telah berubah dari yang sebelumnyatargetDiffPrice
ke dua, yaitutargetDiffPriceA2B
dantargetDiffPriceB2A
Aku tidak tahu.
Selanjutnya, Anda dapat menggunakan fungsi grafik plot perpustakaan grafik plot untuk menggambar data pada grafik.
// plot
$.PlotHLine(targetDiffPriceA2B, "A->B") // the first parameter of the function is the value of the horizontal line in the Y-axis direction, and the second parameter is the display text
$.PlotHLine(targetDiffPriceB2A, "B->A")
Ketika strategi dijalankan, grafik akan ditampilkan seperti ini.
Selanjutnya, gambar kurva spread real-time; untuk menghindari overdrawing, menempatkan kode yang memetakan kurva spread real-time dalam deteksi saldo. s
if (ts - lastKeepBalanceTS > keepBalanceCyc * 1000) {
nowAccs = _C(updateAccs, exchanges)
var isBalance = keepBalance(initAccs, nowAccs, [depthA, depthB])
cancelAll()
if (isBalance) {
lastKeepBalanceTS = ts
if (isTrade) {
var nowBalance = _.reduce(nowAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
var initBalance = _.reduce(initAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
LogProfit(nowBalance - initBalance, nowBalance, initBalance, nowAccs)
isTrade = false
}
}
$.PlotLine("A2B", depthA.Bids[0].Price - depthB.Asks[0].Price) // plot real-time spread curves
$.PlotLine("B2A", depthB.Bids[0].Price - depthA.Asks[0].Price) // the first parameter is the curve name, and the second parameter is the curve value at the current moment, that is, the value in the Y-axis direction at the current moment
}
Kode plot hanya membutuhkan 4 baris untuk memungkinkan strategi dengan tampilan grafik selama berjalan.
Seperti yang disebutkan di atas, nomor garis pemicu spread telah diubah menjadi dua, yang masing-masing mengontrol pemicu lindung nilai dariA->B
danB->A
Dengan cara ini, algoritma harga pesanan sebelumnya tidak dapat digunakan, dan metode penambahan harga slide ke harga pasar digunakan sebagai gantinya.
if (depthA.Bids[0].Price - depthB.Asks[0].Price > targetDiffPriceA2B && Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount) >= minHedgeAmount) { // A->B market condition satisfied
var priceSell = depthA.Bids[0].Price - slidePrice
var priceBuy = depthB.Asks[0].Price + slidePrice
var amount = Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount)
if (nowAccs[0].Stocks > minHedgeAmount && nowAccs[1].Balance * 0.8 / priceSell > minHedgeAmount) {
amount = Math.min(amount, nowAccs[0].Stocks, nowAccs[1].Balance * 0.8 / priceSell, maxHedgeAmount)
Log("triggerA->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[1].Balance * 0.8 / priceSell, nowAccs[0].Stocks) // prompt message
hedge(exB, exA, priceBuy, priceSell, amount)
cancelAll()
lastKeepBalanceTS = 0
isTrade = true
}
} else if (depthB.Bids[0].Price - depthA.Asks[0].Price > targetDiffPriceB2A && Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount) >= minHedgeAmount) { // B->A market condition satisfied
var priceBuy = depthA.Asks[0].Price + slidePrice
var priceSell = depthB.Bids[0].Price - slidePrice
var amount = Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount)
if (nowAccs[1].Stocks > minHedgeAmount && nowAccs[0].Balance * 0.8 / priceBuy > minHedgeAmount) {
amount = Math.min(amount, nowAccs[1].Stocks, nowAccs[0].Balance * 0.8 / priceBuy, maxHedgeAmount)
Log("triggerB->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[0].Balance * 0.8 / priceBuy, nowAccs[1].Stocks) // prompt message
hedge(exA, exB, priceBuy, priceSell, amount)
cancelAll()
lastKeepBalanceTS = 0
isTrade = true
}
}
Karena harga beli dan jual dibagi menjadi dua data,hedge
fungsi juga perlu dimodifikasi.
function hedge(buyEx, sellEx, priceBuy, priceSell, amount) {
var buyRoutine = buyEx.Go("Buy", priceBuy, amount)
var sellRoutine = sellEx.Go("Sell", priceSell, amount)
Sleep(500)
buyRoutine.wait()
sellRoutine.wait()
}
Ada juga beberapa penyesuaian kecil berdasarkan modifikasi ini, yang tidak akan dijelaskan di sini.
Tambahkan interaksi ke strategi, sehingga strategi dapat memodifikasi garis pemicu penyebaran secara real time. Desain interaksi strategi juga sangat sederhana. Pertama, tambahkan kontrol interaktif ke strategi di halaman pengeditan strategi.
Ada dua kontrol yang ditambahkan, satu disebut A2B dan yang lainnya disebut B2A. Setelah memasukkan nilai di kotak input kontrol, klik tombol di sebelah kanan kotak input. Perintah akan dikirim ke strategi segera, misalnya: masukkan nilai123
di kotak input, klikA2B
tombol, dan perintah akan dikirim ke strategi segera.
A2B:123
Desain interaktif deteksi dan pengolahan kode dalam kode strategi.
// interaction
var cmd = GetCommand() // every time when the loop is operated here, it will detect whether an interactive command is sent; if no, return null string
if (cmd) { // interactive command detected, such as A2B:123
Log("received command:", cmd)
var arr = cmd.split(":") // split out the interactive control name and the value in the input box; arr[0] means A2B, and arr[1] means 123
if (arr[0] == "A2B") { // judge whether the triggered interactive control is A2B
Log("modify parameterA2B,", diffAsPercentage ? "parameter of spread ratio:" : "parameter of spread:", arr[1])
if (diffAsPercentage) {
hedgeDiffPercentageB2A = parseFloat(arr[1]) // modify the spread trigger line
} else {
hedgeDiffPriceA2B = parseFloat(arr[1]) // modify the spread trigger line
}
} else if (arr[0] == "B2A") { // detected the triggered control is B2A
Log("modify parameterB2A,", diffAsPercentage ? "parameter of spread ratio:" : "parameter of spread:", arr[1])
if (diffAsPercentage) {
hedgeDiffPercentageA2B = parseFloat(arr[1])
} else {
hedgeDiffPriceB2A = parseFloat(arr[1])
}
}
}
Membuat tampilan data bar status lebih diatur dan mudah diamati.
var tbl = {
"type" : "table",
"title" : "data",
"cols" : ["platform", "Currency", "frozenCurrrency", "quoteCurrency", "frozenQuoteCurrency", "triggerSpread", "currentSpread"],
"rows" : [],
}
tbl.rows.push(["A:" + exA.GetName(), nowAccs[0].Stocks, nowAccs[0].FrozenStocks, nowAccs[0].Balance, nowAccs[0].FrozenBalance, "A->B:" + targetDiffPriceA2B, "A->B:" + (depthA.Bids[0].Price - depthB.Asks[0].Price)])
tbl.rows.push(["B:" + exB.GetName(), nowAccs[1].Stocks, nowAccs[1].FrozenStocks, nowAccs[1].Balance, nowAccs[1].FrozenBalance, "B->A:" + targetDiffPriceB2A, "B->A:" + (depthB.Bids[0].Price - depthA.Asks[0].Price)])
LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")
Backtest adalah hanya tes strategi, sebagai fungsi deteksi awal. Banyak bug sebenarnya dapat diuji pada tahap backtest. Tidak perlu terlalu peduli tentang hasil backtest. Akhirnya, strategi masih perlu diuji di lingkungan yang sebenarnya dengan bot nyata.
Kode sumber strategi:https://www.fmz.com/strategy/302834