Les ressources ont été chargées... Je charge...

Conception d'un système de gestion synchrone basé sur les ordres FMZ (1)

Auteur:Je suis désolée., Créé: 2022-04-06 15:08:26, mis à jour: 2022-04-24 18:00:51

Conception d'un système de gestion synchrone basé sur les ordres FMZ (1)

Dans les articles précédents sur FMZ Digest, nous avons conçu plusieurs stratégies synchrones d'ordre et de position.

Ces conceptions prennent le compte de référence et le compte synchrone dans la même stratégie à gérer pour réaliser la synchronisation des ordres et des positions.

La pensée du design

Tout d'abord, nous avons besoin de quelques bonnes suggestions et exigences. Les deux précédentes stratégies de synchronisation d'ordres et de positions ont plusieurs inconvénients évidents.

  • 1.Les utilisateurs qui mettent en œuvre la stratégie de synchronisation des robots doivent disposer de la CLAVE API de la plateforme de compte de référence et de la CLAVE API du compte de synchronisation. Pour le scénario d'utilisation, le problème est le suivant: il est normal que vos autres comptes de plateforme suivent l'un de vos propres comptes. Mais cela peut être gênant pour le scénario où le compte de référence et le compte de synchronisation n'ont pas le même propriétaire. Le propriétaire du compte de synchronisation est parfois réticent à fournir la CLAVE API de son compte de plateforme en raison de considérations de sécurité. Mais comment passer un ordre de trading synchronisé sans fournir la CLAVE API?

    Résolution: Utiliser l'API étendue FMZ, le propriétaire du compte de synchronisation (le superviseur des ordres) a seulement besoin d'enregistrer la plateforme de trading FMZ Quant, puis d'exécuter une stratégie (dans le système conçu dans cet article:Order Synchronous Management System (Synchronous Server)Ensuite, la clé API étendue de FMZ (notez qu'il ne s'agit pas de la clé API du compte de la plateforme) et l'identifiant de bot du système de gestion de la synchronisation des commandes (serveur synchrone) seront fournis au propriétaire du compte de référence (le propriétaire de la commande). Lorsque le bot du propriétaire du compte de référence (le propriétaire de l'ordre) (Order Synchronous Management System Library (Single Server)Dans le cas où un robot de synchronisation (ou un robot de synchronisation) envoie un signal, le propriétaire du compte reçoit le signal de trading.

  • 2.Beaucoup de développeurs ont de meilleures stratégies et ne peuvent pas utiliser les deux précédentes stratégies de synchronisation d'ordre et de position décrites ci-dessus. Parce que cela nécessite de fusionner leurs propres stratégies avec ces stratégies de synchronisation, et leurs stratégies peuvent devoir être considérablement modifiées, ce qui prend du temps et de la main-d'œuvre. Y a-t-il un bon moyen de mettre à niveau directement certaines de vos stratégies matures à celles avec la fonction de synchronisation d'ordre?

    Résolution: Vous pouvez concevoir une bibliothèque de modèles synchrones de commande (leOrder Synchronous Management System Library (Single Server)L'expérience a montré qu'il est possible d'intégrer cette bibliothèque de modèles dans le système conçu dans l'article), de sorte que le propriétaire du compte de référence (le propriétaire de la commande) puisse insérer directement cette bibliothèque de modèles dans sa propre stratégie pour réaliser la synchronisation de l'ordre et de la position.

  • 3.Réduire un bot supplémentaire Le dernier inconvénient est que si vous utilisez les deux précédentes stratégies de synchronisation des ordres et des positions décrites ci-dessus, il est nécessaire d'ouvrir une position supplémentaire du compte de référence (compte avec des ordres) pour la surveillance des bots. Résolution: Utilisez la bibliothèque de modèles pour intégrer la fonction dans la stratégie de compte de référence.

Par conséquent, le système se compose de deux parties: 1. bibliothèque de système de gestion synchrone de commande (serveur unique) 2.système de gestion synchrone des commandes (serveur synchrone)

Une fois que nous sommes sûrs de nos exigences, commençons à concevoir!

Conception 1: Bibliothèque de système de gestion synchrone de commande (serveur unique)

Veuillez noter qu'il ne s'agit pas ici d'une stratégie, mais d'une bibliothèque de modèles FMZ, qui peut être recherchée dans la documentation FMZ API et dont nous ne discuterons pas ici.

Code du modèle:

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

La conception est très simple, la bibliothèque a 2 fonctions.Order Synchronous Management System Library (Single Server)Cette stratégie peut alors utiliser les fonctions suivantes.

  • $. PosMonitor est en ligne. L'effet de cette fonction est de surveiller les changements de position des objets d'échange dans la stratégie, puis d'envoyer des signaux de trading au bot défini dans les paramètres du modèle: commander synchrone management system library (Single Server).
  • $. getTbl La fonction renvoie les données synchrones surveillées.

L'exemple d'utilisation est lemainfonction dans la bibliothèque du système de gestion synchrone des commandes (serveur unique):

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

Une bibliothèque de modèles elle-même peut également créer un bot de stratégie, qui est généralement utilisé pour tester la bibliothèque de modèles.mainla fonction dans le modèle est lamainfonction d'une de vos propres stratégies.

Le code de test est écrit pour utiliser le bot simulé OKEX pour tester, et la clé API du bot simulé OKEX doit être configurée sur FMZ comme un compte de référence (avec des ordres), et la fonction principale commence à basculer vers le bot simulé. Ensuite, définissez la paire de trading sur ETH_USDT, et définissez le contrat pour échanger. Ensuite, entrez 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, et le premier paramètre de la fonction appelée est 0, ce qui signifie surveiller les échanges d'objets d'échange[0], la paire de trading ETH_USDT et le contrat de swap.$.getTbl()pour obtenir les informations du graphique, et utiliserLogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")pour faire apparaître les données du graphique sur la barre d'état.

Vous voyez, tant que$.PosMonitor(0, "ETH_USDT", "swap")est utilisé dans une stratégie qui appelle le modèle, la stratégie peut avoir pour fonction de surveiller une certaine position du symbole et de pousser le message de changement de position.

Avant l'essai, expliquer la conception des paramètres duOrder Synchronous Management System Library (Single Server)stratégie: Je viens de parler de la façon d'utiliser la fonction d'interface du modèle pour faire une mise à niveau de stratégie avec une fonction de transport des ordres. La question de savoir à qui envoyer est configurée par les paramètres deorder synchronous management system library (Single Server).

img

Vous pouvez voir cinq paramètres, qui peuvent supporter au maximum cinq poussées (si vous avez besoin d'augmenter le nombre de poussées, vous pouvez l'étendre par vous-même); la valeur par défaut des paramètres est une chaîne vide, à savoir non traitée.

  • étiquette L'étiquette du compte synchrone, utilisée pour étiqueter un compte; le nom de l'étiquette peut être défini au hasard.

  • robotId L'ID du bot; l'ID du bot duorder synchronous management system (Synchronous Server)créée par le propriétaire du compte synchrone.

  • accèsClé La clé d'accès de l'API étendue FMZ.

  • Clé secrète La clé secrète de l'API étendue FMZ.

Ensuite, nous pouvons effectuer un test simple.

Commande de la bibliothèque du système de gestion synchrone (serveur unique) opération de bot:

img

Le bot du système de gestion synchrone de commande (serveur synchrone) a reçu le signal: Ordre Système de gestion synchrone (serveur synchrone) maintenant n'a pas été entièrement conçu par nous, et nous pouvons utiliser un code simple pour le réaliser, sans commerce, seulement l'impression de signal:

Code temporaire du système de gestion synchrone de commande (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

Comme vous pouvez le voir, le bot du propriétaire du compte synchrone a reçu le message:ETH_USDT,swap,buy,1Je suis désolée. Ainsi, dans l'étape suivante, nous pouvons superviser les ordres automatiquement, selon la paire de négociation, le code du contrat, la direction de négociation et le volume.

Actuellement,order synchronous management system (Synchronous Server)est seulement un code temporaire, et nous pourrons en discuter plus en détail dans l'article suivant.


Plus de