Explication détaillée de la stratégie des ordres en attente de BitMEX

Auteur:La bonté, Créé: 2019-01-16 15:28:13, Mis à jour: 2019-01-22 14:16:48

BitMEX est devenue la plateforme de choix pour le trading d'effet de levier de crypto-monnaie, mais ses restrictions de trading d'API sont strictes et rendent les traders automatiques très confus.

1. Caractéristiques du BitMEX

L'avantage le plus significatif est que la liquidité de négociation est très active, en particulier le contrat perpétuel Bitcoin, le montant de la transaction par minute dépasse souvent un million ou même dix millions de dollars américains; BitMEX les ordres en attente de négociation ont la politique de retour des frais de commission, bien que ce ne soit pas beaucoup, mais a attiré un grand nombre de négociations de fabrication de marché, ce qui a rendu la profondeur des prix très riche. le dernier prix d'achat et de vente ont souvent plus d'un million de dollars de valeur des ordres en attente; à cause de ce point, le prix de la transaction fluctue souvent autour de l'unité de changement minimum de $ 0,50.

Limites de fréquence de l'API BitMEX

La fréquence de requête de l'API REST est limitée à 300 fois toutes les 5 minutes, presque égale à 1 fois toutes les secondes, cette limite peut être considérée comme très stricte par rapport aux autres plateformes de trading. Une fois la limite dépassée, Rate limit exceeded sera demandé. Si vous continuez à dépasser la limite, l'IP peut être désactivée pendant une heure. Plusieurs désactivations en peu de temps entraîneront une semaine de désactivation. Pour chaque requête d'API, BitMEX renverra les données d'en-tête, les données d'en-tête sont utilisées pour voir le nombre actuel de requêtes restantes. En fait, si l'API est utilisée correctement, elle ne dépassera pas la limite de fréquence et n'a généralement pas besoin d'être vérifiée.

3.Utilisez le websocket pour obtenir le devis du marché

L'API REST de BitMEX est plus restrictive. La recommandation officielle est d'utiliser davantage le protocole websocket et de pousser plus de types de données que l'échange moyen.

Si le temps de poussée des données de profondeur est trop long, il y aura une erreur, qui ne correspond pas à la profondeur réelle. Les détails de commande manquent beaucoup et sont presque indisponibles. Il y a un retard significatif dans la publication des informations de compte, de préférence en utilisant l'API REST. Lorsque la volatilité du marché est trop grande, le délai de repoussée atteindra quelques secondes. Le code suivant utilise le protocole websocket pour obtenir des informations sur les marchés et les comptes en temps réel, principalement pour les stratégies de création de marché.

var ticker  = {price:0, buy:0, sell:0, time:0} //Ticker information, the latest price, "buy one" price, "sell one" price, update time
//Account information, respectively, position, buying and selling price, buying and selling quantity, position status, order Id
var info = {position:0, buyPrice:0, sellPrice:0, buyAmount:0, sellAmount:0, buyState:0, sellState:0, buyId:0, sellId:0}
var buyListId = []//Global variables, pre-emptive buying id list, will described below
var sellListId = []
var APIKEY = 'your api id' //Need to fill in the BitMEX API ID here. Note that it is not a key, which is required for websocket protocol authentication.
var expires = parseInt(Date.now() / 1000) + 10
var signature = exchange.HMAC("sha256", "hex", "GET/realtime" + expires, "{{secretkey}}")//The secretkey will be automatically replaced at the bottom level and does not need to be filled in.
var bitmexClient = Dial("wss://www.bitmex.com/realtime", 60)
var auth = JSON.stringify({args: [APIKEY, expires, signature], op: "authKeyExpires"})//Authentication information, otherwise you cannot subscribe to the account
bitmexClient.write(auth)
bitmexClient.write('{"op": "subscribe", "args": ["position","execution","trade:XBTUSD"]}')//Subscribed to positions, order execution and perpetual contract real-time transaction
while(true){
    var data = bitmexClient.read()
    if(data){
        bitmexData = JSON.parse(data)
        if('table' in bitmexData && bitmexData.table == 'trade'){
            data = bitmexData.data
            ticker.price = parseFloat(data[data.length-1].price)//The latest transaction price, will push multiple transactions at a time, take one will be ok
            //You can get the "buy one" and "sell one" price according to the direction of the latest transaction, without subscribing to the depth.
            if(data[data.length-1].side == 'Buy'){
                ticker.sell = parseFloat(data[data.length-1].price)
                ticker.buy = parseFloat(data[data.length-1].price)-0.5
            }else{
                ticker.buy = parseFloat(data[data.length-1].price)
                ticker.sell = parseFloat(data[data.length-1].price)+0.5
            }
            ticker.time =  new Date(data[data.length-1].timestamp);//Update time, can be used to determine the delay
        }
    }else if(bitmexData.table == 'position'){
        var position = parseInt(bitmexData.data[0].currentQty)  
        if(position != info.position){
            Log('Position change: ', position, info.position, '#FF0000@')//Position change Log, and pushed to WeChat, remove @ means Do not push
            info.position = position  
        }
        info.position  = parseInt(bitmexData.data[0].currentQty)  
    }
}

