Conception d'un système de gestion de la synchronisation des commandes basé sur FMZ Quant (1)

Auteur:Je ne sais pas., Créé: 2022-11-07 10:20:01, Mis à jour: 2023-09-15 20:45:23

img

Conception d'un système de gestion de la synchronisation des commandes basé sur FMZ Quant (1)

Dans des articles précédents dans la bibliothèque FMZs, nous avons conçu plusieurs types de stratégies de synchronisation pour l'ordre et la position.

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.

Idées de conception

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.

    1. Les utilisateurs de stratégies de synchronisation réel bot doivent avoir l'échange API KEY du compte de référence, et l'échange API KEY du compte de synchronisation. Ce problème est bien pour la situation d'utilisation où les autres comptes d'échange suivent son propre compte. Cependant, il peut être gênant pour la situation où le compte de référence et le compte de synchronisation ne sont pas le même propriétaire. Parfois, le propriétaire du compte synchronisé ne veut pas fournir la clé API de son propre compte d'échange pour des raisons de sécurité, mais comment synchroniser les transactions de commande sans fournir la clé API?

    Les solutions: Utiliser l'interface API étendue de FMZ, le propriétaire du compte synchronisé (suiveur de commande) n'a qu'à enregistrer un compte sur la plateforme de trading FMZ Quant, puis exécuter une stratégie (dans le système conçu dans cet article:Order Synchronous ServerEnsuite, 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.

    1. Beaucoup de développeurs ont de bonnes stratégies, mais ils ne peuvent pas utiliser les 2 stratégies de synchronisation d'ordre et de position décrites ci-dessus. Parce qu'ils ont besoin d'intégrer leurs propres stratégies avec ces stratégies synchronisées, et les stratégies peuvent avoir besoin d'être radicalement modifiées, ce qui coûtera beaucoup de travail et d'effort. Y a-t-il un bon moyen de mettre à niveau certaines de vos stratégies matures directement vers la fonction de synchronisation d'ordre? Les solutions: Vous pouvez concevoir une bibliothèque de classe de modèle de synchronisation d'ordre (leOrder 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.
    1. Réduire un vrai robot supplémentaire. Le dernier inconvénient est que si vous utilisez les 2 commandes passées, la stratégie de synchronisation des positions décrite ci-dessus. Il est nécessaire d'ouvrir un bot réel supplémentaire pour surveiller les positions du compte de référence (compte pour les chefs d'ordre). Les solutions: Utilisez la bibliothèque de classes de modèle pour intégrer des fonctionnalités dans la stratégie de compte de référence.

Donc le système se compose de 2 parties:

  1. Bibliothèque de classes du système de gestion de la synchronisation des commandes (serveur unique)
  2. Système de gestion de la synchronisation des commandes (serveur synchrone)

Une fois que nous avons défini nos besoins, commençons à concevoir!

Conception 1: bibliothèque de classes du système de gestion de la synchronisation des commandes (serveur unique)

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 lemainfonction 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.mainla fonction dans un modèle est lamainfonction 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).

img

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 ServerUn 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)
    }
}

img

Nous pouvons voir que le vrai bot du propriétaire du compte synchronisé a reçu le message:ETH_USDT,swap,buy,1Je 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.


Relationnée

Plus de