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

Auteur:Le petit rêve, Créé: 2022-02-14 19:46:30, Mis à jour: 2023-09-15 20:44:11

img

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

Dans les articles précédents de la bibliothèque FMZ, nous avons conçu plusieurs stratégies de synchronisation des commandes et des stocks.

Nous avons essayé une conception un peu différente, basée sur la puissante extension de l'API de la plate-forme de négociation quantitative FMZ, nous avons conçu un système de gestion de la synchronisation des commandes.

Des idées de conception

Tout d'abord, nous avons besoin de bonnes suggestions, de bonnes exigences.

  • 1, les implémentateurs de la stratégie de synchronisation en direct doivent disposer de la clé API de l'échange de l'account de référence. Le problème pour les scénarios d'utilisation est le suivant: il n'y a pas de problème pour les autres comptes de l'échange de suivre un compte de l'échange; mais il peut être gênant pour les scénarios de référence et de synchronisation où il n'y a pas de propriétaire. Les propriétaires de comptes synchronisés sont parfois réticents à fournir la clé API de leur compte d'échange pour des raisons de sécurité.

    La solution: En utilisant l'API étendue de FMZ, les propriétaires de comptes synchronisés (les abonnés) doivent simplement s'inscrire à la plateforme de trading quantitative FMZ et exécuter une stratégie (dans le système conçu pour cet article):订单同步管理系统(Synchronous Server)Vous pouvez ensuite fournir l'ID du disque dur de l'extension API KEY de FMZ (attention, pas l'API KEY d'un compte d'échange) et du système de gestion des ordres synchrones (Synchronous Server) au propriétaire du compte de référence (Band). Lorsque le disque virtuel du titulaire de compte (le bandeau) est utilisé dans le système conçu pour ce document订单同步管理系统类库(Single Server)Une fois que vous avez envoyé un signal, le disque virtuel du titulaire du compte en synchronisation reçoit un signal de transaction, qui est ensuite automatiquement supprimé.

  • 2, beaucoup de développeurs ont des stratégies de comparaison et ne peuvent pas utiliser les deux ordres à terme décrits ci-dessus, les stratégies de synchronisation de stock; parce que cela nécessite de fusionner leurs stratégies avec ces stratégies de synchronisation, qui peuvent nécessiter des modifications importantes et fastidieuses. La solution: Vous pouvez concevoir une bibliothèque de modèles synchronisés sur commande (dans le système conçu pour cet article)订单同步管理系统类库(Single Server)Les utilisateurs de l'outil peuvent utiliser des stratégies de synchronisation de commande ou de stockage en intégrant directement cette bibliothèque de modèles dans leur propre stratégie.

  • 3° réduire un disque supplémentaire. Le dernier inconvénient est que si vous utilisez les deux ordres à terme décrits ci-dessus, la stratégie de synchronisation des dépôts. La solution: Utilisez une bibliothèque de modèles pour intégrer des fonctionnalités dans la politique de compte de référence.

Le système est donc composé de deux parties: 1, la bibliothèque des systèmes de gestion de la synchronisation des commandes (Single Server) 2, Système de gestion des commandes synchrones

Une fois que vous avez une idée claire de ce que vous voulez, vous pouvez commencer à concevoir.

Conception 1: bibliothèque de classes de systèmes de gestion de synchronisation des commandes (Single Server)

Notez que ce n'est pas une stratégie; c'est une bibliothèque de modèles FMZ, et le concept de bibliothèque de modèles peut être recherché dans la documentation de l'API FMZ.

Le code de la bibliothèque de modèles:

// 全局变量
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) {
        // 开仓
        var tradeDirection = type == PD_LONG ? "buy" : "sell"
        // 发送信号
        msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)        
    } else if (delta < 0) {
        // 平仓
        var tradeDirection = type == PD_LONG ? "closebuy" : "closesell"
        if (nowAmount <= 0) {
            Log("未检测到持仓")
            return 
        }
        // 发送信号
        msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)
    } else {
        throw "错误"
    }
    if (msg) {
        _.each(fmzExtendApis, function(extendApiConfig) {
            var ret = sendCommandRobotMsg(extendApiConfig[keyName_robotId], extendApiConfig[keyName_extendAccessKey], extendApiConfig[keyName_extendSecretKey], msg)
            Log("调用CommandRobot接口,", "label:", extendApiConfig[keyName_label], ", msg:", msg, ", ret:", ret)
            Sleep(1000)
        })
    }
}

