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

Explication détaillée de la mise à niveau de l'API FMZ Quant: amélioration de l'expérience de conception de la stratégie

Auteur:FMZ~Lydia, Créé: 2024-07-05 09:44:08, Mis à jour: 2024-07-25 15:15:03

[TOC] Je vous en prie.

img

Explication détaillée de la mise à niveau de l'API FMZ Quant: amélioration de l'expérience de conception de la stratégie

Préface

Après 9 ans d'itération technique, la plateforme de trading quantitative FMZ a été reconstruite à plusieurs reprises, bien que les utilisateurs ne l'aient peut-être pas remarqué.

Afin de rendre la conception de la stratégie plus pratique, la logique de trading plus claire et plus facile pour les débutants, la plateforme a mis à jour l'interface API utilisée par la stratégie. Les dockers utilisant la dernière version peuvent activer ces nouvelles fonctionnalités. La plateforme est toujours compatible avec les anciens appels d'interface dans la plus grande mesure.

Guide de syntaxe:https://www.fmz.com/syntax-guideGuide de l' utilisateur:https://www.fmz.com/user-guide

Regardons donc rapidement quelles interfaces ont été mises à jour et quels changements sont nécessaires pour utiliser les anciennes stratégies pour les rendre compatibles avec l'API actuelle.

1. Une nouvelle interface API

Ajout d'échange. Fonction GetTickers

Pour concevoir des stratégies multi-produits et des stratégies complètes de surveillance du marché, l'interface de marché agrégée est essentielle.

Si l'échange n'a pas cette interface (échanges individuels), lors de l'appelexchange.GetTickers(), un message d'erreur s'affiche: Non pris en charge.

Cette fonction n'a pas de paramètres et renvoie les données de marché en temps réel de toutes les variétés dans l'interface de marché agrégée de la bourse.

exchange.GetTickers()fonction est la version de demande complète duexchange.GetTicker()fonction (regardez attentivement, la différence entre ces deux noms de fonction est juste le singulier et le pluriel).

Nous utilisons l'environnement de simulation OKX pour les tests:

function main() {
    exchange.IO("simulate", true)

    var tickers = exchange.GetTickers()
    if (!tickers) {
        throw "tickers error"
    }

    var tbl = {type: "table", title: "test tickers", cols: ["Symbol", "High", "Open", "Low", "Last", "Buy", "Sell", "Time", "Volume"], rows: []}
    for (var i in tickers) {
        var ticker = tickers[i]
        tbl.rows.push([ticker.Symbol, ticker.High, ticker.Open, ticker.Low, ticker.Last, ticker.Buy, ticker.Sell, ticker.Time, ticker.Volume])
    }

    LogStatus("`" + JSON.stringify(tbl) +  "`")
    return tickers.length
}

img

Ajout d'échange. Créer la fonction Ordre

Le nouveauexchange.CreateOrder()La plus grande fonction deexchange.CreateOrder()Il s'agit de spécifier directement le type et la direction de l'ordre dans les paramètres de la fonction, de sorte qu'il ne dépend plus de la paire de négociation, du code de contrat, de la direction de négociation et d'autres paramètres du système.

Dans les scénarios de placement d'ordres de négociation multi-espèces et les scénarios concomitants, la complexité de la conception est considérablement réduite.exchange.CreateOrder()fonction sontsymbol, side, price, amount.

Test en utilisant l'environnement de simulation des contrats à terme OKX:

function main() {
    exchange.IO("simulate", true)

    var id1 = exchange.CreateOrder("ETH_USDT.swap", "buy", 3300, 1)
    var id2 = exchange.CreateOrder("BTC_USDC.swap", "closebuy", 70000, 1)
    var id3 = exchange.CreateOrder("LTC_USDT.swap", "sell", 110, 1)

    Log("id1:", id1, ", id2:", id2, ", id3:", id3)
}

img

De cette façon, seulement troisexchange.CreateOrder()Les appels de fonction ont été utilisés pour placer trois ordres de contrats à terme de variétés et de directions différentes.

