Dans des articles précédents dans la bibliothèque FMZ
Ils gèrent les comptes de référence et les comptes synchronisés dans une seule stratégie pour réaliser la synchronisation des ordres et des positions.
Les deux précédentes stratégies de synchronisation d'ordre et de position ci-dessus, qui présentent plusieurs lacunes évidentes, que nous aborderons ensemble.
Les solutions:
Utiliser l'interface API étendue de FMZOrder Synchronous Server
Ensuite, il suffit de fournir la clé API étendue FMZ (notez qu'il ne s'agit pas de la clé API du compte d'échange) et l'ID de bot réel du serveur synchrone de commande au propriétaire du compte de référence (leader de commande).
Lorsque le propriétaire du compte de référence (les suiveurs de commande)Order Synchronization Management System Class Library (Single Server)
Dans le cas où un robot (ou un robot) envoie un signal, le propriétaire du compte de synchronisation reçoit le signal de trading et passe automatiquement la commande suivante.
Order Synchronization Management System Class Library (Single Server)
L'opération de synchronisation de l'ordre et de la position peut être effectuée directement par le propriétaire du compte de référence (leader de commande) dans sa propre stratégie.Donc le système se compose de 2 parties:
Une fois que nous avons défini nos besoins, commençons à concevoir!
Notez que ce n'est pas une stratégie. C'est une bibliothèque de classe de modèle de FMZ. Le concept d'une bibliothèque de classe de modèle peut être recherché dans la documentation de l'API FMZ et nous ne le répéterons pas.
Code de bibliothèque de classe modèle:
// 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)
}
}
La conception est très simple, la bibliothèque de classes a 2 fonctions fonctionnelles.Order Synchronization Management System Class Library (Single Server)
. Ensuite, la stratégie peut utiliser les fonctions suivantes.
$. Moniteur de positionnement. Le but de cette fonction est de surveiller les changements de position des objets d'échange dans la stratégie, puis d'envoyer des signaux de négociation au marché réel des robots définis dans les paramètres du modèle: Bibliothèque de classes du système de gestion de la synchronisation des commandes (serveur unique).
$. gagne Retournez aux données de synchronisation surveillées.
Un exemple d'utilisation est donné dans lemain
fonction du modèle de bibliothèque de classes du système de gestion de la synchronisation des commandes (serveur unique):
// 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)
}
}
Une bibliothèque de classe de modèle peut également créer un bot de stratégie réel par lui-même, qui est généralement utilisé pour tester la bibliothèque de classe de modèle, comme le test du modèle.main
la fonction dans un modèle est lamain
fonction d'une de vos propres stratégies.
Le code de test est écrit en utilisant la démo OKEX pour tester, vous devez configurer la clé API de démo OKEX sur FMZ en tant que compte de référence (ordre-leading), et il commence à passer à la démo dans la fonction principale. Ensuite, définissez la paire de trading sur ETH_USDT et définissez le contrat pour échanger. Ensuite, il entre dans une boucle while. Dans la boucle, un ordre est placé toutes les 3 minutes pour simuler le déclenchement des transactions de stratégie.$.PosMonitor(0, "ETH_USDT", "swap")
est appelé dans la boucle while, le premier paramètre de cette fonction est passé à 0, ce qui signifie surveiller les échanges d'objets d'échange[0], surveiller la paire de négociation ETH_USDT, le contrat de swap.$.getTbl()
Pour obtenir des informations sur les graphiques,LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
pour faire apparaître les données du graphique sur la barre d'état.
Donc, nous pouvons voir que nous pouvons faire la stratégie ont la capacité de surveiller les positions d'une certaine espèce, et les changements de position pour envoyer des messages en utilisant$.PosMonitor(0, "ETH_USDT", "swap")
Dans le cas de l'exposé à risque, le montant de l'exposé à risque est le montant de l'exposé à risque.
Avant les tests, nous expliquerons la conception des paramètres stratégiques de laOrder Synchronization Management System Class Library (Single Server)
Je suis désolée.
Nous venons de parler de la façon d'utiliser la fonction d'interface d'un modèle pour mettre à niveau une stratégie pour avoir une fonction de commandes.
La question de savoir à qui envoyer est configurée par les paramètres de laOrder Synchronization Management System Class Library (Single Server)
.
Nous pouvons voir qu'il y a 5 paramètres, prenant en charge jusqu'à 5 poussées (il peut être étendu par eux-mêmes si elle a besoin d'augmentation), les paramètres par défaut sont des chaînes vides, c'est-à-dire non traitées.
étiquette Une étiquette pour un compte de synchronisation, elle est utilisée pour définir une étiquette pour un compte avec un nom qui peut être défini à volonté.
robotId
L'identifiant du robot, l'identifiant duOrder Synchronous Server
Un vrai bot créé par le propriétaire du compte synchrone.
accèsClé Accès étendu à l'APIClé de FMZ
Clé secrète Clé secrète d'API étendue de FMZ
Le code temporaire du système de gestion de la synchronisation des commandes (serveur synchrone):
function main() {
LogReset(1)
while (true) {
var cmd = GetCommand()
if (cmd) {
// cmd: ETH_USDT,swap,buy,1
Log("cmd: ", cmd)
}
Sleep(1000)
}
}
Nous pouvons voir que le vrai bot du propriétaire du compte synchronisé a reçu le message:ETH_USDT,swap,buy,1
Je suis désolée.
Ensuite, il nous permettra de faire notre propre ordre automatique suivant dans l'étape suivante basée sur les paires trading, les codes de contrat, les directions commerciales, et le montant de l'information.
Jusqu'à présent, leOrder Synchronization Management System (Synchronous Server)
est le code temporaire, nous continuerons à explorer sa conception dans le prochain numéro.