$.PosMonitor = function(exIndex, symbol, ct) {    
    var ts = new Date().getTime()
    var ex = exchanges[exIndex]
    // 判断ex类型
    var exName = ex.GetName()
    var isFutures = exName.includes("Futures_")
    var exType = isFutures ? "futures" : "spot"
    if (!isFutures) {
        throw "仅支持期货跟单"
    }

    if (exType == "futures") {
        // 缓存 symbol ct
        var buffSymbol = ex.GetCurrency()
        var buffCt = ex.GetContractType()

        // 切换到对应的交易对、合约代码
        ex.SetCurrency(symbol)
        if (!ex.SetContractType(ct)) {
            throw "SetContractType failed"
        }

        // 监控持仓
        var keyInitRefPosAmount = "refPos-" + exIndex + "-" + symbol + "-" + ct    // refPos-exIndex-symbol-contractType
        var initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
        if (!initRefPosAmount) {
            // 没有初始化数据,初始化          
            mapInitRefPosAmount[keyInitRefPosAmount] = getPosAmount(_C(ex.GetPosition), ct)
            initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
        }

        // 监控
        var nowRefPosAmount = getPosAmount(_C(ex.GetPosition), ct)
        // 计算仓位变动
        var longPosDelta = nowRefPosAmount.long - initRefPosAmount.long
        var shortPosDelta = nowRefPosAmount.short - initRefPosAmount.short

        // 检测变动
        if (!(longPosDelta == 0 && shortPosDelta == 0)) {
            // 执行多头动作
            if (longPosDelta != 0) {
                Log(ex.GetName(), ex.GetLabel(), symbol, ct, "执行多头跟单,变动量:", longPosDelta)
                follow(nowRefPosAmount, symbol, ct, PD_LONG, longPosDelta)
            }
            // 执行空头动作
            if (shortPosDelta != 0) {
                Log(ex.GetName(), ex.GetLabel(), symbol, ct, "执行空头跟单,变动量:", shortPosDelta)
                follow(nowRefPosAmount, symbol, ct, PD_SHORT, shortPosDelta)
            }

            // 执行跟单操作后,更新
            mapInitRefPosAmount[keyInitRefPosAmount] = nowRefPosAmount
        }

        // 恢复 symbol ct
        ex.SetCurrency(buffSymbol)
        ex.SetContractType(buffCt)
    } else if (exType == "spot") {
        // 现货
    }
}

$.getTbl = function() {
    var tbl = {
        "type" : "table", 
        "title" : "同步数据", 
        "cols" : [], 
        "rows" : []
    }
    // 构造表头
    tbl.cols.push("监控账户:refPos-exIndex-symbol-contractType")
    tbl.cols.push(`监控持仓:{"时间戳":xxx,"多头持仓量":xxx,"空头持仓量":xxx}`)
    _.each(fmzExtendApis, function(extendApiData, index) {
        tbl.cols.push(keyName_robotId + "-" + index)
    })
    
    // 写入数据
    _.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
}

