Dalam artikel-artikel FMZ Library sebelumnya, kami telah merancang beberapa strategi sinkronisasi order dan posisi.
Ini dimaksudkan untuk menempatkan akun referensi dan akun sinkronisasi menjadi satu strategi guna mengelola dan menyinkronkan pesanan dan posisi. Hari ini kita akan mencoba desain yang berbeda. Berdasarkan antarmuka API canggih dari platform perdagangan kuantitatif FMZ, kita akan merancang sistem manajemen sinkronisasi pesanan.
Pertama-tama kami membutuhkan beberapa saran dan kebutuhan yang baik. Dua strategi sinkronisasi posisi dan urutan di atas memiliki beberapa kendala yang jelas. Mari kita bahas bersama:
Larutan:
Dengan menggunakan antarmuka API FMZ yang diperluas, pemilik akun sinkronisasi (pengikut) hanya perlu mendaftarkan platform perdagangan kuantitatif FMZ dan kemudian menjalankan strategi (dalam sistem yang dirancang dalam artikel ini:订单同步管理系统(Synchronous Server)
Strategi pasar riil). Kemudian berikan KUNCI API FMZ yang diperluas (perhatikan, bukan KUNCI API dari akun pertukaran) dan ID waktu nyata dari sistem manajemen sinkronisasi pesanan (Server Sinkron) kepada pemilik akun referensi (orang yang membawa pesanan) .
Ketika mengacu pada perintah sebenarnya dari pemilik akun (orang yang memiliki perintah) (dalam sistem yang dirancang dalam artikel ini)订单同步管理系统类库(Single Server)
) mengirimkan sinyal, akun riil dari pemilik akun yang disinkronkan akan menerima sinyal perdagangan dan kemudian melakukan pemesanan secara otomatis.
订单同步管理系统类库(Single Server)
Strategi), yang memungkinkan pemilik akun referensi (orang yang menerima pesanan) untuk langsung menanamkan pustaka templat ini ke dalam strateginya sendiri untuk mencapai fungsi sinkronisasi pesanan dan posisi.Jadi sistem ini terdiri dari 2 bagian: 1. Perpustakaan kelas sistem manajemen sinkronisasi pesanan (Server Tunggal) 2. Pesan Sistem Manajemen Sinkron (Server Sinkron)
Sekarang persyaratannya sudah jelas, mari kita mulai mendesain!
Perhatikan, ini bukan strategi. Ini adalah pustaka kelas templat FMZ. Konsep pustaka kelas templat dapat dicari dalam dokumentasi API FMZ, jadi saya tidak akan membahasnya secara rinci di sini.
Kode pustaka templat:
// 全局变量
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) {
// 开仓
var tradeDirection = type == PD_LONG ? "buy" : "sell"
// 发送信号
msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)
} else if (delta < 0) {
// 平仓
var tradeDirection = type == PD_LONG ? "closebuy" : "closesell"
if (nowAmount <= 0) {
Log("未检测到持仓")
return
}
// 发送信号
msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)
} else {
throw "错误"
}
if (msg) {
_.each(fmzExtendApis, function(extendApiConfig) {
var ret = sendCommandRobotMsg(extendApiConfig[keyName_robotId], extendApiConfig[keyName_extendAccessKey], extendApiConfig[keyName_extendSecretKey], msg)
Log("调用CommandRobot接口,", "label:", extendApiConfig[keyName_label], ", msg:", msg, ", ret:", ret)
Sleep(1000)
})
}
}
$.PosMonitor = function(exIndex, symbol, ct) {
var ts = new Date().getTime()
var ex = exchanges[exIndex]
// 判断ex类型
var exName = ex.GetName()
var isFutures = exName.includes("Futures_")
var exType = isFutures ? "futures" : "spot"
if (!isFutures) {
throw "仅支持期货跟单"
}
if (exType == "futures") {
// 缓存 symbol ct
var buffSymbol = ex.GetCurrency()
var buffCt = ex.GetContractType()
// 切换到对应的交易对、合约代码
ex.SetCurrency(symbol)
if (!ex.SetContractType(ct)) {
throw "SetContractType failed"
}
// 监控持仓
var keyInitRefPosAmount = "refPos-" + exIndex + "-" + symbol + "-" + ct // refPos-exIndex-symbol-contractType
var initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
if (!initRefPosAmount) {
// 没有初始化数据,初始化
mapInitRefPosAmount[keyInitRefPosAmount] = getPosAmount(_C(ex.GetPosition), ct)
initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
}
// 监控
var nowRefPosAmount = getPosAmount(_C(ex.GetPosition), ct)
// 计算仓位变动
var longPosDelta = nowRefPosAmount.long - initRefPosAmount.long
var shortPosDelta = nowRefPosAmount.short - initRefPosAmount.short
// 检测变动
if (!(longPosDelta == 0 && shortPosDelta == 0)) {
// 执行多头动作
if (longPosDelta != 0) {
Log(ex.GetName(), ex.GetLabel(), symbol, ct, "执行多头跟单,变动量:", longPosDelta)
follow(nowRefPosAmount, symbol, ct, PD_LONG, longPosDelta)
}
// 执行空头动作
if (shortPosDelta != 0) {
Log(ex.GetName(), ex.GetLabel(), symbol, ct, "执行空头跟单,变动量:", shortPosDelta)
follow(nowRefPosAmount, symbol, ct, PD_SHORT, shortPosDelta)
}
// 执行跟单操作后,更新
mapInitRefPosAmount[keyInitRefPosAmount] = nowRefPosAmount
}
// 恢复 symbol ct
ex.SetCurrency(buffSymbol)
ex.SetContractType(buffCt)
} else if (exType == "spot") {
// 现货
}
}
$.getTbl = function() {
var tbl = {
"type" : "table",
"title" : "同步数据",
"cols" : [],
"rows" : []
}
// 构造表头
tbl.cols.push("监控账户:refPos-exIndex-symbol-contractType")
tbl.cols.push(`监控持仓:{"时间戳":xxx,"多头持仓量":xxx,"空头持仓量":xxx}`)
_.each(fmzExtendApis, function(extendApiData, index) {
tbl.cols.push(keyName_robotId + "-" + index)
})
// 写入数据
_.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
}
// 引用该模板类库的策略调用范例
function main() {
// 清除所有日志
LogReset(1)
// 切换到OKEX 模拟盘测试
exchanges[0].IO("simulate", true)
// 设置合约
exchanges[0].SetCurrency("ETH_USDT")
exchanges[0].SetContractType("swap")
// 定时交易时间间隔
var tradeInterval = 1000 * 60 * 3 // 三分钟交易一次,用于观察跟单信号
var lastTradeTS = new Date().getTime()
while (true) {
// 策略其它逻辑...
// 用于测试的模拟交易触发
var ts = new Date().getTime()
if (ts - lastTradeTS > tradeInterval) {
Log("模拟带单策略发生交易,持仓变化", "#FF0000")
exchanges[0].SetDirection("buy")
exchanges[0].Buy(-1, 1)
lastTradeTS = ts
}
// 使用模板的接口函数
$.PosMonitor(0, "ETH_USDT", "swap") // 可以设置多个监控,监控带单策略上的不同的exchange对象
var tbl = $.getTbl()
// 显示状态栏
LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
Sleep(1000)
}
}
Desainnya sangat sederhana, pustaka kelas ini memiliki 2 fungsi fungsional. Ketika strategi perdagangan terprogram pada platform FMZ merujuk订单同步管理系统类库(Single Server)
Setelah pustaka templat. Strategi ini dapat menggunakan fungsi berikut.
$.PosMonitor Fungsinya adalah untuk memantau perubahan posisi objek pertukaran dalam strategi, lalu mengirimkan sinyal perdagangan ke pasar riil yang ditetapkan dalam parameter templat: Pustaka Kelas Sistem Manajemen Sinkronisasi Pesanan (Server Tunggal).
$.getTbl Mengembalikan data sinkronisasi yang dipantau.
Contoh penggunaan ada di: Template Perpustakaan Kelas Sistem Manajemen Sinkronisasi Pesanan (Server Tunggal)main
Dalam fungsi:
// 引用该模板类库的策略调用范例
function main() {
// 清除所有日志
LogReset(1)
// 切换到OKEX 模拟盘测试
exchanges[0].IO("simulate", true)
// 设置合约
exchanges[0].SetCurrency("ETH_USDT")
exchanges[0].SetContractType("swap")
// 定时交易时间间隔
var tradeInterval = 1000 * 60 * 3 // 三分钟交易一次,用于观察跟单信号
var lastTradeTS = new Date().getTime()
while (true) {
// 策略其它逻辑...
// 用于测试的模拟交易触发
var ts = new Date().getTime()
if (ts - lastTradeTS > tradeInterval) {
Log("模拟带单策略发生交易,持仓变化", "#FF0000")
exchanges[0].SetDirection("buy")
exchanges[0].Buy(-1, 1)
lastTradeTS = ts
}
// 使用模板的接口函数
$.PosMonitor(0, "ETH_USDT", "swap") // 可以设置多个监控,监控带单策略上的不同的exchange对象
var tbl = $.getTbl()
// 显示状态栏
LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
Sleep(1000)
}
}
Pustaka templat itu sendiri juga dapat membuat strategi nyata, yang biasanya digunakan untuk menguji pustaka templat. Misalnya, uji coba templat ini. Anda dapat memahami templatenyamain
Fungsi adalah strategi milik Anda sendiri.main
fungsi.
Kode pengujian ditulis untuk menggunakan pengujian disk simulasi OKEX. Anda perlu mengonfigurasi KUNCI API disk simulasi OKEX di FMZ sebagai akun referensi (dengan perintah), dan mulai beralih ke disk simulasi di fungsi utama. Kemudian atur pasangan perdagangan ke ETH_USDT dan kontrak ke perpetual (swap). Lalu masukkan loop while. Perintah ditempatkan setiap 3 menit dalam siklus untuk mensimulasikan pemicu perdagangan strategi. Perulangan while memanggil$.PosMonitor(0, "ETH_USDT", "swap")
Parameter pertama dari fungsi ini dilewatkan sebagai 0, yang menunjukkan pertukaran pemantauan[0] Objek pertukaran ini memantau pasangan perdagangan ETH_USDT dan kontrak swap. Lalu panggil$.getTbl()
Untuk mendapatkan informasi grafik, gunakanLogStatus(_D(), "\n" + "
” + JSON.stringify(tbl) + “")
Memungkinkan data bagan ditampilkan pada bilah status.
Jadi Anda lihat, selama Anda menggunakannya dalam kebijakan yang merujuk pada templat ini$.PosMonitor(0, "ETH_USDT", "swap")
, strategi tersebut dapat dilengkapi dengan fungsi memantau posisi produk tertentu dan mengirimkan pesan berdasarkan perubahan posisi.
Sebelum melakukan pengujian, mohon dijelaskan订单同步管理系统类库(Single Server)
Desain parameter strategi:
Saya baru saja berbicara tentang cara menggunakan fungsi antarmuka templat untuk mengaktifkan peningkatan strategi agar memiliki satu fungsi. Jadi kepada siapa sinyal dikirimkan ketika posisi berubah?
Kepada siapa pertanyaan ini ditujukan ditentukan oleh订单同步管理系统类库(Single Server)
Parameter yang akan dikonfigurasi.
Anda dapat melihat ada 5 parameter, yang mendukung hingga 5 push (Anda dapat memperluasnya jika perlu menambahnya), dan parameter tersebut secara default berisi string kosong, yang berarti tidak diproses. Format string konfigurasi: label, robotId, accessKey, secretKey
label Label akun yang disinkronkan digunakan untuk menandai akun tertentu, dan namanya dapat diatur sesuai keinginan.
robotId
ID asli, dibuat oleh pemilik akun sinkronisasi订单同步管理系统(Synchronous Server)
ID transaksi sesungguhnya.
accessKey Akses API FMZ yang diperluas
secretKey API rahasia FMZ yang diperluas
Berikutnya kita dapat melakukan tes sederhana.
Kelas perpustakaan sistem manajemen sinkronisasi pesanan (Server Tunggal) operasi disk nyata:
Sistem manajemen sinkronisasi pesanan (Synchronous Server) menerima sinyal: Kami belum menyelesaikan desain sistem manajemen sinkronisasi pesanan (Synchronous Server). Mari kita implementasikan terlebih dahulu dengan kode sederhana yang tidak melakukan transaksi tetapi hanya mencetak sinyal:
Kode sementara sistem manajemen sinkronisasi pesanan (Server Sinkron):
function main() {
LogReset(1)
while (true) {
var cmd = GetCommand()
if (cmd) {
// cmd: ETH_USDT,swap,buy,1
Log("cmd: ", cmd)
}
Sleep(1000)
}
}
Anda dapat melihat bahwa akun sebenarnya dari pemilik akun sinkronisasi telah menerima informasi:ETH_USDT,swap,buy,1
。
Dengan cara ini, langkah selanjutnya adalah secara otomatis mengikuti perintah berdasarkan pasangan perdagangan, kode kontrak, arah perdagangan, dan kuantitas dalam informasi.
saat ini订单同步管理系统(Synchronous Server)
Ini hanyalah kode sementara, kami akan terus mengeksplorasi desainnya di edisi berikutnya.