Ajout d'échange.GetHistoryOrders

Le nouveauexchange.GetHistoryOrders()La fonction est utilisée pour obtenir les ordres de transaction historiques d'une certaine variété.

Pour interroger les commandes historiques, les interfaces mises en œuvre par les différents échanges varient considérablement:

  • Certains prennent en charge les requêtes paginées, tandis que d'autres ne le font pas;
  • Certaines bourses ont une période de fenêtre de requête, c'est-à-dire que les ordres plus anciens que N jours ne peuvent pas être interrogés;
  • La plupart des échanges prennent en charge la requête à un moment précis, mais certains ne le font pas; Ces interfaces sont encapsulées avec le plus haut degré de compatibilité, et lors de leur utilisation effective, il convient de veiller à ce qu'elles répondent aux exigences et aux attentes de la stratégie.

La description détaillée de la fonction n'est pas répétée ici, vous pouvez consulter le manuel de syntaxe dans la documentation API:

https://www.fmz.com/syntax-guide#fun_exchange.gethistoryorders

Testé à l'aide de l'environnement de trading au comptant Binance:

function main() {
    var orders = exchange.GetHistoryOrders("ETH_USDT")

    // Write to chart
    var tbl = {type: "table", title: "test GetHistoryOrders", cols: ["Symbol", "Id", "Price", "Amount", "DealAmount", "AvgPrice", "Status", "Type", "Offset", "ContractType"], rows: []}
    for (var order of orders) {
        tbl.rows.push([order.Symbol, order.Id, order.Price, order.Amount, order.DealAmount, order.AvgPrice, order.Status, order.Type, order.Offset, order.ContractType])
    }
    
    LogStatus("orders.length:", orders.length, "\n", "`" + JSON.stringify(tbl) +  "`")
}

img

Ajout de la fonction GetPositions

L'ancienne version de la fonction d'acquisition des données de position estexchange.GetPosition()Cette mise à jour ajoute une nouvelle fonction d'acquisition de position pour mieux correspondre à la sémantique de nommage de la fonction:exchange.GetPositions(). En même temps, il est encore compatible/mis à niveau avec la fonction GetPosition.

