[TOC] Je vous en prie.
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.
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
}
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)
}
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.
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:
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) + "`")
}
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:
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) + "`")
}
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
Lorsque le paramètre est passé auexchange.GetPositions()
La fonction est une chaîne vide
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ètresymbol
a des formats différents pour les contrats à terme/à terme pour l'objet d'échangeexchange
:
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.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 BTCvar 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
}
La demande d'un lot de données de marché pour un symbole spécifié est devenue beaucoup plus simple.
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"))
}
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) + "`")
}
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.
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:
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)
}
La fonction GetOrders ajoute égalementsymbol
Paramè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:
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) + "`")
}
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.
Lorsque leETH_USDT.swap
Si 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.
Quand une chaîne vide""
Les commandes en USDT ne sont pas acceptées, mais les commandes en USDT sont acceptées.
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()
.
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.com
sans 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")
}
Cette mise à niveau affecte principalement le paramètreid
de 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:
123456
Avant cette mise à niveau, si vous voulez appeler la fonction GetOrder, l'ordre Id passé est123456
.BTC-USDT
Je 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.
L'impact de cette mise à niveau sur lesexchange.CancelOrder()
fonction est la même que laexchange.GetOrder()
function.
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
.
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
.
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.
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.
Cette mise à jour ajoute un champ Symbole à la structure Position.exchange.GetTicker()
function.
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.
Les champs deAccount
structure renvoyée par leGetAccount
La 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 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)
}