Trong các bài viết trước đây trong thư viện FMZ
Chúng quản lý tài khoản tham chiếu và tài khoản đồng bộ trong một chiến lược để đạt được đồng bộ hóa lệnh và vị trí. và hôm nay chúng tôi sẽ thử một thiết kế khác, chúng tôi sẽ thiết kế một hệ thống quản lý đồng bộ hóa lệnh dựa trên giao diện API mở rộng mạnh mẽ của nền tảng giao dịch FMZ Quant.
Đầu tiên, chúng ta cần một số đề xuất tốt và nhu cầu. hai lệnh trước đây và vị trí chiến lược đồng bộ hóa trên, mà có một số thiếu sót rõ ràng, mà chúng tôi sẽ thảo luận cùng nhau.
Giải pháp:
Sử dụng giao diện API mở rộng của FMZOrder Synchronous Server
Chiến lược trong Real Bot). Sau đó chỉ cần cung cấp FMZ mở rộng API KEY (lưu ý rằng nó không phải là API KEY của tài khoản trao đổi) và Order Synchronous Server thực bot ID cho chủ sở hữu của tài khoản tham chiếu (đạo diễn lệnh).
Khi chủ tài khoản tham chiếu (những người theo dõi lệnh) thực bot (cácOrder Synchronization Management System Class Library (Single Server)
trong hệ thống được thiết kế trong bài viết này) gửi tín hiệu, chủ tài khoản đồng bộ hóa bot thực sự sẽ nhận tín hiệu giao dịch và đặt lệnh tiếp theo tự động.
Order Synchronization Management System Class Library (Single Server)
chiến lược trong hệ thống được thiết kế trong bài viết này), do đó chủ sở hữu tài khoản tham chiếu (đạo lệnh) có thể nhúng thư viện lớp mẫu này vào chiến lược của riêng mình trực tiếp để đạt được chức năng đồng bộ hóa thứ tự và vị trí.Vì vậy, hệ thống bao gồm 2 phần:
Một khi chúng ta đã xác định nhu cầu của mình, hãy bắt đầu thiết kế!
Lưu ý rằng đây không phải là một chiến lược. Đây là một thư viện lớp mẫu của FMZ. Khái niệm thư viện lớp mẫu có thể được tìm kiếm trong tài liệu API FMZ và chúng tôi sẽ không lặp lại nữa.
Mã thư viện lớp mẫu:
// Global variables
var keyName_label = "label"
var keyName_robotId = "robotId"
var keyName_extendAccessKey = "extendAccessKey"
var keyName_extendSecretKey = "extendSecretKey"
var fmzExtendApis = parseConfigs([config1, config2, config3, config4, config5])
var mapInitRefPosAmount = {}
function parseConfigs(configs) {
var arr = []
_.each(configs, function(config) {
if (config == "") {
return
}
var strArr = config.split(",")
if (strArr.length != 4) {
throw "configs error!"
}
var obj = {}
obj[keyName_label] = strArr[0]
obj[keyName_robotId] = strArr[1]
obj[keyName_extendAccessKey] = strArr[2]
obj[keyName_extendSecretKey] = strArr[3]
arr.push(obj)
})
return arr
}
function getPosAmount(pos, ct) {
var longPosAmount = 0
var shortPosAmount = 0
_.each(pos, function(ele) {
if (ele.ContractType == ct && ele.Type == PD_LONG) {
longPosAmount = ele.Amount
} else if (ele.ContractType == ct && ele.Type == PD_SHORT) {
shortPosAmount = ele.Amount
}
})
var timestamp = new Date().getTime()
return {ts: timestamp, long: longPosAmount, short: shortPosAmount}
}
function sendCommandRobotMsg (robotId, accessKey, secretKey, msg) {
// https://www.fmz.com/api/v1?access_key=xxx&secret_key=yyyy&method=CommandRobot&args=[186515,"ok12345"]
var url = "https://www.fmz.com/api/v1?access_key=" + accessKey + "&secret_key=" + secretKey + "&method=CommandRobot&args=[" + robotId + ',"' + msg + '"]'
Log(url)
var ret = HttpQuery(url)
return ret
}
function follow(nowPosAmount, symbol, ct, type, delta) {
var msg = ""
var nowAmount = type == PD_LONG ? nowPosAmount.long : nowPosAmount.short
if (delta > 0) {
// open the position
var tradeDirection = type == PD_LONG ? "buy" : "sell"
// send signals
msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)
} else if (delta < 0) {
// close the position
var tradeDirection = type == PD_LONG ? "closebuy" : "closesell"
if (nowAmount <= 0) {
Log("no positions found")
return
}
// send signals
msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)
} else {
throw "error"
}
if (msg) {
_.each(fmzExtendApis, function(extendApiConfig) {
var ret = sendCommandRobotMsg(extendApiConfig[keyName_robotId], extendApiConfig[keyName_extendAccessKey], extendApiConfig[keyName_extendSecretKey], msg)
Log("call the CommandRobot interface, ", "label:", extendApiConfig[keyName_label], ", msg:", msg, ", ret:", ret)
Sleep(1000)
})
}
}
$.PosMonitor = function(exIndex, symbol, ct) {
var ts = new Date().getTime()
var ex = exchanges[exIndex]
// judge the type of ex
var exName = ex.GetName()
var isFutures = exName.includes("Futures_")
var exType = isFutures ? "futures" : "spot"
if (!isFutures) {
throw "only future-following is supported"
}
if (exType == "futures") {
// caching symbol ct
var buffSymbol = ex.GetCurrency()
var buffCt = ex.GetContractType()
// switch to the corresponding contract pair, contract code
ex.SetCurrency(symbol)
if (!ex.SetContractType(ct)) {
throw "SetContractType failed"
}
// monitor positions
var keyInitRefPosAmount = "refPos-" + exIndex + "-" + symbol + "-" + ct // refPos-exIndex-symbol-contractType
var initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
if (!initRefPosAmount) {
// no initialization data, initialize it
mapInitRefPosAmount[keyInitRefPosAmount] = getPosAmount(_C(ex.GetPosition), ct)
initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
}
// monitor
var nowRefPosAmount = getPosAmount(_C(ex.GetPosition), ct)
// calculate the position changes
var longPosDelta = nowRefPosAmount.long - initRefPosAmount.long
var shortPosDelta = nowRefPosAmount.short - initRefPosAmount.short
// detect changes
if (!(longPosDelta == 0 && shortPosDelta == 0)) {
// Perform long positions
if (longPosDelta != 0) {
Log(ex.GetName(), ex.GetLabel(), symbol, ct, "Perform long position-following, changes in volume:", longPosDelta)
follow(nowRefPosAmount, symbol, ct, PD_LONG, longPosDelta)
}
// Perform short positions
if (shortPosDelta != 0) {
Log(ex.GetName(), ex.GetLabel(), symbol, ct, "Perform short position-following, changes in volume:", shortPosDelta)
follow(nowRefPosAmount, symbol, ct, PD_SHORT, shortPosDelta)
}
// Update after performing the order-following operation
mapInitRefPosAmount[keyInitRefPosAmount] = nowRefPosAmount
}
// restore symbol ct
ex.SetCurrency(buffSymbol)
ex.SetContractType(buffCt)
} else if (exType == "spot") {
// Spots
}
}
$.getTbl = function() {
var tbl = {
"type" : "table",
"title" : "synchronization of data",
"cols" : [],
"rows" : []
}
// construct the table headers
tbl.cols.push("monitor the account: refPos-exIndex-symbol-contractType")
tbl.cols.push(`monitor the position: {"timestamp":xxx,"long positions":xxx,"short positions":xxx}`)
_.each(fmzExtendApis, function(extendApiData, index) {
tbl.cols.push(keyName_robotId + "-" + index)
})
// Write data in
_.each(mapInitRefPosAmount, function(initRefPosAmount, key) {
var arr = [key, JSON.stringify(initRefPosAmount)]
_.each(fmzExtendApis, function(extendApiData) {
arr.push(extendApiData[keyName_robotId])
})
tbl.rows.push(arr)
})
return tbl
}
// Example of the strategy call that references the template class library
function main() {
// Clear all logs
LogReset(1)
// Switch to OKEX demo to test
exchanges[0].IO("simulate", true)
// Set the contract
exchanges[0].SetCurrency("ETH_USDT")
exchanges[0].SetContractType("swap")
// Timed trading interval
var tradeInterval = 1000 * 60 * 3 // Trade for every three minutes to observe the order-following signals
var lastTradeTS = new Date().getTime()
while (true) {
// Other logic of the strategy...
// Simulated trading triggers for testing
var ts = new Date().getTime()
if (ts - lastTradeTS > tradeInterval) {
Log("Trade the simulation order-leading strategies, position changes", "#FF0000")
exchanges[0].SetDirection("buy")
exchanges[0].Buy(-1, 1)
lastTradeTS = ts
}
// Interface functions that use templates
$.PosMonitor(0, "ETH_USDT", "swap") // Multiple monitors can be set up to monitor different exchange objects on the order-following strategy
var tbl = $.getTbl()
// Display status bar
LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
Sleep(1000)
}
}
Thiết kế rất đơn giản, thư viện lớp có 2 chức năng. Khi một chiến lược giao dịch lập trình trên nền tảng FMZ tham chiếu thư viện lớp mẫu củaOrder Synchronization Management System Class Library (Single Server)
. Sau đó chiến lược có thể sử dụng các hàm sau đây.
$. Positor Monitor. Mục đích của chức năng này là để theo dõi các thay đổi vị trí của các đối tượng trao đổi trong chiến lược và sau đó gửi tín hiệu giao dịch đến thị trường bot thực sự được đặt trong các tham số của mẫu: thư viện lớp Order Synchronization Management System (Single Server).
$.getTbl Trở lại dữ liệu đồng bộ được theo dõi.
Ví dụ sử dụng là trongmain
chức năng của mẫu thư viện lớp hệ thống quản lý đồng bộ hóa lệnh (Single Server):
// Example of the strategy call that references the template class library
function main() {
// Clear all logs
LogReset(1)
// Switch to OKEX demo to test
exchanges[0].IO("simulate", true)
// Set the contract
exchanges[0].SetCurrency("ETH_USDT")
exchanges[0].SetContractType("swap")
// Timed trading interval
var tradeInterval = 1000 * 60 * 3 // Trade for every three minutes to observe the order-following signals
var lastTradeTS = new Date().getTime()
while (true) {
// Other logic of the strategy...
// Simulated trading triggers for testing
var ts = new Date().getTime()
if (ts - lastTradeTS > tradeInterval) {
Log("Trade the simulation order-leading strategies, position changes", "#FF0000")
exchanges[0].SetDirection("buy")
exchanges[0].Buy(-1, 1)
lastTradeTS = ts
}
// Interface functions by using templates
$.PosMonitor(0, "ETH_USDT", "swap") // Multiple monitors can be set up to monitor different exchange objects on the order-following strategy
var tbl = $.getTbl()
// Display status bar
LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
Sleep(1000)
}
}
Một thư viện lớp mẫu cũng có thể tự tạo ra một bot thực sự chiến lược, thường được sử dụng để kiểm tra thư viện lớp mẫu, chẳng hạn như kiểm tra mẫu.main
hàm trong một mẫu làmain
chức năng của một trong những chiến lược của riêng bạn.
Mã thử nghiệm được viết bằng cách sử dụng OKEX demo để thử nghiệm, bạn cần cấu hình OKEX demo API KEY trên FMZ như một tài khoản tham chiếu (đưa ra lệnh), và nó bắt đầu chuyển sang demo trong chức năng chính. Sau đó đặt cặp giao dịch thành ETH_USDT và đặt hợp đồng để trao đổi. Sau đó nó đi vào vòng lặp while. Trong vòng lặp, một lệnh được đặt mỗi 3 phút để mô phỏng việc kích hoạt các giao dịch chiến lược.$.PosMonitor(0, "ETH_USDT", "swap")
được gọi trong vòng lặp while, tham số đầu tiên của hàm này được truyền đến 0, có nghĩa là để theo dõi các giao dịch đối tượng trao đổi[0], theo dõi cặp giao dịch ETH_USDT, hợp đồng trao đổi.$.getTbl()
để có được thông tin biểu đồ, sử dụngLogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
để làm cho dữ liệu biểu đồ hiển thị trên thanh trạng thái.
Vì vậy, chúng ta có thể thấy rằng chúng ta có thể làm cho chiến lược có khả năng theo dõi vị trí của một loài nhất định, và vị trí thay đổi để gửi tin nhắn bằng cách sử dụng$.PosMonitor(0, "ETH_USDT", "swap")
trong một chiến lược tham chiếu đến mẫu.
Trước khi thử nghiệm, chúng tôi sẽ giải thích các thiết kế các tham số chiến lược củaOrder Synchronization Management System Class Library (Single Server)
.
Chúng ta vừa nói về cách sử dụng chức năng giao diện của một mẫu để nâng cấp một chiến lược để có chức năng dẫn đầu lệnh.
Câu hỏi về việc gửi ai được cấu hình bởi các tham số củaOrder Synchronization Management System Class Library (Single Server)
.
Chúng ta có thể thấy rằng có 5 tham số, hỗ trợ lên đến 5 đẩy (nó có thể được mở rộng bởi chính mình nếu nó cần tăng), các tham số mặc định là các chuỗi trống, đó là, không được xử lý.
nhãn Một nhãn cho một tài khoản đồng bộ, nó được sử dụng để thiết lập một nhãn cho một tài khoản với một tên có thể được thiết lập theo ý muốn.
robotId
Robot ID, ID củaOrder Synchronous Server
bot thực được tạo bởi chủ sở hữu tài khoản đồng bộ.
accessKey Truy cập API mở rộngKey của FMZ
mậtKey Chìa khóa API mở rộng của FMZ
Mã tạm thời của Hệ thống quản lý đồng bộ hóa đơn hàng (Synchronous Server):
function main() {
LogReset(1)
while (true) {
var cmd = GetCommand()
if (cmd) {
// cmd: ETH_USDT,swap,buy,1
Log("cmd: ", cmd)
}
Sleep(1000)
}
}
Chúng ta có thể thấy rằng bot thực sự của chủ tài khoản đồng bộ hóa đã nhận được tin nhắn:ETH_USDT,swap,buy,1
.
Sau đó nó sẽ cho phép chúng tôi để làm cho tự động của chúng tôi theo dõi lệnh trong bước tiếp theo dựa trên các cặp giao dịch, mã hợp đồng, hướng giao dịch, và số tiền trong thông tin.
Cho đến nay,Order Synchronization Management System (Synchronous Server)
là mã tạm thời, chúng ta sẽ tiếp tục khám phá thiết kế của nó trong số tiếp theo.