Leexchange.GetPositions()La fonction a trois formes d'appel:

  • Je suis désolé. Lorsqu'aucun paramètre n'est passé, les données de position sont demandées sur la base des paramètres actuels de la paire de négociation/du code du contrat.
  • Les échanges de titres et de titres de titres sont effectués en utilisant les conditions suivantes: Lorsque vous spécifiez des informations spécifiques sur un produit (le format de l'ETH_USDT.swap est défini par la plateforme FMZ), demandez les données de position du produit spécifique.
  • Je suis en train d'échanger. Demandez à l'interface de position d'échange d'obtenir toutes les dimensions actuelles des données de position (divisées selon la dimension du produit de l'interface d'échange) Test en utilisant l'environnement de simulation des contrats à terme OKX:
function main() {
    exchange.IO("simulate", true)

    exchange.SetCurrency("BTC_USDT")
    exchange.SetContractType("swap")

    var p1 = exchange.GetPositions()
    var p2 = exchange.GetPositions("")

    var tbls = []
    for (var positions of [p1, p2]) {
        var tbl = {type: "table", title: "test GetPosition/GetPositions", cols: ["Symbol", "Amount", "Price", "FrozenAmount", "Type", "Profit", "Margin", "ContractType", "MarginLevel"], rows: []}
        for (var p of positions) {
            tbl.rows.push([p.Symbol, p.Amount, p.Price, p.FrozenAmount, p.Type, p.Profit, p.Margin, p.ContractType, p.MarginLevel])
        } 
        tbls.push(tbl)
    }

    LogStatus("`" + JSON.stringify(tbls) +  "`")
}

img

Lorsque le paramètre est passé auexchange.GetPositions()la fonction estETH_USDT.swap, les données de position des contrats perpétuels basés sur U de l'ETH peuvent être obtenues.

img

Lorsque le paramètre est passé auexchange.GetPositions()La fonction est une chaîne vide , les données de position de tous les contrats basés sur U peuvent être obtenus.

2. Mise à niveau de l'interface API

Mise à jour de la fonction GetTicker

La mise à niveau principale de la fonction de marchéexchange.GetTicker()Il permet à la fonction de demander des données de marché directement en fonction des informations sur le produit spécifiées par le paramètre sans la paire de négociation et le code du contrat en cours. Il simplifie le processus d'écriture du code. En même temps, il est toujours compatible avec la méthode d'appel sans passer de paramètres, et est compatible avec l'ancienne stratégie de plate-forme dans la plus grande mesure.

Le paramètresymbola des formats différents pour les contrats à terme/à terme pour l'objet d'échangeexchange:

  • Objet d'échange au comptant Le format est le suivant:AAA_BBB, AAA représente baseCurrency, c'est-à-dire monnaie de négociation, et BBB représente quoteCurrency, c'est-à-dire monnaie de fixation des prix. Par exemple: paire de négociation au comptant BTC_USDT.
  • Objet de change de contrats à terme Le format est le suivant:AAA_BBB.XXX, AAA représente baseCurrency, c'est-à-dire monnaie de négociation, BBB représente quoteCurrency, c'est-à-dire monnaie de tarification, et XXX représente le code du contrat, tel que le contrat perpétuel de swap. Par exemple: BTC_USDT.swap, contrat perpétuel basé sur U de BTC. Testé en utilisant l'environnement en direct Binance Futures:
var symbols = ["BTC_USDT.swap", "BTC_USDT.quarter", "BTC_USD.swap", "BTC_USD.next_quarter", "ETH_USDT.swap"]

function main() {
    exchange.SetCurrency("ETH_USD")
    exchange.SetContractType("swap")

    var arr = []
    var t = exchange.GetTicker()
    arr.push(t)

    for (var symbol of symbols) {
        var ticker = exchange.GetTicker(symbol)
        arr.push(ticker)
    }

    var tbl = {type: "table", title: "test GetTicker", cols: ["Symbol", "High", "Open", "Low", "Last", "Buy", "Sell", "Time", "Volume"], rows: []}
    for (var ticker of arr) {
        tbl.rows.push([ticker.Symbol, ticker.High, ticker.Open, ticker.Low, ticker.Last, ticker.Buy, ticker.Sell, ticker.Time, ticker.Volume])
    }

    LogStatus("`" + JSON.stringify(tbl) +  "`")
    return arr
}

img

La demande d'un lot de données de marché pour un symbole spécifié est devenue beaucoup plus simple.

Mettre à jour l'échange.Fonction GetDepth

Comme pour la fonction GetTicker, leexchange.GetDepth()Cette fonction ajoute également un paramètre de symbole. Cela nous permet de spécifier directement le symbole lors de la demande de données de profondeur.

Testé en utilisant l'environnement Binance Futures en direct:

function main() {
    exchange.SetCurrency("LTC_USD")
    exchange.SetContractType("swap")

    Log(exchange.GetDepth())
    Log(exchange.GetDepth("ETH_USDT.quarter"))
    Log(exchange.GetDepth("BTC_USD.swap"))
}

img

Mettre à jour la fonction Exchange.GetTrades

Comme pour la fonction GetTicker, leexchange.GetTrades()Cette fonction ajoute également un paramètre de symbole, ce qui nous permet de spécifier le symbole directement lors de la demande de données de transaction de marché.

Testé en utilisant l'environnement Binance Futures en direct:

function main() {
    var arr = []
    var arrR = []
    var symbols = ["LTC_USDT.swap", "ETH_USDT.quarter", "BTC_USD.swap"]    

    for (var symbol of symbols) {
        var r = exchange.Go("GetTrades", symbol)
        arrR.push(r)
    }

    for (var r of arrR) {
        arr.push(r.wait())
    }
    
    var tbls = []
    for (var i = 0; i < arr.length; i++) {
        var trades = arr[i]
        var symbol = symbols[i]

        var tbl = {type: "table", title: symbol, cols: ["Time", "Amount", "Price", "Type", "Id"], rows: []}
        for (var trade of trades) {
            tbl.rows.push([trade.Time, trade.Amount, trade.Price, trade.Type, trade.Id])
        }

        tbls.push(tbl)
    }

    LogStatus("`" + JSON.stringify(tbls) +  "`")
}

img

Cette mise à niveau est également compatible avec le paramètre de symbole spécifié par leexchange.Go()fonctionner lors de l'appel simultané de l'interface API de la plateforme.

Mise à jour de la fonction Exchange.GetRecords

La fonction GetRecords a été considérablement ajustée cette fois-ci. En plus de prendre en charge le paramètre symbole pour spécifier directement les informations de type des données de ligne K demandées, le paramètre de période d'origine est conservé pour spécifier la période de ligne K et un paramètre limite est ajouté pour spécifier la longueur de ligne K attendue lors de la demande. En même temps, il est également compatible avec l'ancienne version de la fonction GetRecords qui ne passe que dans le paramètre de période.

La méthode d'appel deexchange.GetRecords()la fonction est:

  • Je suis en train d' échange.GetRecords Si aucun paramètre n'est spécifié, les données de la ligne K du produit correspondant au code de la paire de négociation/du contrat en cours sont demandées.
  • Je suis en train d' écrire un article. Lorsque seul le paramètre de la période de la ligne K est spécifié, les données de la ligne K du produit correspondant à la paire de négociation/code du contrat en cours sont demandées.
  • Je suis désolé, mais je ne peux pas vous aider. Lorsque seules les informations sur le produit sont spécifiées, les données de la ligne K du produit spécifié sont demandées.
  • Les résultats de l'enquête sont les suivants: Indiquer les informations relatives au produit et la période spécifique de ligne K pour demander des données de ligne K.
  • Je suis désolé, mais je n'ai pas le choix. Spécifier les informations sur le produit, la période spécifique de ligne K et la longueur de ligne K attendue pour demander des données de ligne K. Notez que lorsque le paramètre limite dépasse la longueur maximale d'une seule demande de l'échange, une demande de page sera générée (c'est-à-dire plusieurs appels à l'interface de ligne K de l'échange).

