Dalam artikel sebelumnya, kita melaksanakan strategi lindung nilai mudah bersama-sama, dan kemudian kita akan belajar bagaimana untuk menaik taraf strategi ini. Perubahan strategi tidak besar, tetapi butiran perubahan memerlukan perhatian. definisi beberapa tempat dalam kod telah berubah dari yang sebelumnya, yang perlu difahami.
A exchange -> B exchange
, B exchange -> A exchange
, dan melukis garis mendatar yang mencetuskan penyebaran.line drawing class library
untuk menangani secara langsung, kelebihan adalah bahawa ia mudah digunakan, di sini kita juga belajar bagaimana untuk menggunakantemplate class library
fungsi FMZ.Seterusnya, mari kita melaksanakan reka bentuk ini satu demi satu.
Ambil Binance bot sebenar spot sebagai contoh, beralih ke mod leveraged spot, gunakan kodexchanges[i].IO
, masukkan parametertrade_normal
untuk beralih ke kedudukan leverage mengikut kedudukan, dan inputtrade_super_margin
untuk beralih ke kedudukan sepenuhnya, backtesting tidak disokong. ini hanya digunakan dalam bot sebenar.
Tambah kepada fasa persediaan pada awalmain
fungsi:
// Switch leverage mode
for (var i = 0 ; i < exchanges.length ; i++) { // Traverse and detect all added exchange objects
if (exchanges[i].GetName() == "Binance" && marginType != 0) { //If the exchange object represented by the current i-index is Binance spot, and the parameter marginType of the strategy interface is not the option of "common currency", execute the switch operation
if (marginType == 1) {
Log(exchanges[i].GetName(), "Set to leveraged position-by-position")
exchanges[i].IO("trade_normal")
} else if (marginType == 2) {
Log(exchanges[i].GetName(), "Set to leveraged full position")
exchanges[i].IO("trade_super_margin")
}
}
}
Strategi di sini hanya menambah kod untuk menukar mod leverage koin ke koin Binance spot, jadi tetapan suis pada parameter strategi hanya sah untuk Binance spot.
Ia adalah sangat mudah untuk menggunakan templat lukisan yang sudah dibungkus. nama templat yang kita gunakan adalahLine Drawing Library
. Ia boleh diperolehi dengan mencari terus di platform FMZ strategi persegi.
Atau klik pautan terus:https://www.fmz.com/strategy/27293untuk melompat ke halaman salinan untuk templat ini.
Klik butang untuk menyalin perpustakaan kelas templat ini ke perpustakaan strategi anda sendiri.
Kemudian anda boleh menyemak perpustakaan kelas templat yang akan digunakan dalam lajur templat di halaman penyuntingan strategi. Simpan strategi selepas menyemaknya, dan strategi akan merujuk kepada templat ini. Ini hanya penerangan ringkas penggunaan perpustakaan kelas templat. Strategi ini telah merujuk kepada templat ini, jadi tidak perlu mengulangi operasi. Apabila anda menyalin strategi ini di kotak strategi, anda dapat melihat bahawaLine Drawing Library
telah dirujuk dalam bar templat pada halaman penyuntingan strategi.
Kami akan belajar bagaimana untuk menggunakan fungsiLine Drawing Library
untuk membuat carta.
Kami merancang untuk menarik penyebaranA->B
, penyebaranB->A
, dan garis pemicu penyebaran. kita perlu melukis dua lengkung (menyebar semasa A ke B, B ke A), dua garis mendatar (garis penyebaran pemicu), seperti yang ditunjukkan dalam gambar di atas.
Kerana kita mahu untuk mereka bentuk lindung nilai satu sisi, garis pencetusA->B
danB->A
Kita tidak boleh menggunakan reka bentuk 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
}
Terdapat hanya satu penyebaran pencetustargetDiffPrice
.
Jadi di sini kita perlu mengubah kod, mengubah parameter terlebih dahulu.
Kemudian ubah kod:
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 cara ini, garis pemicu perbezaan telah berubah dari yang sebelumnyatargetDiffPrice
Untuk duatargetDiffPriceA2B
, targetDiffPriceB2A
.
Langkah seterusnya adalah untuk melukis data ini pada carta dengan menggunakan fungsi garis gambar perpustakaan lukisan garis.
// drawing
$.PlotHLine(targetDiffPriceA2B, "A->B") // The first parameter of this 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")
Apabila strategi berjalan, terdapat carta seperti ini.
Seterusnya lukis kurva spread masa nyata, untuk mengelakkan menggambar garis.
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) // Draw real-time spread curves
$.PlotLine("B2A", depthB.Bids[0].Price - depthA.Asks[0].Price) // The first parameter is the name of the curve, and the second parameter is the value of the curve at the current moment, that is, the value in the Y-axis direction at the current moment
}
Dengan cara ini, kod lukisan hanya 4 baris, yang membolehkan strategi untuk mempunyai grafik yang dipaparkan pada masa berjalan.
Seperti yang dinyatakan di atas, garis pencetus spread telah diubah menjadi dua, mengawal pencetus lindung nilaiA->B
danB->A
Dengan cara ini, algoritma harga pesanan sebelumnya tidak boleh digunakan, dan kaedah penambahan harga slip kepada harga pasaran 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 conditions are met
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("trigger A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[1].Balance * 0.8 / priceSell, nowAccs[0].Stocks) // Tips
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 conditions are met
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("trigger B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[0].Balance * 0.8 / priceBuy, nowAccs[1].Stocks) //Tips
hedge(exA, exB, priceBuy, priceSell, amount)
cancelAll()
lastKeepBalanceTS = 0
isTrade = true
}
}
Oleh kerana harga beli dan jualan dipisahkan kepada dua data, fungsi lindung nilaihedge
juga perlu diubah.
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()
}
Terdapat juga beberapa penyesuaian kecil berdasarkan perubahan ini, yang tidak akan diulangi di sini.
Tambah interaksi kepada strategi, supaya strategi dapat mengubah garis pencetus penyebaran dalam masa nyata. Reka bentuk interaksi strategi juga sangat mudah. Pertama, tambahkan kawalan interaksi kepada strategi di halaman penyuntingan strategi.
Tambah dua kawalan, satu dipanggil A2B dan satu dipanggil B2A. Selepas memasukkan nilai dalam kotak input kawalan, klik butang di sebelah kanan kotak input. Arahan akan dihantar ke strategi dengan serta-merta, contohnya: masukkan nilai123
dalam kotak input, klikA2B
butang, dan arahan akan dihantar kepada strategi segera.
A2B:123
Reka bentuk kod pengesanan dan pemprosesan interaktif dalam kod strategi.
// interact
var cmd = GetCommand() // Every time the loop is executed here, it checks whether there is an interactive command, and returns to an empty string if not.
if (cmd) { // An interactive command was detected, such as A2B:123
Log("command received:", cmd)
var arr = cmd.split(":") // Split out the interactive control name and the value in the input box, arr[0] is A2B, arr[1] is 123
if (arr[0] == "A2B") { // Determine whether the triggered interactive control is A2B
Log("Modify the parameters of A2B, ", diffAsPercentage ? "The parameter is the difference percentage" : "The parameter is the difference:", arr[1])
if (diffAsPercentage) {
hedgeDiffPercentageB2A = parseFloat(arr[1]) // Modify the trigger spread line
} else {
hedgeDiffPriceA2B = parseFloat(arr[1]) // Modify the trigger spread line
}
} else if (arr[0] == "B2A") { // Triggered control detected is B2A
Log("Modify the parameters of B2A, ", diffAsPercentage ? "The parameter is the difference percentage" : "The parameter is the difference:", arr[1])
if (diffAsPercentage) {
hedgeDiffPercentageA2B = parseFloat(arr[1])
} else {
hedgeDiffPriceB2A = parseFloat(arr[1])
}
}
}
Buat paparan bar status data lebih teratur dan mudah untuk memerhatikan.
var tbl = {
"type" : "table",
"title" : "data",
"cols" : ["exchange", "coin", "freeze coin", "denominated currency", "freeze denominated currency", "trigger spread", "current spread"],
"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) + "`")
Backtesting hanyalah strategi ujian, fungsi pengesanan awal, dan banyak bug boleh diuji pada peringkat backtesting sebenarnya.
Kod sumber strategi:https://www.fmz.com/strategy/302834