[TOC]
Este é o terceiro artigo sobre a prática quantitativa de exchanges DEX. Desta vez, apresentaremos o guia de uso do protocolo Vertex.
No contexto das bolsas descentralizadas tradicionais (DEX), os traders quantitativos geralmente precisam fazer concessões: ou aceitam o alto deslizamento e a baixa eficiência de execução do modelo de criador de mercado automatizado (AMM), ou caem no dilema técnico da fragmentação de liquidez entre cadeias e funções de derivativos únicos. O surgimento do Protocolo Vertex está redefinindo os limites on-chain das estratégias quantitativas por meio de um experimento de fusão “nível descentralizado + institucional” - não há um dilema de “escolha um dos dois” aqui, apenas o equilíbrio final entre velocidade, profundidade e liberdade.
Como a primeira DEX a integrar um pool de liquidez multicadeia unificado, livro de ordens híbrido (CLOB) e mercado de moeda incorporado, a Vertex considera “experiência centralizada, alma descentralizada” como seu núcleo e abre um caminho único para traders quantitativos:
Uma nova definição de velocidade e fluidez
Com a evolução contínua da tecnologia blockchain, a fronteira entre as bolsas centralizadas tradicionais (CEX) e as bolsas descentralizadas (DEX) está gradualmente se confundindo. Como o centro da plataforma Vertex, o Vertex Edge não apenas remodela a velocidade e a liquidez das transações, mas também combina perfeitamente uma excelente tecnologia de correspondência de ordens e vantagens de autocustódia por meio da integração entre cadeias, trazendo uma nova experiência DeFi para traders globais.
Unificando a liquidez entre cadeias: quebrando a fragmentação da liquidez Nos mercados tradicionais, a liquidez entre diferentes cadeias é frequentemente fragmentada, o que faz com que os comerciantes não consigam aproveitar os melhores preços e profundidade de transação. A Vertex Edge nasceu nesse contexto, concretizando o compartilhamento sincronizado de liquidez permanente entre diversas cadeias por meio de uma rede unificada de livro de ordens. Atualmente, a Vertex Edge cobre liquidez de contratos perpétuos em 7 cadeias tradicionais, incluindo Arbitrum, Base, Sei, Blast, Mantle, Sonic e Abstract, para que os traders não precisem mais se preocupar com a dispersão de liquidez e possam negociar pelo melhor preço, alcançando verdadeiramente uma conexão perfeita de liquidez global.
Negociação de livro de ordens híbrido: o equilíbrio perfeito entre correspondência ultrarrápida e liquidação na cadeia A Vertex Edge adota um modelo de negociação de livro de ordens híbrido e suas principais tecnologias incluem:
Correspondente de livro de ordens off-chain: utiliza um mecanismo de correspondência off-chain de altíssima velocidade para obter correspondência de ordens com uma latência de apenas 5 a 15 milissegundos, comparável à maioria das exchanges centralizadas; Mecanismo de risco na cadeia e AMM: sistemas de gerenciamento de risco e formadores de mercado automatizados (AMMs) são implantados em cada cadeia suportada para garantir que as ordens possam ser liquidadas de forma segura e transparente após a correspondência. Essa arquitetura não apenas garante uma resposta de transação extremamente rápida, mas também fornece aos usuários segurança descentralizada por meio de liquidação na cadeia, permitindo que os traders desfrutem de desempenho de nível CEX enquanto mantêm a independência da autocustódia de ativos.
Função multiconta: gerencie várias contas em uma única carteira e aloque fundos de forma mais eficiente; Posições spot alavancadas: Use todos os ativos como margem para alcançar maior eficiência de capital; Gestão de risco flexível: depósitos, posições e dados de lucros e perdas são considerados de maneira unificada para controlar com precisão a exposição ao risco.
Endereço da página de login “protocolo vertex”:
O Vertex é o mesmo que a maioria dos DEXs. Após fazer login no dapp, você precisa se conectar à carteira para autorização. O sistema de subcontas do Vertex é diferenciado com base em um rótulo. O rótulo participa do cálculo do endereço da carteira para obter um endereço de carteira de subconta. Ao mesmo tempo, esse endereço é autorizado a fazer pedidos e outras operações.
Por exemplo, useWalletConnectO endereço da carteira quando conectado é:0x7a5ec2748e9065794491a8d29dcf3f9edb8d7c43
, o rótulo padrão é “padrão” e o endereço da subconta calculado é:0x7a5ec2748e9065794491a8d29dcf3f9edb8d7c4364656661756c740000000000
. As tags padrão são:64656661756c740000000000
。
O Vertex suporta a recarga de múltiplos ativos. Geralmente, você escolhe recarregar USDC como uma margem e usa diretamente a carteira conectada para transferir transações. Vale ressaltar que operações como retirada, transferência, envio de tokens e transferência de subcontas na Vertex consumirão USDC, e as taxas não são baixas, portanto, essas operações precisam ser feitas com cautela.
Mudar para uma cadeia diferente:
No vértice, diferentes cadeias têm diferentes informações de configuração, como nós, indexadores e IDs de cadeia. A cadeia padrão para encapsulamento FMZ éArbitrum One
Pode ser usado.Log(HttpQuery("https://gateway.prod.vertexprotocol.com/v1/query?type=contracts"))
Consultar o ID de uma cadeia, informações de contrato implantadas, etc.
Após efetuar login no FMZ.COM, na página de configuração da exchange, selecione “Cryptocurrency”, selecione Vertex Exchange, você pode configurar diretamente a chave proxy da carteira no dapp. Claro, você também pode configurar a chave privada da carteira. No Vertex, você pode usar a interface para gerenciar autorização/desautorização da chave proxy e outras operações, o que também é mais conveniente.
Chave proxy:
Por exemplo, na página de front-end da troca de vertex DEX: navegador Chrome (ative a depuração) -> Aplicativo -> Armazenamento local -> https://app.vertex -> vertex userSettings
Configurar troca de vértices
Duas coisas precisam ser configuradas no FMZ. A primeira é o endereço da carteira (não o endereço da chave proxy usada para assinatura, deve ser o endereço da carteira conectado ao dapp). A segunda é a chave secreta usada para assinatura (pode ser uma chave privada de carteira ou uma chave de proxy). Como as chaves de proxy podem ser usadas, o endereço da carteira configurada e a chave não são necessariamente um par.
O sistema de subcontas do Vertex é identificado por tags. A tag padrão usada no FMZ édefault
A conta principal da tag, caso precise alternar, você pode utilizá-la no código:
exchange.IO("subAccountTag", "default") // 切换到主子账号
exchange.IO("subAccountTag", "test01") // 切换到标签名为 test01 的子账号
Depois de configurar as informações de configuração da troca e implantar um programa custodiante que pode acessar a interface do vértice, podemos começar a escrever algum código para operações práticas.
Usamos a subconta principal para testes (a subconta com tag: default) e usamosArbitrumrede.
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
}
Pode-se observar que o tipo de contrato no Vertex é um contrato baseado em USDC, a margem é USDC e o valor de um contrato representa uma moeda correspondente, por exemploBTC_USDC.swap
Ou seja, no contrato de BTC baseado em USDC, um contrato representa uma posição de BTC. O código acima mostra como solicitar informações de mercado de contratos e gerar vários conteúdos.
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()
})
}
Gráfico de vértices
Desenho de operação de estratégia 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) + "`")
}
O ciclo da taxa de financiamento é de 1 hora.
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")
}
Os dados retornados pela solicitação final são:{"status":"success","data":{"max_order_size":"170536415320344899"},"request_type":"query_max_order_size"}
Pode-se observar que os ativos disponíveis na conta corrente para o contrato perpétuo Ethereum com preço de 3000, a quantidade máxima de pedido para uma ordem de venda é: 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")
}
Informações de autorização encontradas:
{“status”:“success”,“data”:{“linked_signer”:“0x79119…”},“request_type”:“query_linked_signer”} O endereço “0x79119…” é o endereço proxy para autorizar transações de pedidos ao conectar-se à carteira na página front-end do Vertex. Essa autorização pode ser revogada ou adicionada (por meio de chamadas de API).
O seguinte é o foco deste artigo. Estamos ocupados há muito tempo apenas para conduzir transações de forma simples e rápida em exchanges descentralizadas.
Teste uma negociação mais simples e coloque uma ordem de limite 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) + "`")
}
Deve-se notar que os dados fornecidos pela API Vertex divergem do conteúdo exibido na página front-end da Vertex, principalmente devido a diferenças no preço médio de holding e no lucro e perda de holdings. Isso foi enviado de volta à equipe da Vertex e pode ser atualizado e atualizado posteriormente.
4、Trigger Order
Como a ordem de disparo do vértice é independente do ponto final,exchange.IO
Ao colocar uma ordem condicional para uma função, você precisa especificarTrigger: https://trigger.prod.vertexprotocol.com
, vamos continuar com a operação prática.
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))
}
Abaixo do ponto de extremidade do gatilho, há também:
O método de chamada é semelhante ao Place Trigger Order, então não entrarei em detalhes aqui.
A tag de subconta padrão é:default
, mudamos para uma tag personalizada:subAcc02
。
function main() {
exchange.IO("subAccountTag", "subAcc02")
return exchange.GetAccount()
}
Ao transferir dinheiro para um endereço de subconta, o Vertex criará essa subconta.
O nonce da conta precisa ser consultado e passado para os parâmetros da interface de transferência como um parâmetro.
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))
}
Por exemplo: 0xabc… corresponde ao endereço da subconta com a tag default. 0xdef… corresponde ao endereço da subconta com a tag subAcc02. 0x123… é o endereço da carteira.
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))
}
Preste atenção à precisão do 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))
}
Tokens Mint LP para pares de negociaçãoUSDT_USDC
O pool de câmbio acrescenta liquidez.
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))
}
Ponto final da interface do Websocket:wss://gateway.prod.vertexprotocol.com/v1/ws
。
[🚧🚧🚧ing…]
Os testes acima são baseados no custodian mais recente. Você precisa baixar o custodian mais recente para dar suporte ao agregador Vertex DEX.
Obrigado pelo seu apoio e obrigado pela leitura.