Testé en utilisant l'environnement Binance Futures en direct:

function main() {
    exchange.SetCurrency("ETH_USDT")
    exchange.SetContractType("swap")
    
    var r1 = exchange.GetRecords()
    var r2 = exchange.GetRecords(60 * 60)
    var r3 = exchange.GetRecords("BTC_USDT.swap")
    var r4 = exchange.GetRecords("BTC_USDT.swap", 60)
    var r5 = exchange.GetRecords("LTC_USDT.swap", 60, 3000)

    Log("r1 time difference between adjacent bars:", r1[1].Time - r1[0].Time, "Milliseconds, Bar length:", r1.length)
    Log("r2 time difference between adjacent bars:", r2[1].Time - r2[0].Time, "Milliseconds, Bar length:", r2.length)
    Log("r3 time difference between adjacent bars:", r3[1].Time - r3[0].Time, "Milliseconds, Bar length:", r3.length)
    Log("r4 time difference between adjacent bars:", r4[1].Time - r4[0].Time, "Milliseconds, Bar length:", r4.length)
    Log("r5 time difference between adjacent bars:", r5[1].Time - r5[0].Time, "Milliseconds, Bar length:", r5.length)
}

img

Mettre à jour la fonction Exchange.GetOrders

La fonction GetOrders ajoute égalementsymbolParamètres, qui peuvent spécifier le type des ordres en cours non terminés (ordres en attente) directement à interroger; il prend également en charge la requête de tous les ordres en attente (quel que soit le type); et est compatible avec la méthode d'appel originale.

Leexchange.GetOrders()La fonction peut être appelée de la manière suivante:

  • Je suis en train d' échanger des ordres. La valeur de la transaction est la valeur de la transaction en cours, qui est la valeur de la transaction en cours.
  • Je suis désolé, mais je n'ai pas le choix. Consultez toutes les commandes en cours pour les contrats perpétuels sur BTC avec marge USDT.
  • Je suis en train de faire un échange. Recherche de toutes les commandes inachevées dans la dimension actuelle de l'échange (divisée selon la dimension de l'interface API de l'échange).

