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. Không có nhiều thay đổi trong chiến lược, nhưng chi tiết của các thay đổi cần phải được chú ý.
A->B
vàB->A
, cũng như các đường kích hoạt phân tán ngang, chúng ta có thể trực tiếp sử dụng cácchart plot library
; lợi thế là sự đơn giản và dễ sử dụng.template library
together.Tiếp theo, chúng ta hãy thực hiện những ý tưởng thiết kế này từng cái một.
Để chuyển sang chế độ ký quỹ tại chỗ, sử dụng mãexchanges[i].IO
, nhập tham sốtrade_normal
để chuyển sang biên độ cô lập, và nhập khẩutrade_super_margin
để chuyển sang biên ngang, mà không được hỗ trợ trong backtest.
Trong quá trình chuẩn bị vào đầumain
chức năng, thêm:
// 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")
}
}
}
Chiến lược ở đây chỉ thêm mã để chuyển đổi chế độ ký quỹ giao ngay của Binance Spot, vì vậy cài đặt chuyển đổi trong các thông số chiến lược chỉ hoạt động cho Binance Spot.
Sử dụng các mẫu phác thảo được đóng gói rất đơn giản. Tên mẫu chúng tôi sử dụng ở đây làchart plot Library
Bạn có thể trực tiếp tìm kiếm nó trên quảng trường FMZ.
Hoặc bạn có thể nhấp trực tiếp vào liên kết:https://www.fmz.com/strategy/27293để chuyển sang trang sao chép của mẫu.
Nhấp vào nút và bạn có thể dễ dàng sao chép mẫu vào thư viện chiến lược của riêng bạn.
Sau đó, trên trang chỉnh sửa chiến lược, bạn có thể kiểm tra thư viện mẫu được sử dụng trong cột mẫu. Sau khi kiểm tra, lưu chiến lược và chiến lược sẽ sử dụng mẫu này. Đây chỉ là một mô tả ngắn gọn về việc sử dụng thư viện mẫu. Vì chiến lược đã tham chiếu đến mẫu này, không cần phải lặp lại hoạt động. Khi bạn sao chép mã chiến lược trong Square, bạn có thể thấy rằngchart plot Library
đã được tham chiếu trong thanh mẫu của trang chỉnh sửa chiến lược.
Ở đây chúng ta chủ yếu học cách sử dụng các chức năng củachart plot library
để âm mưu.
Chúng tôi có kế hoạch để vẽ ra sự lan rộng củaA->B
vàB->A
Chúng ta cần vẽ hai đường cong (hiện tại, các đường chênh lệch từ A đến B và B đến A), và 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ế một hàng rào một bên, các đường kích hoạt củaA->B
vàB->A
sẽ khác nhau, và 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 sự gia tăng được kích hoạttargetDiffPrice
.
Do đó, ở đây chúng ta cần sửa đổi mã, và chúng ta cần sửa đổi các tham số đầu tiên.
sau đó, sửa đổ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
}
Do đó, đường kích hoạt lây lan đã thay đổi từ trước đó mộttargetDiffPrice
đến hai, cụ thể làtargetDiffPriceA2B
vàtargetDiffPriceB2A
.
Tiếp theo, bạn có thể sử dụng chức năng vẽ biểu đồ của thư viện biểu đồ để vẽ dữ liệu trên biểu đồ.
// 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")
Khi chiến lược được chạy, biểu đồ sẽ được hiển thị như thế này.
Tiếp theo, vẽ đường cong chênh lệch thời gian thực; để tránh vẽ quá mức, đặt mã vẽ các đường cong chênh lệch thời gian thực trong phát hiện số dư. 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
}
Mã vẽ chỉ cần 4 dòng để cho phép chiến lược với một biểu đồ hiển thị trong khi chạy.
Như đã đề cập ở trên, số dòng kích hoạt chênh lệch đã được thay đổi thành hai, tương ứng kiểm soát kích hoạt phòng hộ củaA->B
vàB->A
Bằng 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á trượt 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 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
}
}
Vì giá mua và giá bán được chia thành hai dữ liệu,hedge
chức năng 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 các sửa đổi này, mà sẽ không được mô tả ở đâ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.
Có hai điều khiển được thêm vào, một tên là A2B và một tên 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 lệnh 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.
// 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])
}
}
}
Làm cho hiển thị dữ liệu thanh trạng thái được điều chỉnh và dễ quan sát hơn.
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 chỉ là một thử nghiệm của chiến lược, như một chức năng phát hiện sơ bộ. Nhiều lỗi thực sự có thể được thử nghiệm trong giai đoạn backtest. Không cần phải quan tâm quá nhiều đến kết quả backtest. Cuối cùng, chiến lược vẫn cần được thử nghiệm trong môi trường thực tế với các bot thực sự.
Mã nguồn chiến lược:https://www.fmz.com/strategy/302834