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

Conception de la stratégie Martingale pour les contrats à terme de crypto-monnaie

Auteur:FMZ~Lydia, Créé: 2022-08-04 15:41:45, Mis à jour: 2023-09-21 21:10:49

img

Conception de la stratégie Martingale pour les contrats à terme de crypto-monnaie

Récemment, il y a beaucoup de stratégies Martingale discutées dans le groupe officiel de FMZ, et il n'y a pas beaucoup de stratégies Martingale de contrats de crypto-monnaie sur la plate-forme. Par conséquent, j'ai profité de l'occasion pour concevoir une stratégie Martingale simple pour les contrats à terme de crypto-monnaie. Pourquoi est-elle appelée stratégie Martingale? Parce que les risques potentiels de la stratégie Martin ne sont en effet pas petits, elle n'est pas conçue exactement selon la stratégie Martin. Cependant, ce type de stratégie comporte encore de nombreux risques, et les paramètres de la stratégie de type Martin sont étroitement liés au risque, et le risque ne doit pas être ignoré.

Cet article explique principalement et apprend de la conception de stratégies de type Martin.

Obtenir des capitaux propres totaux

L'équité totale est souvent utilisée lors de la conception de stratégies à terme de crypto-monnaie. C'est parce que les rendements doivent être calculés, en particulier lorsque vous devez calculer les rendements flottants. Puisque la position est occupée par la marge, l'ordre en attente est également occupé.exchange.GetAccount()En fait, la plupart des bourses à terme de crypto-monnaie fournissent les données du capital total, mais cet attribut n'est pas uniformément regroupé sur FMZ.

Nous avons donc conçu des fonctions pour obtenir ces données selon différents échanges:

// OKEX V5 obtain total equity
function getTotalEquity_OKEX_V5() {
    var totalEquity = null 
    var ret = exchange.IO("api", "GET", "/api/v5/account/balance", "ccy=USDT")
    if (ret) {
        try {
            totalEquity = parseFloat(ret.data[0].details[0].eq)
        } catch(e) {
            Log("failed to obtain the total equity of the account!")
            return null
        }
    }
    return totalEquity
}

// Binance futures
function getTotalEquity_Binance() {
    var totalEquity = null 
    var ret = exchange.GetAccount()
    if (ret) {
        try {
            totalEquity = parseFloat(ret.Info.totalWalletBalance)
        } catch(e) {
            Log("failed to obtain the total equity of the account!")
            return null
        }
    }
    return totalEquity
}

LetotalEquitydans le code est le capital total dont nous avons besoin. puis nous écrivons une fonction comme l'entrée d'appel, et appeler la fonction correspondante selon le nom de l'échange.

function getTotalEquity() {
    var exName = exchange.GetName()
    if (exName == "Futures_OKCoin") {
        return getTotalEquity_OKEX_V5()
    } else if (exName == "Futures_Binance") {
        return getTotalEquity_Binance()
    } else {
        throw "This exchange is not supported"
    }
}

Concevoir des fonctions auxiliaires