// 引用该模板类库的策略调用范例
function main() {
    // 清除所有日志
    LogReset(1)

    // 切换到OKEX 模拟盘测试
    exchanges[0].IO("simulate", true)

    // 设置合约
    exchanges[0].SetCurrency("ETH_USDT")
    exchanges[0].SetContractType("swap")

    // 定时交易时间间隔
    var tradeInterval = 1000 * 60 * 3        // 三分钟交易一次,用于观察跟单信号
    var lastTradeTS = new Date().getTime()
    
    while (true) {
        // 策略其它逻辑...

        // 用于测试的模拟交易触发
        var ts = new Date().getTime()
        if (ts - lastTradeTS > tradeInterval) {
            Log("模拟带单策略发生交易,持仓变化", "#FF0000")
            exchanges[0].SetDirection("buy")
            exchanges[0].Buy(-1, 1)
            lastTradeTS = ts
        }

        // 使用模板的接口函数
        $.PosMonitor(0, "ETH_USDT", "swap")    // 可以设置多个监控,监控带单策略上的不同的exchange对象  
        var tbl = $.getTbl()
        
        // 显示状态栏
        LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
        Sleep(1000)
    }
}

Cette bibliothèque est très simple de conception et comporte deux fonctions.订单同步管理系统类库(Single Server)Après la bibliothèque de classes de modèles. Cette stratégie peut être utilisée avec la fonction suivante.

  • Je ne peux pas vous aider. Le rôle de cette fonction est de surveiller les changements de position d'un objet d'échange dans la stratégie, puis d'envoyer des signaux de transaction au disque réel, définis dans les paramètres de la bibliothèque du système de gestion synchrone d'ordres (Single Server).

  • Je suis désolée. Les données synchronisées de la surveillance sont renvoyées.

Un exemple d'utilisation est le modèle de la bibliothèque de systèmes de gestion de synchronisation de commandes (Single Server).mainDans la fonction:

// 引用该模板类库的策略调用范例
function main() {
    // 清除所有日志
    LogReset(1)

    // 切换到OKEX 模拟盘测试
    exchanges[0].IO("simulate", true)

    // 设置合约
    exchanges[0].SetCurrency("ETH_USDT")
    exchanges[0].SetContractType("swap")

    // 定时交易时间间隔
    var tradeInterval = 1000 * 60 * 3        // 三分钟交易一次,用于观察跟单信号
    var lastTradeTS = new Date().getTime()
    
    while (true) {
        // 策略其它逻辑...

        // 用于测试的模拟交易触发
        var ts = new Date().getTime()
        if (ts - lastTradeTS > tradeInterval) {
            Log("模拟带单策略发生交易,持仓变化", "#FF0000")
            exchanges[0].SetDirection("buy")
            exchanges[0].Buy(-1, 1)
            lastTradeTS = ts
        }

        // 使用模板的接口函数
        $.PosMonitor(0, "ETH_USDT", "swap")    // 可以设置多个监控,监控带单策略上的不同的exchange对象  
        var tbl = $.getTbl()
        
        // 显示状态栏
        LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
        Sleep(1000)
    }
}

Une bibliothèque de modèles elle-même peut également créer des disques de stratégie, généralement utilisés pour tester la bibliothèque de modèles.mainUne fonction est votre propre stratégie.mainLes fonctions.

Le code de test a été écrit pour tester l'analogue OKEX, il est nécessaire de configurer l'API KEY de l'analogue OKEX sur FMZ comme compte de référence (bande), de commencer à passer à l'analogue dans la fonction principale. Ensuite, la paire de transactions est définie comme ETH_USDT, le contrat est définie comme permanent (swap). Puis entrez dans un cycle while.$.PosMonitor(0, "ETH_USDT", "swap")Le premier paramètre de cette fonction, appelé, est passé à 0, ce qui signifie que l'objet de l'échange, qui surveille la paire de transactions ETH_USDT, est un contrat de swap.$.getTbl()Obtenir des informations sur les graphiques et les utiliserLogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")Pour que les données du graphique s'affichent sur la barre d'état.

Donc, vous voyez, si vous utilisez une stratégie qui fait référence à ce modèle,$.PosMonitor(0, "ETH_USDT", "swap")Il est possible de faire en sorte que la stratégie ait la fonction de surveiller la position d'une variété, de modifier la position et de pousser le message.