4° Les compétences en matière de mise en place des ordres

BitMEX recommande officiellement d'utiliser commande en vrac et modification d'ordre pour passer une commande. commande en vrac peut être exécutée plus rapidement en raison de l'audit en temps réel, de la vérification des risques, du calcul de la marge et de la mise en service de BitMEX. Par conséquent, la fréquence de commande en vrac est calculée comme un dixième de la fréquence normale. En outre, notre opération d'ordre doit utiliser la méthode de commande en vrac et modification d'ordre pour minimiser l'utilisation de l'API.

commande en vrac ne limite pas la quantité de commande (ne peut pas être trop), en fait, une seule commande peut également utiliser l'interface commande en vrac. En raison de l'opération de modification de la commande, nous pouvons pré-commande certaines commandes où le prix dévie considérablement, ces commandes ne seront pas exécutées, mais lorsque nous avons besoin de passer une commande, nous n'avons qu'à modifier le prix et la quantité de la commande passée. lorsque la modification de la commande se produit échec, il peut également être utilisé comme signal pour l'ordre à exécuter.

Le code de mise en œuvre spécifique est le suivant:

// Cancel all orders and reset global variables
function cancelAll(){
    exchange.IO("api","DELETE","/api/v1/order/all","symbol=XBTUSD")//Call IO extension revocation
    info = {position:0, buyPrice:0, sellPrice:0, buyAmount:0, sellAmount:0, buyState:0, sellState:0, buyId:0, sellId:0}
    buyListId = []
    sellListId = []
}
//placing alternate order
function waitOrders(){
    var orders = []
    if(buyListId.length<4){
        //When the number of inspections is insufficient, place another "bulk"
        for(var i=0;i<7;i++){
            //Due to BitMEX restrictions, the price can not be excessively excessive, the order quantity can not be too small, and the "execInst" parameter guarantees that only the market making transaction can be executed.
            orders.push({symbol:'XBTUSD', side:'Buy', orderQty:100, price:ticker.buy-400+i, execInst:'ParticipateDoNotInitiate'})
        }
    }
    if(sellListId.length<4){
        for(var i=0;i<7;i++){
            orders.push({symbol:'XBTUSD', side:'Sell', orderQty:100, price:ticker.buy+400+i, execInst:'ParticipateDoNotInitiate'})
        }
    }
    if(orders.length>0){
        var param = "orders=" + JSON.stringify(orders);
        var ids = exchange.IO("api", "POST", "/api/v1/order/bulk", param);//Bulk orders submitted here
        for(var i=0;i<ids.length;i++){
            if(ids.side == 'Buy'){
                buyListId.push(ids.orderID)
            }else{
                sellListId.push(ids.orderID)
            }
        }
    }
}
//Modify order function
function amendOrders(order, direction, price, amount, id){
    var param = "orders=" + JSON.stringify(order);
    var ret = exchange.IO("api", "PUT", "/api/v1/order/bulk", param);//Modify one order at a time
    //Modification occurs error
    if(!ret){
        var err = GetLastError()
        //overloaded unmodified strategy, need to recycle the order id
        if(err.includes('The system is currently overloaded')){
            if(id){
                if(direction == 'buy'){
                    buyListId.push(id)
                }else{
                    sellListId.push(id)
                }
            }
            Sleep(1000)
            return
        }
        //Illegal order status, indicating that the order to be modified has been completely executed
        else if(err.includes('Invalid ordStatus')){
            Log(order, direction)
            if(direction == 'buy'){
                info.buyId = 0
                info.buyState = 0
                info.buyAmount = 0
                info.buyPrice = 0
            }else{
                info.sellId = 0
                info.sellState = 0
                info.sellAmount = 0
                info.sellPrice = 0
            }
            //Since the push is not timely, update the position with the "rest" protocol here.
            pos = _C(exchange.GetPosition)
            if(pos.length>0){
                info.position = pos[0].Type == 0 ? pos[0].Amount : -pos[0].Amount
            }else{
                info.position = 0
            }
        }
        //Unknown error cannot be modified, all orders are cancelled, reset once
        else if(err.includes('Invalid orderID')){
            cancelAll()
            Log('Invalid orderID,reset once')
        }
        //Exceed the frequency limit, you can continue to try after hibernation
        else if(err.includes('Rate limit exceeded')){
            Sleep(2000)
            return
        }
        //The account is banned, all orders are revoked, and sleep is awaiting recovery for a long time.
        else if(err.includes('403 Forbidden')){
            cancelAll()
            Log('403,reset once')
            Sleep(5*60*1000)
        }
    }else{
        //Modify order successfully
        if(direction == 'buy'){
            info.buyState = 1
            info.buyPrice = price
            info.buyAmount = amount
        }else{
            info.sellState = 1
            info.sellPrice = price
            info.sellAmount = amount
        }
    }
}
//0.5 price change
function fixSize(num){
    if(num>=_N(num,0)+0.75){
        num = _N(num,0)+1
    }else if(num>=_N(num,0)+0.5){
        num=_N(num,0)+0.5
    }else{
        num=_N(num,0)
    }
    return num
}
//Trading function
function trade(){
    waitOrders()//Check if you need a replacement order
    var buyPrice = fixSize(ticker.buy-5) //For demonstration purposes only, specific transactions should be written by yourself.
    var sellPrice = fixSize(ticker.sell+5)
    var buyAmount =  500
    var sellAmount = 500
    //Modify from an alternate order when there is no order
    if(info.buyState == 0  && buyListId.length > 0){
        info.buyId = buyListId.shift()
        amendOrders([{orderID:info.buyId, price:buyPrice, orderQty:buyAmount}],'buy', group, buyPrice, buyAmount, info.buyId)
    }
    if(info.sellState == 0 && sellListId.length > 0){
        info.sellId = sellListId.shift()
        amendOrders([{orderID: info.sellId, price:sellPrice, orderQty:sellAmount}],'sell', group, sellPrice, sellAmount, info.sellId )
    }
    //Existing orders need to change price
    if(buyPrice !=  info.buyPrice && info.buyState == 1){
        amendOrders([{orderID:info.buyId, price:buyPrice, orderQty:buyAmount}],'buy', group, buyPrice, buyAmount)
    }
    if(sellPrice != info.sellPrice && info.sellState == 1){
        amendOrders([{orderID:info.sellId, price:sellPrice, orderQty:sellAmount}],'sell', group, sellPrice, sellAmount)
    }
}

5. Autres

Le serveur de BitMEX est situé dans le serveur d'Amazon à Dublin, en Irlande. Le ping du serveur est inférieur à 1 ms lorsque vous choisissez un serveur cloud AWS à Dublin, mais lorsqu'il y a encore un retard dans la poussée, le problème de surcharge ne peut pas être résolu. En outre, lorsque le compte est connecté, l'agent du serveur ne peut pas être situé aux États-Unis et dans d'autres endroits où ne permettent pas les échanges de crypto-monnaie. En raison du règlement, le compte sera interdit.

Le code dans cet article a été modifié à partir de ma stratégie personnelle et n'est pas garanti pour être complètement correct à titre de référence.


Plus de

gmgphilLe connecteur WS produit une erreur: Erreur de référence: identifiant "données" non défini à...

Le foinUne erreur de code, le problème a été résolu.