Avant de concevoir la fonction principale et la logique principale, nous devons faire quelques préparatifs et concevoir quelques fonctions auxiliaires.

  • Annuler toutes les commandes en attente

    function cancelAll() {
        while (1) {
            var orders = _C(exchange.GetOrders)
            if (orders.length == 0) {
                break
            }
            for (var i = 0 ; i < orders.length ; i++) {
                exchange.CancelOrder(orders[i].Id, orders[i])
                Sleep(500)
            }
            Sleep(500)
        }
    }
    

    Cette fonction est familière à ceux qui lisent souvent le code d'exemple de stratégie sur le carré de stratégie FMZ, et de nombreuses stratégies ont utilisé des conceptions similaires.

  • Opérations de placement de contrats à terme

    function trade(distance, price, amount) {
        var tradeFunc = null 
        if (distance == "buy") {
            tradeFunc = exchange.Buy
        } else if (distance == "sell") {
            tradeFunc = exchange.Sell
        } else if (distance == "closebuy") {
            tradeFunc = exchange.Sell
        } else {
            tradeFunc = exchange.Buy
        }
        exchange.SetDirection(distance)
        return tradeFunc(price, amount)
    }
    
    function openLong(price, amount) {
        return trade("buy", price, amount)
    }
    
    function openShort(price, amount) {
        return trade("sell", price, amount)
    }
    
    function coverLong(price, amount) {
        return trade("closebuy", price, amount)
    }
    
    function coverShort(price, amount) {
        return trade("closesell", price, amount)
    }
    

    Il existe quatre directions pour le trading de contrats à terme: openLong, openShort, coverLong et coverShort. Nous avons donc conçu quatre fonctions d'ordre correspondant à ces opérations. Si vous considérez seulement l'ordre, alors il y a plusieurs facteurs nécessaires: direction, prix de l'ordre et volume de l'ordre. Nous avons aussi conçu une fonction appelée:tradepour gérer l'opération lorsquedistance, price, amountsont spécifiées. Les appels à la fonction openLong, openShort, coverLong et coverShort sont finalement complétés par letradefonction, c'est-à-dire la mise en place d'un ordre sur un marché à terme basé sur la distance, le prix et la quantité établis.

Fonction principale

