[TOC]
Il s’agit du troisième article sur la pratique quantitative des échanges DEX. Cette fois, nous allons présenter le guide d’utilisation du protocole Vertex.
Dans le cadre des échanges décentralisés traditionnels (DEX), les traders quantitatifs doivent souvent faire des compromis : soit accepter le glissement élevé et la faible efficacité d’exécution du modèle de teneur de marché automatisé (AMM), soit tomber dans le dilemme technique de la fragmentation de la liquidité inter-chaînes et des fonctions dérivées uniques. L’émergence du protocole Vertex redéfinit les limites de la chaîne des stratégies quantitatives à travers une expérience de fusion « décentralisée + niveau institutionnel » - il n’y a pas ici de dilemme « choisir l’un des deux », seulement l’équilibre ultime entre vitesse, profondeur et liberté.
En tant que premier DEX à intégrer un pool de liquidité multi-chaînes unifié, un carnet d’ordres hybride (CLOB) et un marché des devises intégré, Vertex prend « l’expérience centralisée, l’âme décentralisée » comme cœur et ouvre une voie unique pour les traders quantitatifs :
Une nouvelle définition de la vitesse et de la fluidité
Avec l’évolution continue de la technologie blockchain, la frontière entre les échanges centralisés traditionnels (CEX) et les échanges décentralisés (DEX) s’estompe progressivement. En tant que plaque tournante de la plateforme Vertex, Vertex Edge remodèle non seulement la vitesse et la liquidité des transactions, mais combine également parfaitement une excellente technologie de correspondance des commandes et des avantages d’auto-conservation grâce à l’intégration inter-chaînes, apportant une nouvelle expérience DeFi aux traders mondiaux.
Unifier la liquidité inter-chaînes : briser la fragmentation de la liquidité Sur les marchés traditionnels, la liquidité entre les différentes chaînes est souvent fragmentée, ce qui empêche les traders de bénéficier des meilleurs prix et de la meilleure profondeur de transaction. Vertex Edge est né dans ce contexte, réalisant le partage synchrone de liquidités permanentes sur plusieurs chaînes via un réseau de carnet d’ordres unifié. Actuellement, Vertex Edge couvre la liquidité des contrats perpétuels sur 7 chaînes principales, dont Arbitrum, Base, Sei, Blast, Mantle, Sonic et Abstract, de sorte que les traders n’ont plus à s’inquiéter de la dispersion de la liquidité et peuvent négocier au meilleur prix, réalisant véritablement une connexion transparente de la liquidité mondiale.
Trading hybride sur carnet d’ordres : l’équilibre parfait entre mise en correspondance ultra-rapide et règlement en chaîne Vertex Edge adopte un modèle de négociation de carnet d’ordres hybride et ses technologies de base incluent :
Correspondance du carnet d’ordres hors chaîne : utilise un mécanisme de correspondance hors chaîne ultra-rapide pour obtenir une correspondance des ordres avec une latence de seulement 5 à 15 millisecondes, comparable à la plupart des échanges centralisés ; Moteur de risque en chaîne et AMM : des systèmes de gestion des risques et des teneurs de marché automatisés (AMM) sont déployés sur chaque chaîne prise en charge pour garantir que les ordres peuvent être réglés de manière sécurisée et transparente après la mise en correspondance. Cette architecture garantit non seulement une réponse extrêmement rapide aux transactions, mais offre également aux utilisateurs une sécurité décentralisée grâce au règlement en chaîne, permettant aux traders de profiter de performances de niveau CEX tout en maintenant l’indépendance de l’auto-conservation des actifs.
Fonction multi-comptes : gérez plusieurs comptes dans un seul portefeuille et allouez les fonds plus efficacement ; Positions spot à effet de levier : utiliser tous les actifs comme marge pour obtenir une meilleure efficacité du capital ; Gestion flexible des risques : les dépôts, les positions et les données de profits et pertes sont pris en compte de manière unifiée pour contrôler avec précision l’exposition au risque.
Adresse de la page de connexion « Vertex Protocol » :
Vertex est identique à la plupart des DEX. Après vous être connecté à la dapp, vous devez vous connecter au portefeuille pour obtenir une autorisation. Le système de sous-comptes de Vertex se distingue par une étiquette. L’étiquette participe au calcul de l’adresse du portefeuille pour obtenir une adresse de portefeuille de sous-compte. En même temps, cette adresse est autorisée à passer des commandes et d’autres opérations.
Par exemple, utilisezWalletConnectL’adresse du portefeuille lors de la connexion est :0x7a5ec2748e9065794491a8d29dcf3f9edb8d7c43
, l’étiquette par défaut est « par défaut » et l’adresse du sous-compte calculée est :0x7a5ec2748e9065794491a8d29dcf3f9edb8d7c4364656661756c740000000000
. Les balises par défaut sont :64656661756c740000000000
。
Vertex prend en charge la recharge de plusieurs actifs. En général, vous choisissez de recharger l’USDC en tant que marge et d’utiliser directement le portefeuille connecté pour transférer les transactions. Il convient de noter que les opérations telles que le retrait, le transfert, l’envoi de jetons et le transfert de sous-comptes sur Vertex consommeront de l’USDC et que les frais ne sont pas bas, ces opérations doivent donc être appelées avec prudence.
Passer à une autre chaîne :
Sur le vertex, les différentes chaînes ont des informations de configuration différentes telles que les nœuds, les indexeurs et les identifiants de chaîne. La chaîne par défaut pour l’encapsulation FMZ estArbitrum One
Elle est disponible.Log(HttpQuery("https://gateway.prod.vertexprotocol.com/v1/query?type=contracts"))
Interroger l’ID d’une chaîne, les informations sur le contrat déployé, etc.
Après vous être connecté à FMZ.COM, sur la page de configuration de l’échange, sélectionnez « Crypto-monnaie », sélectionnez Vertex Exchange, vous pouvez configurer directement la clé proxy du portefeuille sur le dapp. Bien entendu, vous pouvez également configurer la clé privée du portefeuille. Sur Vertex, vous pouvez utiliser l’interface pour gérer l’autorisation/la désautorisation de la clé proxy et d’autres opérations, ce qui est également plus pratique.
Clé proxy :
Par exemple, sur la page d’accueil de l’échange DEX vertex : navigateur Chrome (activer le débogage) -> Application -> Stockage local -> https://app.vertex -> vertex userSettings
Configurer Vertex Exchange
Deux éléments doivent être configurés sur FMZ. Le premier est l’adresse du portefeuille (pas l’adresse de la clé proxy utilisée pour la signature, il doit s’agir de l’adresse du portefeuille connecté à la dapp). La deuxième est la clé secrète utilisée pour la signature (elle peut être une clé privée de portefeuille ou une clé proxy). Étant donné que des clés proxy peuvent être utilisées, l’adresse et la clé du portefeuille configurées ne constituent pas nécessairement une paire.
Le système de sous-comptes de Vertex est identifié par des balises. La balise par défaut utilisée sur FMZ estdefault
Le compte principal de la balise, si vous avez besoin de changer, vous pouvez l’utiliser dans le code :
exchange.IO("subAccountTag", "default") // 切换到主子账号
exchange.IO("subAccountTag", "test01") // 切换到标签名为 test01 的子账号
Après avoir configuré les informations de configuration d’échange et déployé un programme de garde pouvant accéder à l’interface de vertex, nous pouvons commencer à écrire du code pour les opérations pratiques.
Nous utilisons le sous-compte principal pour les tests (le sous-compte avec la balise : default), et nous utilisonsArbitrumréseau.
function main() {
var markets = exchange.GetMarkets()
if (!markets) {
throw "get markets error"
}
var tbl = {
type: "table",
title: "test markets",
cols: [
"key", "Symbol", "BaseAsset", "QuoteAsset", "TickSize", "AmountSize", "PricePrecision", "AmountPrecision", "MinQty",
"MaxQty", "MinNotional", "MaxNotional", "CtVal", "CtValCcy"
],
rows: []
}
for (var symbol in markets) {
var market = markets[symbol]
tbl.rows.push([
symbol, market.Symbol, market.BaseAsset, market.QuoteAsset, market.TickSize, market.AmountSize,
market.PricePrecision, market.AmountPrecision, market.MinQty, market.MaxQty, market.MinNotional, market.MaxNotional, market.CtVal, market.CtValCcy
])
}
LogStatus("`" + JSON.stringify(tbl) + "`")
return markets
}
On peut voir que le type de contrat sur Vertex est un contrat basé sur l’USDC, la marge est l’USDC et la valeur d’un contrat représente une devise correspondante, par exempleBTC_USDC.swap
Autrement dit, le contrat BTC basé sur l’USDC, un contrat représente une position BTC. Le code ci-dessus montre comment demander des informations sur le marché des contrats et générer divers contenus.
function main() {
var depths = [{"symbol": "ETH_USDC"}, {"symbol": "SOL_USDC"}, {"symbol": "BTC_USDC"}]
for (var ele of depths) {
ele["depth"] = exchange.GetDepth(ele["symbol"] + ".swap")
}
var tbls = []
for (var ele of depths) {
var tbl = {"type": "table", "title": ele["symbol"], "cols": ["level", "price", "amount"], "rows": []}
var depth = ele["depth"]
for (var i = 0 ; i < 3 ; i++) {
tbl["rows"].push(["卖" + (i + 1), depth.Asks[i].Price, depth.Asks[i].Amount])
}
tbl["rows"].reverse()
for (var i = 0 ; i < 3 ; i++) {
tbl["rows"].push(["买" + (i + 1), depth.Bids[i].Price, depth.Bids[i].Amount])
}
tbls.push(tbl)
}
LogStatus("`" + JSON.stringify(tbls) + "`")
}
function main() {
var arrTrades = [{"symbol": "ETH_USDC"}, {"symbol": "SOL_USDC"}, {"symbol": "BTC_USDC"}]
for (var ele of arrTrades) {
ele["trades"] = exchange.GetTrades(ele["symbol"] + ".swap")
}
var tbls = []
for (var ele of arrTrades) {
var tbl = {"type": "table", "title": ele["symbol"], "cols": ["Time", "Price", "Amount", "side"], "rows": []}
var trades = ele["trades"]
for (var trade of trades) {
tbl["rows"].push([_D(trade.Time), trade.Price, trade.Amount, trade.Type == 0 ? "买入" : "卖出"])
}
tbls.push(tbl)
}
LogStatus("`" + JSON.stringify(tbls) + "`")
}
function main() {
let c = KLineChart({
overlay: true
})
let bars = exchange.GetRecords("SOL_USDC.swap")
if (!bars) {
return
}
bars.forEach(function(bar, index) {
c.begin(bar)
Log(index, bar)
c.close()
})
}
Carte des sommets
Dessin de la stratégie et des opérations de la FMZ
function main() {
var fundings = exchange.GetFundings()
var tbl = {
"type": "table",
"title": "GetFundings",
"cols": ["Symbol", "Interval", "Time", "Rate"],
"rows": [],
}
for (var f of fundings) {
tbl["rows"].push([f.Symbol, f.Interval / 3600000, _D(f.Time), f.Rate * 100 + " %"])
}
LogStatus(_D(), "\n`" + JSON.stringify(tbl) + "`")
}
Le cycle de financement est d’une heure.
Max Order Size Gets the max order size possible of a given product for a given subaccount.
function main() {
// GET [GATEWAY_REST_ENDPOINT]/query?type=max_order_size&product_id={product_id}&sender={sender}&price_x18={price_x18}&direction={direction}
// price_x18=3000000000000000000000 : 3000 USDC
// product_id=4 : ETH_USDC.swap
// sender=0x123 : e.g. 0x123
return HttpQuery("https://gateway.prod.vertexprotocol.com/query?type=max_order_size&product_id=4&sender=0x123&price_x18=3000000000000000000000&direction=short")
}
Les données renvoyées par la requête finale sont :{"status":"success","data":{"max_order_size":"170536415320344899"},"request_type":"query_max_order_size"}
On peut voir que les actifs disponibles sur le compte courant pour le contrat perpétuel Ethereum avec un prix de 3000, la quantité maximale de commande pour un ordre de vente est de : 0,17 ETH
Linked Signer Retrieves current linked signer of a provided subaccount
function main() {
return HttpQuery("https://gateway.prod.vertexprotocol.com/query?type=linked_signer&subaccount=0x123")
}
Informations d’autorisation trouvées :
{“status”:“success”,“data”:{“linked_signer”:“0x79119…”},“request_type”:“query_linked_signer”} L’adresse « 0x79119 » est l’adresse proxy permettant d’autoriser les transactions de commande lors de la connexion au portefeuille sur la page front-end de Vertex. Cette autorisation peut être révoquée ou ajoutée (via des appels API).
Voici le sujet de cet article. Nous nous sommes occupés pendant longtemps de réaliser des transactions simplement et rapidement sur des échanges décentralisés.
Testez une transaction plus simple et placez un ordre limité normal.
function main() {
var id1 = exchange.CreateOrder("ETH_USDC.swap", "buy", 2000, 0.1)
var id2 = exchange.CreateOrder("SOL_USDC.swap", "buy", 60, 2)
Log("ETH_USDC.swap id1:", id1)
Log("SOL_USDC.swap id2:", id2)
var orders = exchange.GetOrders("USDC.swap")
var tbl = {type: "table", title: "test GetOrders", 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("`" + JSON.stringify(tbl) + "`")
}
function main() {
var orders = exchange.GetOrders("USDC.swap")
var tbl = {type: "table", title: "test GetOrders", 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])
exchange.CancelOrder(order.Id)
}
LogStatus("`" + JSON.stringify(tbl) + "`")
return exchange.GetOrders()
}
function main() {
// 使用市价单下单持仓
exchange.SetCurrency("ETH_USDC")
exchange.SetContractType("swap")
exchange.Buy(-1, 0.01)
var positions = exchange.GetPositions()
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])
}
LogStatus("`" + JSON.stringify(tbl) + "`")
}
Il convient de noter que les données fournies par l’API Vertex diffèrent du contenu affiché sur la page d’accueil de Vertex, principalement en raison des différences dans le prix moyen des titres et dans les profits et pertes des titres. Ces informations ont été transmises à l’équipe Vertex et peuvent être mises à niveau et mises à jour ultérieurement.
4、Trigger Order
Étant donné que l’ordre de déclenchement du sommet est indépendant du point de terminaison,exchange.IO
Lorsque vous passez une commande conditionnelle pour une fonction, vous devez spécifierTrigger: https://trigger.prod.vertexprotocol.com
, continuons avec l’opération pratique.
function main() {
// isTrigger : true
var nonce = exchange.IO("nonce", true) // 如果是 Trigger Order 订单用到的 nonce 需要指定 isTrigger : true
// flag , reduceOnly
var expiration = exchange.IO("expiration", "GTC", false) // 设置订单为GTC类型,非只减仓
// params
var params = {
"place_order": {
"product_id": 4,
"order": {
"sender": "0x123...",
"priceX18": "4100000000000000000000",
"amount": "-100000000000000000",
"expiration": expiration,
"nonce": nonce
},
"trigger": {
"price_above": "4000000000000000000000"
}
}
}
return exchange.IO("api", "POST", "https://trigger.prod.vertexprotocol.com/v1/execute", "", JSON.stringify(params))
}
Sous le point de déclenchement, il y a également :
La méthode d’appel est similaire à Place Trigger Order, je n’entrerai donc pas dans les détails ici.
La balise de sous-compte par défaut est :default
, nous passons à une balise personnalisée :subAcc02
。
function main() {
exchange.IO("subAccountTag", "subAcc02")
return exchange.GetAccount()
}
Lors du transfert d’argent vers une adresse de sous-compte, Vertex créera réellement ce sous-compte.
Le nonce du compte doit être interrogé et transmis dans les paramètres de l’interface de transfert en tant que paramètre.
function main() {
var ret = HttpQuery("https://gateway.prod.vertexprotocol.com/v1/query?type=nonces&address=0x123...")
var obj = JSON.parse(ret)
var nonce = obj["data"]["tx_nonce"]
Log("nonce:", nonce)
var params = {
"transfer_quote": {
"tx": {
// default -> subAcc02
"sender": "0xabc...", // default
"recipient": "0xdef...", // subAcc02
"amount": "7000000000000000000",
"nonce": nonce
}
}
}
return exchange.IO("api", "POST", "https://gateway.prod.vertexprotocol.com/v1/execute", "", JSON.stringify(params))
}
Par exemple : 0xabc… correspond à l’adresse du sous-compte avec la balise default. 0xdef… correspond à l’adresse du sous-compte avec la balise subAcc02. 0x123… est l’adresse du portefeuille.
function main() {
var ret = HttpQuery("https://gateway.prod.vertexprotocol.com/v1/query?type=nonces&address=0x123...")
var obj = JSON.parse(ret)
var nonce = obj["data"]["tx_nonce"]
Log("nonce:", nonce)
var params = {
"withdraw_collateral": {
"tx": {
"sender": "0xabc...", // default
"productId": 0, // USDC : 0 , precision : 6
"amount": "10000000", // 10 USDC
"nonce": nonce
}
}
}
return exchange.IO("api", "POST", "https://gateway.prod.vertexprotocol.com/v1/execute", "", JSON.stringify(params))
}
Faites attention à la précision de l’USDC.
function main() {
var ret = HttpQuery("https://gateway.prod.vertexprotocol.com/v1/query?type=nonces&address=0x123...")
var obj = JSON.parse(ret)
var nonce = obj["data"]["tx_nonce"]
Log("nonce:", nonce)
var params = {
"mint_lp": {
"tx": {
"sender": "0xabc...", // default
"productId": 31, // USDT_USDC
"amountBase": "10000000000000000000",
"quoteAmountLow": "9999900000000000000",
"quoteAmountHigh": "10100000000000000000",
"nonce": nonce,
}
}
}
return exchange.IO("api", "POST", "https://gateway.prod.vertexprotocol.com/v1/execute", "", JSON.stringify(params))
}
Jetons Mint LP pour les paires de tradingUSDT_USDC
Le pool d’échange ajoute de la liquidité.
function main() {
var ret = HttpQuery("https://gateway.prod.vertexprotocol.com/v1/query?type=nonces&address=0x123...")
var obj = JSON.parse(ret)
var nonce = obj["data"]["tx_nonce"]
Log("nonce:", nonce)
var params = {
"burn_lp": {
"tx": {
"sender": "0xabc...", // default
"productId": 31, // USDT_USDC
"amount": "7500000000000000000",
"nonce": nonce,
}
}
}
return exchange.IO("api", "POST", "https://gateway.prod.vertexprotocol.com/v1/execute", "", JSON.stringify(params))
}
Point de terminaison de l’interface Websocket :wss://gateway.prod.vertexprotocol.com/v1/ws
。
[🚧🚧🚧ing…]
Les tests ci-dessus sont basés sur le dernier dépositaire. Vous devez télécharger le dernier dépositaire pour prendre en charge l’agrégateur Vertex DEX.
Merci pour votre soutien et merci de votre lecture.