Expliquez-moi avant le test.订单同步管理系统类库(Single Server)Les paramètres de conception de la stratégie: Nous venons de parler de la façon d'utiliser les fonctions d'interface du modèle pour mettre à niveau une stratégie avec une fonction de bandeau. La question de savoir à qui l'envoyer est posée par订单同步管理系统类库(Single Server)Les paramètres sont configurés comme suit:

img

Vous pouvez voir qu'il y a 5 paramètres, avec un maximum de 5 poussées (à ajouter, vous pouvez l'étendre vous-même), les paramètres par défaut sont des chaînes vides, c'est-à-dire ne pas traiter.

  • étiquette Une balise de synchronisation est une balise utilisée pour marquer un compte, dont le nom peut être configuré comme bon lui semble.

  • Nom de robot ID de disque virtuel créé par le propriétaire du compte de synchronisation订单同步管理系统(Synchronous Server)L'ID du disque réel.

  • Le code d'accès AccessKey pour l'API étendue de FMZ

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

Nous pouvons ensuite effectuer un test simple.

La bibliothèque de classes du système de gestion de la synchronisation des commandes (Single Server) fonctionne sur le disque:

img

Le disque dur du système de gestion des commandes (Synchronous Server) reçoit un signal: Le système de gestion des commandes synchrones (Synchronous Server) n'a pas encore été conçu, mais nous l'avons réalisé avec un code simple, sans transaction, en imprimant simplement le signal:

Le code temporaire du système de gestion de la synchronisation des commandes (Synchronous Server):

function main() {
    LogReset(1)
    while (true) {
        var cmd = GetCommand()
        if (cmd) {
            // cmd: ETH_USDT,swap,buy,1
            Log("cmd: ", cmd)
        }
        Sleep(1000)
    }
}

img

Vous pouvez voir que le disque virtuel du propriétaire du compte synchronisé reçoit le message suivant:ETH_USDT,swap,buy,1Je ne sais pas. Il est donc possible d'effectuer son propre suivi automatique en fonction de la paire de transactions, du code de contrat, de la direction et du nombre de transactions contenues dans l'information.

Actuellement订单同步管理系统(Synchronous Server)C'est juste un code temporaire, nous continuerons à explorer sa conception dans le prochain numéro.


Relationnée

Plus de

le groupe Mingxi1005Pour réaliser le suivi, vous avez besoin de deux disques, un disque classe et un disque système de gestion des commandes.

le groupe Mingxi1005Fait selon le tutoriel, affiche une erreur de configuration

Je suis désolée.Quels paramètres doivent être modifiés dans la liste inverse?

Je suis désolée.Si vous avez deux disques réels, l'un émet un signal et l'autre reçoit un signal, les deux disques réels peuvent-ils être combinés?

Le petit rêveVous ne comprenez peut-être pas l'article, cette bibliothèque de classes est un outil qui peut être intégré directement dans la ligne de stratégie de l'utilisateur, puis cette stratégie a une fonction de bande, elle envoie des messages à des comptes de compte bien configurés, et le robot reçoit des messages de liste. C'est tout simplement ce qui se passe.

Le petit rêveVous pouvez consulter l'article, les informations de configuration: étiquette, ID de disque réel, clé d'accès, clé secrète.

le groupe Mingxi1005L'erreur configs error! est une erreur de remplissage du disque de l'acheteur et des 2 KEY dans la bibliothèque du système de gestion de la synchronisation des commandes (Single Server), puis une erreur de référence de la bibliothèque du système de gestion de la synchronisation des commandes (Single Server) est signalée.

le groupe Mingxi1005Une erreur de configuration!

Le petit rêveIl y a aussi des informations erronées sur les réseaux sociaux et les réseaux sociaux.

Le petit rêveIl faut changer de stratégie.

Le petit rêveLe code est ouvert, vous pouvez le modifier en fonction de vos besoins et cela peut être fait.