L'idée de la stratégie est très simple, prenez le prix actuel comme référence et placez des ordres de vente (short) et d'achat (long) à une certaine distance vers le haut ou vers le bas. Une fois la transaction terminée, tous les ordres restants seront annulés, puis un nouvel ordre de clôture sera placé à une certaine distance selon le prix de la position, et un ordre d'augmentation sera placé au prix actuel mis à jour, mais le volume de l'ordre ne sera pas doublé pour les positions supplémentaires.

  • Travaux initiaux En raison de l'ordre en attente, nous avons besoin de deux variables globales pour enregistrer l'identifiant de commande.

    var buyOrderId = null
    var sellOrderId = null
    

    Ensuite, les paramètres d'interface de stratégie sont conçus pour utiliser l'option OKEX_V5 simulé bot, donc un certain traitement doit être fait dans le code:

    var exName = exchange.GetName()    
    // Switch OKEX V5 simulated bot
    if (isSimulate && exName == "Futures_OKCoin") {
        exchange.IO("simulate", true)
    }
    

    Il y a aussi une option pour réinitialiser toutes les informations dans les paramètres d'interface, donc il devrait y avoir un traitement correspondant dans le code:

    if (isReset) {
        _G(null)
        LogReset(1)
        LogProfitReset()
        LogVacuum()
        Log("reset all data", "#FF0000")
    }
    

    Nous n'exécutons que des contrats perpétuels, donc l'écriture est fixée ici et réglée sur perpétuel seulement.

    exchange.SetContractType("swap")
    

    Ensuite, nous devons également considérer l'exactitude du prix de l'ordre et du montant de l'ordre. Si l'exactitude n'est pas correctement définie, l'exactitude sera perdue pendant le processus de calcul de la stratégie. Si les données ont un grand nombre de décimales, il est facile de faire rejeter l'ordre par l'interface d'échange.

    exchange.SetPrecision(pricePrecision, amountPrecision)
    Log("set precision", pricePrecision, amountPrecision)
    

    Récupération de données simple par conception

    if (totalEq == -1 && !IsVirtual()) {
        var recoverTotalEq = _G("totalEq")
        if (!recoverTotalEq) {
            var currTotalEq = getTotalEquity()
            if (currTotalEq) {
                totalEq = currTotalEq
                _G("totalEq", currTotalEq)
            } else {
                throw "failed to obtain initial equity"
            }
        } else {
            totalEq = recoverTotalEq
        }
    }
    

    Si vous voulez spécifier le capital initial total du compte lorsque la stratégie est en cours d'exécution, vous pouvez définir le paramètretotalEq. Si ce paramètre est réglé sur -1, la stratégie lira les données de capital total stockées. S'il n'y a pas de données de capital total stockées, la valeur actuelle de capital total lu est utilisée comme le capital total initial de la stratégie en cours d'exécution. Après cela, une augmentation du capital total indique un profit et une diminution du capital total indique une perte. Si les données de capital total sont lues, la stratégie continuera à fonctionner avec ces données.

  • logique principale Après le travail initial, nous sommes finalement arrivés à la partie logique principale de la stratégie.

      while (1) {                                  // The main logic of the strategy is designed as an infinite loop
          var ticker = _C(exchange.GetTicker)      // Read the current market information first, mainly using the latest transaction price
          var pos = _C(exchange.GetPosition)       // Read current position data
          if (pos.length > 1) {                    // Judging the position data, because of the logic of this strategy, it is unlikely that long and short positions will appear at the same time, so if there are long and short positions at the same time, an error will be thrown
              Log(pos)
              throw "Simultaneous long and short positions"                  // Throw an error to stop the strategy
          }
          //Depends on status
          if (pos.length == 0) {                    // Make different operations according to the position status, when there is no position, pos.length == 0 
              // If you have not held a position, count the profit once
              if (!IsVirtual()) {
                  var currTotalEq = getTotalEquity()
                  if (currTotalEq) {
                      LogProfit(currTotalEq - totalEq, "current total equity:", currTotalEq)
                  }
              }
    
              buyOrderId = openLong(ticker.Last - targetProfit, amount)       // Open a buy order for a long position
              sellOrderId = openShort(ticker.Last + targetProfit, amount)     // Open a short sell order
          } else if (pos[0].Type == PD_LONG) {   // For long positions, the position and quantity of pending orders are different
              var n = 1
              var price = ticker.Last
              buyOrderId = openLong(price - targetProfit * n, amount)
              sellOrderId = coverLong(pos[0].Price + targetProfit, pos[0].Amount)
          } else if (pos[0].Type == PD_SHORT) {   // For short positions, the position and quantity of pending orders are different
              var n = 1
              var price = ticker.Last
              buyOrderId = coverShort(pos[0].Price - targetProfit, pos[0].Amount)
              sellOrderId = openShort(price + targetProfit * n, amount)
          }
    
          if (!sellOrderId || !buyOrderId) {   // If one side of the pending order fails, cancel all pending orders and start over
              cancelAll()
              buyOrderId = null 
              sellOrderId = null
              continue
          } 
    
          while (1) {  // The pending order is completed, start monitoring the order
              var isFindBuyId = false 
              var isFindSellId = false
              var orders = _C(exchange.GetOrders)
              for (var i = 0 ; i < orders.length ; i++) {
                  if (buyOrderId == orders[i].Id) {
                      isFindBuyId = true 
                  }
                  if (sellOrderId == orders[i].Id) {
                      isFindSellId = true 
                  }               
              }
              if (!isFindSellId && !isFindBuyId) {    // Detected that both buy and sell orders have been filled
                  cancelAll()
                  break
              } else if (!isFindBuyId) {   // Detected buy order closing
                  Log("buy order closing")
                  cancelAll()
                  break
              } else if (!isFindSellId) {  // Detected sell order closing
                  Log("sell order closing")
                  cancelAll()
                  break
              }
              LogStatus(_D())
              Sleep(3000)
          }
          Sleep(500)
      }
    

Toute la logique et le design sont expliqués.

Tests de retour

Laissez la stratégie passer par un marché du 19 mai.

img

img

On voit que la stratégie Martingale comporte encore certains risques.

Le vrai bot peut être exécuté avec le bot de simulation OKEX V5

Adresse stratégique:https://www.fmz.com/strategy/294957

Les stratégies sont principalement utilisées pour l'apprentissage, et l'argent réel doit être utilisé avec prudence~!


Relationnée

Plus de