In früheren Artikeln der FMZ-Bibliothek haben wir mehrere Strategien zur Auftrags- und Positionssynchronisierung entwickelt.
Diese dienen dazu, das Referenzkonto und das Synchronisationskonto in einer Strategie zusammenzuführen, um Aufträge und Positionen zu verwalten und zu synchronisieren. Heute werden wir ein anderes Design ausprobieren. Basierend auf der leistungsstarken erweiterten API-Schnittstelle der quantitativen Handelsplattform FMZ werden wir ein Auftragssynchronisationsmanagementsystem entwickeln.
Zunächst brauchen wir einige gute Vorschläge und Wünsche. Die beiden oben genannten Strategien zur Synchronisierung von Aufträgen und Positionen weisen mehrere offensichtliche Schwachstellen auf. Lassen Sie uns diese gemeinsam besprechen:
Lösung:
Mithilfe der erweiterten API-Schnittstelle von FMZ muss der Inhaber des Synchronisationskontos (Follower) lediglich die quantitative Handelsplattform von FMZ registrieren und dann eine Strategie ausführen (in dem in diesem Artikel entworfenen System:订单同步管理系统(Synchronous Server)
Strategie realer Markt). Geben Sie dann den erweiterten API-Schlüssel der FMZ (Achtung, nicht den API-Schlüssel des Börsenkontos) und die Echtzeit-ID des Auftragssynchronisationsverwaltungssystems (Synchronous Server) an den Inhaber des Referenzkontos (die Person, die den Auftrag einbringt) weiter. .
Wenn es sich um die tatsächliche Bestellung des Kontoinhabers (desjenigen mit der Bestellung) handelt (im in diesem Artikel beschriebenen System)订单同步管理系统类库(Single Server)
) ein Signal sendet, empfängt das reale Konto des synchronisierten Kontoinhabers das Handelssignal und platziert anschließend automatisch eine Bestellung.
订单同步管理系统类库(Single Server)
Strategie) ermöglicht es dem Inhaber des Referenzkontos (der Person, die die Bestellung entgegennimmt), diese Vorlagenbibliothek direkt in seine eigene Strategie einzubetten, um die Funktion zur Synchronisierung von Bestellungen und Positionen zu erreichen.Dieses System besteht also aus 2 Teilen: 1. Klassenbibliothek für das Auftragssynchronisationsmanagementsystem (Einzelserver) 2. Synchrones Managementsystem bestellen (Synchronous Server)
Nachdem die Anforderungen nun klar sind, können wir mit dem Entwurf beginnen!
Beachten Sie, dass dies keine Strategie ist. Es handelt sich um eine Vorlagenklassenbibliothek von FMZ. Das Konzept der Vorlagenklassenbibliothek kann in der FMZ-API-Dokumentation nachgeschlagen werden, daher werde ich hier nicht näher darauf eingehen.
Code der Vorlagenbibliothek:
// 全局变量
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)
}
}
Das Design ist sehr einfach, diese Klassenbibliothek hat 2 Funktionsfunktionen. Wenn eine programmatische Handelsstrategie auf der FMZ-Plattform auf订单同步管理系统类库(Single Server)
Nach der Vorlagenbibliothek. Diese Strategie kann die folgende Funktion verwenden.
$.PosMonitor Die Funktion besteht darin, die Positionsänderungen des Börsenobjekts in der Strategie zu überwachen und dann Handelssignale an den realen Markt zu senden, die in den Parametern der Vorlage festgelegt sind: Order Synchronization Management System Class Library (Single Server).
$.getTbl Gibt die überwachten Synchronisierungsdaten zurück.
Das Anwendungsbeispiel finden Sie in: Vorlage für die Klassenbibliothek des Order Synchronization Management Systems (Einzelserver)main
In der Funktion:
// 引用该模板类库的策略调用范例
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)
}
}
Eine Vorlagenbibliothek selbst kann auch echte Strategien erstellen, was normalerweise zum Testen der Vorlagenbibliothek verwendet wird. Beispielsweise ein Test dieser Vorlage. Sie können die Vorlage verstehenmain
Eine Funktion ist eine eigene Strategie.main
Funktion.
Der Testcode wurde geschrieben, um den OKEX-Simulationsdiskettentest zu verwenden. Es ist erforderlich, den API-Schlüssel der OKEX-Simulationsdiskette auf FMZ als Referenzkonto (mit Bestellungen) zu konfigurieren und in der Hauptfunktion mit dem Umschalten auf die Simulationsdiskette zu beginnen. Stellen Sie dann das Handelspaar auf ETH_USDT und den Vertrag auf unbefristet (Swap) ein. Geben Sie dann eine While-Schleife ein. Um die Auslösung des Strategiehandels zu simulieren, wird im Zyklus alle 3 Minuten eine Order platziert. Die while-Schleife ruft auf$.PosMonitor(0, "ETH_USDT", "swap")
Der erste Parameter dieser Funktion wird als 0 übergeben, was bedeutet, dass der Austausch überwacht wird.[0] Dieses Exchange-Objekt überwacht das ETH_USDT-Handelspaar und den Swap-Vertrag. Dann rufen Sie$.getTbl()
Um Diagramminformationen zu erhalten, verwenden SieLogStatus(_D(), "\n" + "
” + JSON.stringify(tbl) + “")
Aktiviert die Anzeige von Diagrammdaten in der Statusleiste.
Sie sehen also, solange Sie es in einer Richtlinie verwenden, die auf diese Vorlage verweist,$.PosMonitor(0, "ETH_USDT", "swap")
, kann die Strategie mit der Funktion ausgestattet werden, die Positionen eines bestimmten Produkts zu überwachen und Nachrichten basierend auf Positionsänderungen zu senden.
Bitte erklären Sie vor dem Testen订单同步管理系统类库(Single Server)
Gestaltung der Strategieparameter:
Ich habe gerade darüber gesprochen, wie man die Vorlagenschnittstellenfunktion verwendet, um ein Strategie-Upgrade mit einer einzigen Funktion zu ermöglichen. An wen wird also das Signal gesendet, wenn sich die Position ändert?
An wen diese Frage gesendet wird, bestimmt订单同步管理系统类库(Single Server)
Zu konfigurierende Parameter.
Sie können sehen, dass es 5 Parameter gibt, die bis zu 5 Pushes unterstützen (Sie können es erweitern, wenn Sie es erhöhen müssen), und der Parameter ist standardmäßig eine leere Zeichenfolge, was bedeutet, dass er nicht verarbeitet wird. Format der Konfigurationszeichenfolge: Bezeichnung, Roboter-ID, Zugriffsschlüssel, geheimer Schlüssel
label Die Bezeichnung des synchronisierten Kontos dient zur Kennzeichnung eines bestimmten Kontos und der Name kann beliebig festgelegt werden.
robotId
Reale ID, erstellt vom Besitzer des Synchronisationskontos订单同步管理系统(Synchronous Server)
Die ID der tatsächlichen Transaktion.
accessKey Erweiterter API-Zugriffsschlüssel der FMZ
secretKey FMZ’s erweiterte API secretKey
Als nächstes können wir einen einfachen Test durchführen.
Bestellsynchronisationsverwaltungssystem-Klassenbibliothek (Einzelserver) Realplattenbetrieb:
Das Auftragssynchronisationsverwaltungssystem (Synchronous Server) hat das Signal erhalten: Wir haben den Entwurf des Auftragssynchronisationsmanagementsystems (Synchronous Server) noch nicht abgeschlossen. Lassen Sie uns es zunächst mit einem einfachen Code implementieren, der keine Transaktionen durchführt, sondern nur Signale druckt:
Temporärer Code des Auftragssynchronisationsverwaltungssystems (Synchronous Server):
function main() {
LogReset(1)
while (true) {
var cmd = GetCommand()
if (cmd) {
// cmd: ETH_USDT,swap,buy,1
Log("cmd: ", cmd)
}
Sleep(1000)
}
}
Sie können sehen, dass das reale Konto des Besitzers des Synchronisierungskontos die Informationen erhalten hat:ETH_USDT,swap,buy,1
。
Auf diese Weise besteht der nächste Schritt darin, die Bestellung automatisch basierend auf dem Handelspaar, dem Vertragscode, der Handelsrichtung und der Menge in den Informationen auszuführen.
derzeit订单同步管理系统(Synchronous Server)
Dies ist nur temporärer Code. Wir werden uns in der nächsten Ausgabe näher mit seinem Design befassen.