In früheren Artikeln in FMZ
Diese verwalten Referenzkonten und synchronisierte Konten in einer Strategie, um Order- und Positionssynchronisierung zu erreichen.
Zuerst brauchen wir einige gute Vorschläge und Bedürfnisse. Die beiden vorherigen Ordnung und Position Synchronisation Strategien oben, die mehrere offensichtliche Mängel haben, die wir gemeinsam diskutieren werden.
Lösungen:
Mit der erweiterten API-Schnittstelle von FMZOrder Synchronous Server
Strategie in Real Bot). Dann geben Sie einfach den FMZ erweiterten API KEY (beachten Sie, dass es nicht der API KEY des Austauschkontos ist) und die Order Synchronous Server real bot ID an den Eigentümer des Referenzkontos (Order Leader).
Wenn der Eigentümer des Referenzkontos (der Auftragsnachfolger) einen echten Bot (denOrder Synchronization Management System Class Library (Single Server)
In diesem Artikel wird ein Signal gesendet, wird der echte Bot des Synchronisierungskontoinhabers das Handelssignal empfangen und automatisch den nachfolgenden Auftrag erteilen.
Order Synchronization Management System Class Library (Single Server)
Strategie im in diesem Artikel entworfenen System), so daß der Eigentümer des Referenzkontos (Order-Leader) diese Vorlage-Klassenbibliothek direkt in seine eigene Strategie einbetten kann, um die Funktion der Reihenfolge- und Positionssynchronisierung zu erreichen.Das System besteht also aus zwei Teilen:
Sobald wir unsere Bedürfnisse definiert haben, fangen wir an zu entwerfen!
Beachten Sie, dass dies keine Strategie ist. Es handelt sich um eine Template-Klasse-Bibliothek von FMZ. Das Konzept einer Template-Klasse-Bibliothek kann in der FMZ API-Dokumentation gesucht werden und wir werden es nicht wiederholen.
Code der Template-Klassenbibliothek:
// 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)
}
}
Das Design ist sehr einfach, die Klassenbibliothek hat 2 Funktionen.Order Synchronization Management System Class Library (Single Server)
. Dann kann die Strategie die folgenden Funktionen verwenden.
$. Positor-Monitor Zweck dieser Funktion ist es, die Positionsänderungen der Austauschobjekte in der Strategie zu überwachen und dann Handelssignale an den echten Bot-Markt zu senden, der in den Parametern der Vorlage: Order Synchronization Management System class library (Single Server) festgelegt ist.
$. GetTbl Zurück zu den überwachten Synchronisierungsdaten.
Ein Beispiel für die Verwendung ist in dermain
Funktion der Vorlage Klassenbibliothek (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)
}
}
Eine Template-Klassenbibliothek kann auch einen Strategie-Real-Bot selbst erstellen, der normalerweise verwendet wird, um die Template-Klassenbibliothek zu testen, wie zum Beispiel die Prüfung der Vorlage.main
Funktion in einer Vorlage istmain
Sie ist eine Funktion einer Ihrer eigenen Strategien.
Der Testcode wird mit dem OKEX-Demo geschrieben, um zu testen, müssen Sie den OKEX-Demo-API-Key auf FMZ als Referenzkonto (Order-Leading) konfigurieren, und er beginnt in der Hauptfunktion auf Demo zu wechseln. Setzen Sie dann das Handelspaar auf ETH_USDT und setzen Sie den Vertrag auf Swap. Dann tritt er in eine While-Schleife ein. In der Schleife wird alle 3 Minuten ein Auftrag platziert, um das Auslösen von Strategie-Transaktionen zu simulieren.$.PosMonitor(0, "ETH_USDT", "swap")
Wenn die ETH-Funktion in der while-Schleife aufgerufen wird, wird der erste Parameter dieser Funktion auf 0 übergeben, was bedeutet, dass die Exchange-Objekt-Austausch[0] überwacht wird, das ETH_USDT-Handelspaar überwacht wird, der Swap-Kontrakt.$.getTbl()
Um Informationen über die Diagramme zu erhalten, werdenLogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
um die auf der Statusleiste angezeigten Diagrammdaten zu erstellen.
Also können wir sehen, dass wir die Strategie haben die Fähigkeit, die Positionen einer bestimmten Spezies zu überwachen, und die Position ändert sich, um Nachrichten zu senden, indem Sie$.PosMonitor(0, "ETH_USDT", "swap")
In einer Strategie, die auf die Vorlage verweist.
Vor dem Testen werden wir die Strategieparameter desOrder Synchronization Management System Class Library (Single Server)
- Ich weiß.
Wir haben gerade darüber gesprochen, wie man die Schnittstellenfunktion einer Vorlage nutzt, um eine Strategie zu aktualisieren, um eine Funktion der Bestellführung zu haben.
Die Frage, wen man schicken soll, wird durch die Parameter derOrder Synchronization Management System Class Library (Single Server)
.
Wir können sehen, dass es 5 Parameter gibt, die bis zu 5 Pushes unterstützen (es kann von selbst erweitert werden, wenn es erhöht werden muss), die Standardparameter sind leere Zeichenfolgen, das heißt, nicht verarbeitet.
Etikett Ein Etikett für ein Synchronisierungskonto, es wird verwendet, um ein Etikett für ein Konto mit einem Namen zu setzen, das nach Belieben festgelegt werden kann.
RobotId
Roboter-ID, die ID desOrder Synchronous Server
Ein echter Bot, der vom Besitzer des synchronen Kontos erstellt wurde.
Zugriffsschlüssel Erweiterter API-Zugriff FMZ-Schlüssel
Geheimer Schlüssel Erweiterter API-Geheimschlüssel von FMZ
Der vorübergehende Code für das System zur Verwaltung der Auftragssynchronisierung (Synchronous Server):
function main() {
LogReset(1)
while (true) {
var cmd = GetCommand()
if (cmd) {
// cmd: ETH_USDT,swap,buy,1
Log("cmd: ", cmd)
}
Sleep(1000)
}
}
Wir können sehen, dass der echte Bot des synchronisierten Kontoinhabers die Nachricht erhielt:ETH_USDT,swap,buy,1
- Ich weiß.
Dann wird es uns ermöglichen, unsere eigenen automatischen Auftrag-nach dem nächsten Schritt basierend auf den trading Paare, Vertrag Codes, Handel Richtungen und Menge in der Information.
Bislang haben dieOrder Synchronization Management System (Synchronous Server)
ist der temporäre Code, werden wir seinen Entwurf in der nächsten Ausgabe weiter erforschen.