Dalam artikel sebelumnya, kita melaksanakan strategi lindung nilai mudah bersama-sama, dan kemudian kita akan belajar bagaimana untuk menaik taraf strategi. Tidak banyak perubahan dalam strategi, tetapi butiran perubahan perlu diperhatikan.
A->B
danB->A
, serta garis pencetus penyebaran mendatar, kita boleh terus menggunakanchart plot library
Dari sini, kita juga belajar bagaimana untuk menggunakan fungsi FMZtemplate library
together.Seterusnya, mari kita merealisasikan idea reka bentuk satu demi satu.
Ambil Binance bot spot sebagai contoh. Untuk beralih ke mod margin spot, gunakan kodexchanges[i].IO
, import parametertrade_normal
untuk beralih kepada margin yang terpencil, dan importtrade_super_margin
untuk beralih ke margin silang, yang tidak disokong dalam backtest. yang hanya boleh digunakan dalam bot.
Dalam persediaan pada awalmain
fungsi, tambah:
// 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 menambah kod untuk menukar mod margin spot Binance Spot, jadi tetapan suis dalam parameter strategi hanya berfungsi untuk Binance Spot.
Menggunakan templat plot yang dikapsulkan adalah sangat mudah. Nama templat yang kita gunakan di sini adalahchart plot Library
Anda boleh cari secara langsung di platform Lapangan FMZ.
Atau anda boleh terus klik pautan:https://www.fmz.com/strategy/27293untuk melompat ke halaman salinan templat.
Klik butang dan anda boleh dengan mudah menyalin templat ke perpustakaan strategi anda sendiri.
Kemudian, pada halaman penyuntingan strategi, anda boleh menyemak perpustakaan templat yang akan digunakan dalam lajur templat. Simpan strategi selepas menyemaknya, dan strategi akan menggunakan templat ini. Ini hanya penerangan ringkas penggunaan perpustakaan templat. Oleh kerana strategi telah merujuk kepada templat ini, tidak perlu mengulangi operasi. Apabila anda menyalin kod strategi di Square, anda dapat melihat bahawachart plot Library
telah dirujuk dalam bar templat halaman penyuntingan strategi.
Di sini kita terutamanya belajar bagaimana untuk menggunakan fungsichart plot library
untuk merangka.
Kami merancang untuk merangka penyebaranA->B
danB->A
, dan garis pencetus penyebaran. kita perlu merangka dua lengkung (kini, penyebaran dari A ke B dan B ke A), dan dua garis mendatar (garis pencetus penyebaran), seperti yang ditunjukkan dalam gambar di atas.
Kerana kita mahu untuk mereka bentuk pagar satu sisi, garis pencetusA->B
danB->A
akan berbeza, dan 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
}
Hanya ada satu penyebaran yang dicetuskantargetDiffPrice
.
Oleh itu, di sini kita perlu mengubah suai kod, dan kita perlu mengubah suai 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
}
Oleh itu, garis pencetus penyebaran telah berubah dari yang sebelumnyatargetDiffPrice
kepada dua, iaitutargetDiffPriceA2B
dantargetDiffPriceB2A
.
Seterusnya, anda boleh menggunakan fungsi grafik plot perpustakaan grafik plot untuk menarik data pada carta.
// 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")
Apabila strategi dijalankan, carta akan dipaparkan seperti ini.
Seterusnya, lukis lengkung spread masa nyata; untuk mengelakkan overdrawing, letakkan kod yang merangka lengkung spread masa nyata dalam pengesanan baki. 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
}
Kod plot hanya memerlukan 4 baris untuk membolehkan strategi dengan paparan carta semasa berjalan.
Seperti yang dinyatakan di atas, nombor garis pencetus spread telah diubah menjadi dua, yang masing-masing mengawal pencetus lindung nilaiA->B
danB->A
Dengan cara ini, algoritma harga pesanan sebelumnya tidak boleh digunakan, dan kaedah menambah harga slaid 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 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
}
}
Oleh kerana harga beli dan jual dibahagikan kepada dua data,hedge
fungsi 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 pengubahsuaian ini, yang tidak akan diterangkan di sini.
Tambah interaksi kepada strategi, supaya strategi boleh mengubah suai garis pencetus penyebaran dalam masa nyata. Reka bentuk interaksi strategi juga sangat mudah. Pertama, tambah kawalan interaktif kepada strategi di halaman penyuntingan strategi.
Terdapat dua kawalan ditambah, satu dipanggil A2B dan yang lain dipanggil B2A. Selepas memasukkan nilai dalam kotak input kawalan, klik butang di sebelah kanan kotak input. Perintah akan dihantar ke strategi dengan segera, contohnya: masukkan nilai123
dalam kotak input, klikA2B
butang, dan arahan akan dihantar ke strategi dengan segera.
A2B:123
Reka bentuk kod pengesanan dan pemprosesan interaktif dalam kod 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])
}
}
}
Buat paparan data bar status lebih terkawal dan mudah diperhatikan.
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) + "`")
Ujian belakang hanya ujian strategi, sebagai fungsi pengesanan awal. Banyak bug sebenarnya boleh diuji dalam peringkat ujian belakang. Tidak perlu terlalu peduli tentang hasil ujian belakang. Akhirnya, strategi masih perlu diuji dalam persekitaran sebenar dengan bot sebenar.
Kod sumber strategi:https://www.fmz.com/strategy/302834