Test en utilisant l'environnement de simulation des contrats à terme OKX:

function main() {
    exchange.IO("simulate", true)

    exchange.SetCurrency("BTC_USDT")
    exchange.SetContractType("swap")

    // Write to chart
    var tbls = []
    for (var symbol of ["null", "ETH_USDT.swap", ""]) {
        var tbl = {type: "table", title: symbol, cols: ["Symbol", "Id", "Price", "Amount", "DealAmount", "AvgPrice", "Status", "Type", "Offset", "ContractType"], rows: []}

        var orders = null
        if (symbol == "null") {
            orders = exchange.GetOrders()
        } else {
            orders = exchange.GetOrders(symbol)
        }

        for (var order of orders) {
            tbl.rows.push([order.Symbol, order.Id, order.Price, order.Amount, order.DealAmount, order.AvgPrice, order.Status, order.Type, order.Offset, order.ContractType])
        }

        tbls.push(tbl)
    }
    
    LogStatus("`" + JSON.stringify(tbls) +  "`")
}

img

Lorsqu'aucun paramètre n'est passé, la demande par défaut est pour tous les ordres en attente non terminés de la paire de trading BTC/USDT en cours et du contrat perpétuel de swap.

img

Lorsque leETH_USDT.swapSi le paramètre est spécifié, tous les ordres en attente du contrat perpétuel de la paire de négociation ETH_USDT sont demandés.

img

Quand une chaîne vide""Les commandes en USDT ne sont pas acceptées, mais les commandes en USDT sont acceptées.

Mise à jour de la fonction Exchange.GetPosition

Il est toujours compatible avec l'ancienne fonction d'acquisition de position nommée et ajoute également le paramètre symbole, qui peut spécifier les informations de type des données de position spécifiques demandées. L'utilisation de cette fonction est exactement la même queexchange.GetPositions().

Mise à jourexchange.IOfonction

Pourexchange.IO("api", ...)les appels de fonction, tous les objets d'échange ont été mis à niveau pour prendre en charge le passage direct des adresses de requête complètes. Par exemple, si vous voulez appeler l'interface OKX:

// GEThttps://www.okx.com/api/v5/compte/max-retrait ccy: BTC

Prend en charge l'écriture directe à l'adresse de basehttps://www.okx.comsans avoir à changer d'abord l'adresse de base et ensuite appeler la fonction IO.

Test en utilisant l'environnement de simulation des contrats à terme OKX:

function main() {
    exchange.IO("simulate", true)

    return exchange.IO("api", "GET", "https://www.okx.com/api/v5/account/max-withdrawal", "ccy=BTC")
}

img

3. Impact de l'interface de l'API

Affecte la fonction Exchange.GetOrder

Cette mise à niveau affecte principalement le paramètreidde l'annéeexchange.GetOrder(id)Le paramètre id est modifié de l'id d'ordre d'échange d'origine à un format de chaîne contenant le produit de négociation. Tous les identifiants de commande encapsulés sur la plateforme FMZ sont dans ce format.

Par exemple:

  • L'identifiant d'ordre initial de l'échange défini dans l'ordre d'échange est:123456Avant cette mise à niveau, si vous voulez appeler la fonction GetOrder, l'ordre Id passé est123456.
  • Le code du produit nommé par la bourse défini dans l'ordre de change:BTC-USDTJe suis désolée. Notez que cela fait référence au code de produit de négociation nommé par la bourse, et non à la paire de négociation définie par la plateforme FMZ.

Après cette mise à niveau, le format de l'identifiant de paramètre qui doit être passé dans leexchange.GetOrder(id)la fonction est réglée sur:BTC-USDT,123456.

