Trong bài viết trước, chúng tôi đã thực hiện một chiến lược phòng hộ đơn giản cùng nhau, và sau đó chúng tôi sẽ học cách nâng cấp chiến lược này. Các thay đổi chiến lược không lớn, nhưng các chi tiết của những thay đổi cần chú ý.
A exchange -> B exchange
, B exchange -> A exchange
, và vẽ đường ngang kích hoạt sự lây lan.line drawing class library
để đối phó trực tiếp, lợi thế là nó dễ sử dụng, ở đây chúng ta cũng học cách sử dụngtemplate class library
chức năng của FMZ.Tiếp theo, chúng ta hãy thực hiện các thiết kế này từng cái một.
Hãy lấy Binance điểm thực bot như một ví dụ, chuyển sang chế độ đòn bẩy điểm, sử dụng mãexchanges[i].IO
, nhập tham sốtrade_normal
để chuyển sang vị trí đòn bẩy theo vị trí và đầu vàotrade_super_margin
để chuyển sang vị trí đầy đủ đòn bẩy, backtesting không được hỗ trợ.
Thêm vào giai đoạn chuẩn bị ở đầumain
chức năng:
// 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")
}
}
}
Chiến lược ở đây chỉ thêm mã để chuyển đổi chế độ đòn bẩy coin-to-coin của Binance spot, vì vậy cài đặt chuyển đổi trên các thông số chiến lược chỉ có giá trị cho Binance spot.
Nó rất dễ dàng để sử dụng mẫu vẽ đã được bọc.Line Drawing Library
Nó có thể được tìm kiếm trực tiếp trên quảng trường chiến lược nền tảng FMZ.
Hoặc nhấp vào liên kết trực tiếp:https://www.fmz.com/strategy/27293để nhảy đến trang sao chép cho mẫu này.
Nhấp vào nút để sao chép thư viện lớp mẫu này vào thư viện chiến lược của riêng bạn.
Sau đó, bạn có thể kiểm tra thư viện lớp mẫu để sử dụng trong cột mẫu trên trang chỉnh sửa chiến lược. Lưu chiến lược sau khi kiểm tra nó, và chiến lược sẽ tham chiếu đến mẫu này. Đây chỉ là một mô tả ngắn gọn về việc sử dụng thư viện lớp mẫu. Chiến lược này đã tham chiếu đến mẫu này, vì vậy không cần phải lặp lại hoạt động. Khi bạn sao chép chiến lược này vào ô chiến lược, bạn có thể thấy rằngLine Drawing Library
đã được tham chiếu trong thanh mẫu trên trang chỉnh sửa chiến lược.
Chúng ta sẽ chủ yếu học cách sử dụng các chức năng củaLine Drawing Library
để vẽ một biểu đồ.
Chúng tôi có kế hoạch để rút ra sự lan rộng củaA->B
, sự lây lan củaB->A
Chúng ta cần vẽ hai đường cong (tiền A đến B, B đến A), hai đường ngang (đường chênh lệch chênh lệch), như được hiển thị trong hình trên.
Bởi vì chúng tôi muốn thiết kế phòng hộ đơn phương, các đường kích hoạt củaA->B
vàB->A
Chúng ta không thể sử dụng thiết kế trong bài trước.
Trong bài trước:
var targetDiffPrice = hedgeDiffPrice
if (diffAsPercentage) {
targetDiffPrice = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentage
}
Chỉ có một cách kích hoạt.targetDiffPrice
.
Vì vậy, ở đây chúng ta phải biến đổi mã, biến đổi các tham số đầu tiên.
Sau đó thay đổi mã:
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
}
Bằng cách này, sự khác biệt kích hoạt đường đã thay đổi từ trước đótargetDiffPrice
đến haitargetDiffPriceA2B
, targetDiffPriceB2A
.
Bước tiếp theo là vẽ các dữ liệu này trên biểu đồ bằng cách sử dụng chức năng đường vẽ của thư viện vẽ đường.
// 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")
Khi chiến lược đang chạy, có một biểu đồ như thế này.
Tiếp theo vẽ đường cong phân bố thời gian thực, để tránh quá vẽ đường.
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
}
Bằng cách này, mã vẽ chỉ có 4 dòng, cho phép chiến lược có biểu đồ hiển thị tại thời điểm chạy.
Như đã đề cập ở trên, đường kích hoạt chênh lệch đã được sửa đổi thành hai, điều khiển kích hoạt phòng ngừa rủi ro củaA->B
vàB->A
Theo cách này, thuật toán giá đặt hàng trước đó không thể được sử dụng, và thay vào đó, phương pháp thêm giá vé vào giá thị trường được sử dụng.
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
}
}
Vì giá mua và giá bán được tách thành hai dữ liệu, chức năng phòng ngừa rủi rohedge
cũng cần phải được sửa đổi.
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()
}
Ngoài ra còn có một số điều chỉnh nhỏ dựa trên những thay đổi này, mà sẽ không được lặp lại ở đây.
Thêm tương tác vào chiến lược, để chiến lược có thể sửa đổi đường kích hoạt lây lan trong thời gian thực. Thiết kế tương tác chiến lược cũng rất đơn giản. Đầu tiên, thêm điều khiển tương tác vào chiến lược trên trang chỉnh sửa chiến lược.
Thêm hai điều khiển, một được gọi là A2B và một được gọi là B2A. Sau khi nhập một giá trị trong hộp đầu vào điều khiển, nhấp vào nút ở bên phải của hộp đầu vào. Một lệnh sẽ được gửi đến chiến lược ngay lập tức, ví dụ: nhập giá trị123
trong hộp đầu vào, bấm vàoA2B
nút, và một hướng dẫn sẽ được gửi đến chiến lược ngay lập tức.
A2B:123
Thiết kế mã phát hiện và xử lý tương tác trong mã chiến lược.
// 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])
}
}
}
Làm cho dữ liệu thanh trạng thái hiển thị có tổ chức và dễ quan sát hơn.
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 chỉ là một chiến lược thử nghiệm, một chức năng phát hiện sơ bộ, và nhiều lỗi có thể được thử nghiệm trong giai đoạn backtesting thực sự.
Mã nguồn chiến lược:https://www.fmz.com/strategy/302834