In den vorherigen Artikeln des FMZ Digest haben wir mehrere ordnungs- und positionssynchrone Strategien entwickelt.
Diese Entwürfe nehmen das Referenzkonto und das synchrone Konto in die gleiche Strategie ein, um die Synchronisierung von Aufträgen und Positionen zu realisieren.
Zunächst einmal brauchen wir einige gute Vorschläge und Anforderungen. Die oben genannten beiden vorherigen Orders und Positions-Synchronisierungsstrategien haben mehrere offensichtliche Nachteile. Lassen Sie uns sie gemeinsam diskutieren:
1.Die Benutzer, die die Strategie-Bot-Synchronisierung implementieren, müssen über den API-Schlüssel der Referenzkontoplattform und den API-Schlüssel des Synchronisierungskontos verfügen. Für das Nutzungsszenario ist das Problem: es ist in Ordnung, wenn Ihre anderen Plattformkonten einem Ihrer eigenen Konten folgen. Aber es kann für das Szenario, in dem das Referenzkonto und das Synchronisierungskonto nicht denselben Besitzer haben, schwierig sein. Der Besitzer des Synchronisierungskontos ist manchmal aus Sicherheitsgründen nicht bereit, den API-Key seines Plattformkontos zur Verfügung zu stellen. Aber wie kann man eine Bestellung für den Handel synchron ohne die Bereitstellung des API-Key platzieren?
Lösung:
Mit der erweiterten FMZ-API muss der Inhaber des Synchronisationskontos (der Auftragsüberwacher) nur die FMZ Quant-Handelsplattform registrieren und dann eine Strategie ausführen (im in diesem Artikel entworfenen System:Order Synchronous Management System (Synchronous Server)
Dann werden der erweiterte API-Key von FMZ (beachten Sie, dass es sich nicht um den API-Key des Plattformkontos handelt) und die Bot-ID des Auftrags-Synchronisierungsmanagementsystems (Synchronous Server) dem Eigentümer des Referenzkontos (dem Auftragsbesitzer) zur Verfügung gestellt.
Wenn der Bot des Referenzkontoinhabers (der Auftragsinhaber) (Order Synchronous Management System Library (Single Server)
In diesem Fall wird der Auftrag später automatisch platziert.
2.Viele Entwickler haben bessere Strategien und können die beiden vorherigen Strategien zur Synchronisierung von Reihenfolge und Position, die oben beschrieben wurden, nicht verwenden. Weil dies ihre eigenen Strategien mit diesen Synchronisierungsstrategien zusammenführen muss, und ihre Strategien möglicherweise stark geändert werden müssen, was zeitaufwendig und arbeitsintensiv ist. Gibt es eine gute Möglichkeit, einige Ihrer ausgereiften Strategien direkt auf diejenigen mit der Reihenfolge Synchronisierungsfunktion zu aktualisieren?
Lösung:
Sie können eine synchrone Template-Bibliothek (dieOrder Synchronous Management System Library (Single Server)
Strategie im im Artikel entworfenen System), so daß der Inhaber des Referenzkontos (der Auftragseigentümer) diese Vorlagenbibliothek direkt in seine eigene Strategie einfügen kann, um eine Synchronisierung von Reihenfolge und Position zu erreichen.
3.Reduzieren Sie einen zusätzlichen Bot Der letzte Nachteil besteht darin, dass, wenn Sie die beiden vorherigen Befehle und die oben beschriebenen Positionssynchronisationsstrategien verwenden, eine zusätzliche Position des Referenzkontos (Konto mit Aufträgen) für die Bot-Überwachung eröffnet werden muss. Lösung: Verwenden Sie die Template-Bibliothek, um die Funktion in die Referenzkonto-Strategie einzubauen.
Das System besteht daher aus zwei Teilen: 1.Order synchrone Verwaltungssystembibliothek (Single Server) 2.Synchrone Verwaltung von Aufträgen (Synchrone Server)
Sobald wir unsere Forderungen erkannt haben, fangen wir an zu entwerfen!
Beachten Sie, dass es sich hier nicht um eine Strategie handelt, sondern um eine FMZ-Vorlagebibliothek, die in der FMZ-API-Dokumentation durchsucht werden kann und die wir hier nicht diskutieren werden.
Code der Muster:
// Global variable
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 position
var tradeDirection = type == PD_LONG ? "buy" : "sell"
// Send signal
msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)
} else if (delta < 0) {
// Open position
var tradeDirection = type == PD_LONG ? "closebuy" : "closesell"
if (nowAmount <= 0) {
Log("No position detected")
return
}
// Send signal
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 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 support futures order supervising"
}
if (exType == "futures") {
// Cache symbol ct
var buffSymbol = ex.GetCurrency()
var buffCt = ex.GetContractType()
// Switch to the corresponding trading pair and contract code
ex.SetCurrency(symbol)
if (!ex.SetContractType(ct)) {
throw "SetContractType failed"
}
// Monitor position
var keyInitRefPosAmount = "refPos-" + exIndex + "-" + symbol + "-" + ct // refPos-exIndex-symbol-contractType
var initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
if (!initRefPosAmount) {
// The data is not initialized; initialize it
mapInitRefPosAmount[keyInitRefPosAmount] = getPosAmount(_C(ex.GetPosition), ct)
initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
}
// Monitor
var nowRefPosAmount = getPosAmount(_C(ex.GetPosition), ct)
// Calculate position changes
var longPosDelta = nowRefPosAmount.long - initRefPosAmount.long
var shortPosDelta = nowRefPosAmount.short - initRefPosAmount.short
// Detect changes
if (!(longPosDelta == 0 && shortPosDelta == 0)) {
// Execute long position action
if (longPosDelta != 0) {
Log(ex.GetName(), ex.GetLabel(), symbol, ct, "Execute long position order supervision, change volume:", longPosDelta)
follow(nowRefPosAmount, symbol, ct, PD_LONG, longPosDelta)
}
// Execute short position action
if (shortPosDelta != 0) {
Log(ex.GetName(), ex.GetLabel(), symbol, ct, "Execute short position order supervision, change volume:", shortPosDelta)
follow(nowRefPosAmount, symbol, ct, PD_SHORT, shortPosDelta)
}
// After executing the order supervision operation, update
mapInitRefPosAmount[keyInitRefPosAmount] = nowRefPosAmount
}
// Recover symbol ct
ex.SetCurrency(buffSymbol)
ex.SetContractType(buffCt)
} else if (exType == "spot") {
// Spot
}
}
$.getTbl = function() {
var tbl = {
"type" : "table",
"title" : "Synchrodata",
"cols" : [],
"rows" : []
}
// Construct the table title
tbl.cols.push("Monitoring account:refPos-exIndex-symbol-contractType")
tbl.cols.push(`Mintoring position:{"timestamp":xxx,"long position volume":xxx,"short position volume":xxx}`)
_.each(fmzExtendApis, function(extendApiData, index) {
tbl.cols.push(keyName_robotId + "-" + index)
})
// Write in the data
_.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
}
// Invocation example of the strategy in the template
function main() {
// Clear all logs
LogReset(1)
//Switch to OKEX simulated bot test
exchanges[0].IO("simulate", true)
// Set contract
exchanges[0].SetCurrency("ETH_USDT")
exchanges[0].SetContractType("swap")
// Timed trading time interval
var tradeInterval = 1000 * 60 * 3 // trade every three minutes, to observe the order supervising signal
var lastTradeTS = new Date().getTime()
while (true) {
// Other logic of the strategy...
// Used to test the simulated trade trigger
var ts = new Date().getTime()
if (ts - lastTradeTS > tradeInterval) {
Log("Simulated strategy with orders has trades, and positions changed", "#FF0000")
exchanges[0].SetDirection("buy")
exchanges[0].Buy(-1, 1)
lastTradeTS = ts
}
// Call the interface function in the template
$.PosMonitor(0, "ETH_USDT", "swap") // You can set multiple monitors, to minitor different exchange objects in the strategy with orders
var tbl = $.getTbl()
// Display the status bar
LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
Sleep(1000)
}
}
Das Design ist sehr einfach, die Bibliothek hat 2 Funktionen.Order Synchronous Management System Library (Single Server)
Diese Strategie kann dann die folgenden Funktionen verwenden.
Das Anwendungsbeispiel istmain
Funktion in der Bibliothek des ordnungssynchronen Managementsystems (Single Server):
// Invocation example of the strategy in the template
function main() {
// Clear all logs
LogReset(1)
// Switch to OKEX simulated bot test
exchanges[0].IO("simulate", true)
// Set contract
exchanges[0].SetCurrency("ETH_USDT")
exchanges[0].SetContractType("swap")
// Timed trading time interval
var tradeInterval = 1000 * 60 * 3 // trade every three minutes, to observe the order supervising signal
var lastTradeTS = new Date().getTime()
while (true) {
// Other logic of the strateg...
// Used to test the simulated trade trigger
var ts = new Date().getTime()
var ts = new Date().getTime()
if (ts - lastTradeTS > tradeInterval) {
Log("Simulated strategy with orders has trades, and positions changed", "#FF0000")
exchanges[0].SetDirection("buy")
exchanges[0].Buy(-1, 1)
lastTradeTS = ts
}
// Use the interface function of the template
$.PosMonitor(0, "ETH_USDT", "swap") // You can set multiple monitors to monitor different exchange objects on an strategy with orders
var tbl = $.getTbl()
// Display the status bar
LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
Sleep(1000)
}
}
Eine Template-Bibliothek selbst kann auch einen Strategie-Bot erstellen, der normalerweise verwendet wird, um die Template-Bibliothek zu testen.main
Funktion in der Vorlage ist diemain
Sie ist eine Funktion einer Ihrer eigenen Strategien.
Der Testcode wird geschrieben, um den OKEX simulierten Bot zu testen, und der API KEY des OKEX simulierten Bots muss auf FMZ als Referenzkonto (mit Orders) konfiguriert werden, und die Hauptfunktion beginnt, auf den simulierten Bot zu wechseln. Setzen Sie dann das Handelspaar auf ETH_USDT und setzen Sie den Vertrag auf Swap. Dann geben Sie eine While-Schleife ein. In der Schleife wird alle 3 Minuten ein Auftrag platziert, um den Auslöser der Strategie-Trades zu simulieren.$.PosMonitor(0, "ETH_USDT", "swap")
wird in der while-Schleife aufgerufen, und der erste Parameter der aufgerufenen Funktion ist 0, was bedeutet, dass die Exchange-Objekt-Exchanges[0], das Handelspärchen ETH_USDT und den Swap-Kontrakt überwacht werden.$.getTbl()
Sie können die Informationen aus dem Diagramm erhalten und verwenden.LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
um die auf der Statusleiste angezeigten Diagrammdaten zu erstellen.
Also sehen Sie, solange$.PosMonitor(0, "ETH_USDT", "swap")
wird in einer Strategie verwendet, die die Vorlage aufruft, kann die Strategie die Funktion haben, eine bestimmte Symbolposition zu überwachen und die Positionsänderungsmeldung zu senden.
Vor der Prüfung ist die Parameterkonstruktion des Prüfgerätes zu erklären.Order Synchronous Management System Library (Single Server)
Strategie:
Ich habe gerade darüber gesprochen, wie man die Schnittstellenfunktion der Vorlage nutzt, um ein Strategie-Upgrade mit einer Funktion der Auftragsabwicklung zu machen.
Die Frage, an wen man senden soll, wird durch die Parameter derorder synchronous management system library (Single Server)
.
Sie können fünf Parameter sehen, die maximal fünf Pushes unterstützen können (wenn Sie die Push-Nummer erhöhen müssen, können Sie sie selbst erweitern); der Standard der Parameter ist eine leere Zeichenfolge, nämlich nicht verarbeitet.
Etikett Das Etikett des synchronen Kontos, das verwendet wird, um ein Konto zu kennzeichnen; der Etikettenname kann zufällig festgelegt werden.
RobotId
Die Bot-ID; die Bot-ID desorder synchronous management system (Synchronous Server)
vom Eigentümer des synchronen Kontos erstellt.
Zugriffsschlüssel Der AccessKey der FMZ erweiterte API.
Geheimer Schlüssel Der geheime Schlüssel der FMZ erweiterte API.
Dann können wir einen einfachen Test durchführen.
Befehl der Bot-Bedienung für die Synchronous Management System Library (Single Server):
Der Bot des Synchronous Management Systems (Synchronous Server) erhielt das Signal: Order Synchronous Management System (Synchronous Server) ist jetzt noch nicht vollständig von uns entworfen worden, und wir können einen einfachen Code verwenden, um es zu realisieren, ohne Handel, nur Drucksignal:
Bestellung Synchronous Management System (Synchronous Server) vorübergehender Code:
function main() {
LogReset(1)
while (true) {
var cmd = GetCommand()
if (cmd) {
// cmd: ETH_USDT,swap,buy,1
Log("cmd: ", cmd)
}
Sleep(1000)
}
}
Wie Sie sehen können, erhielt der Bot des Eigentümers des synchronen Kontos die Nachricht:ETH_USDT,swap,buy,1
- Ich weiß.
So können wir im nächsten Schritt automatisch Aufträge nach Handelspaar, Vertragskode, Handelsrichtung und Volumen überwachen.
Derzeitorder synchronous management system (Synchronous Server)
ist nur ein vorübergehender Code, und wir können seinen Entwurf im nächsten Artikel weiter besprechen.