Tout d'abord, laissez-moi vous expliquer pourquoi cette conception est faite: Parce que la fonction CreateOrder a été améliorée pour spécifier directement le type d'ordre (le type d'ordre placé peut être différent de la paire de trading et du code de contrat actuellement définis). Si l'ID d'ordre retourné ne contient pas les informations de type, alors cet ID d'ordre sera inutilisable. Parce que lors de la vérification de l'ordre, nous ne savons pas à quel type (contrat) l'ordre est destiné. La plupart des bourses nécessitent la spécification de paramètres décrivant le code de type lors de la vérification et de l'annulation des ordres.

Comment être compatible avec cet impact: Si vous utilisezexchange.IOLa valeur retournée contient généralement le symbole d'origine de l'échange (code de produit) et l'identifiant d'ordre d'origine. De même, si vous utilisez l'interface de commande encapsulée de la plateforme FMZ pour passer une commande, puisque le début de l'identifiant de commande est le code du produit de trading, si vous devez utiliser l'identifiant de commande d'origine, supprimez simplement le code du produit et la virgule.

Affecte l' échange.Annuler la commande

L'impact de cette mise à niveau sur lesexchange.CancelOrder()fonction est la même que laexchange.GetOrder() function.

Affecte la fonction d'échange.

L'impact de cette mise à niveau sur lesexchange.Buy()fonction est la même que laexchange.GetOrder()fonction. L'identifiant de commande renvoyé par leexchange.Buy()la fonction est une nouvelle structure, par exemple, l'ID renvoyé lors de la passation d'un ordre à terme sur la bourse OKX est:LTC-USDT-SWAP,1578360858053058560.

Affecte l' échange. Fonction de vente

L'impact de cette mise à niveau sur lesexchange.Sell()fonction est la même que laexchange.GetOrder()fonction. L'identifiant de commande renvoyé par leexchange.Sell()la fonction est une nouvelle structure, par exemple, l'ID renvoyé lors de la passation d'un ordre à terme sur la bourse OKX est:ETH-USDT-SWAP,1578360832820125696.

4. Adaptation structurelle

Structure du ticker

Cette mise à jour ajoute un champ Symbole à la structure du Ticker, qui enregistre les informations de marché de la structure actuelle du Ticker. Le format de ce champ est exactement le même que le format du paramètre de symbole duexchange.GetTicker() function.

Structure de l'ordre

Cette mise à jour ajoute un champ Symbole à la structure de l'Ordre, et le format de ce champ est exactement le même que le format du paramètre symbole duexchange.GetTicker()fonction. Cette mise à jour modifie également le champ ID de la structure de commande, enregistrant les informations sur le produit et les informations de commande originales dans le nouveau format d'identification de commande.exchange.GetOrder()Je ne vais pas vous le répéter.

Structure de la position

Cette mise à jour ajoute un champ Symbole à la structure Position.exchange.GetTicker() function.

5. Système de test de retour

Pour répondre aux besoins des utilisateurs, cette mise à niveau sera d'abord compatible avec le trading en direct, et le système de backtesting sera adapté dans une semaine.

Mise à jour complémentaire

1. Nouveaux champs en équité et en UPnL dans la structure des comptes

Les champs deAccountstructure renvoyée par leGetAccountLa fonction de membre de l'objet d'échange de contrats à terme a été élargie.

  • Titres propres Le taux de change de l'actif de marge actuel est le taux de change de l'actif de marge actuel.

  • L'UPNL Le profit et la perte non réalisés de toutes les positions détenues dans la monnaie de l'actif de marge actuel.

La fonction SetMarginLevel a été améliorée pour prendre en charge le paramètre symbole

La fonction membre SetMarginLevel de l'objet d'échange de contrats à terme a été améliorée et le symbole paramétrique a été ajouté.

Exemple de test:

function main() {
    exchange.SetCurrency("ETH_USDT")
    exchange.SetContractType("swap")
    
    // The current trading pair is ETH_USDT, the contract code is swap, and the leverage value is set to 10
    exchange.SetMarginLevel(10)
    
    // Directly specify the trading pair BTC_USDT, contract code swap, and set the leverage value to 20
    exchange.SetMarginLevel("BTC_USDT.swap", 20)
}

Plus de