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

Auteur:Je suis désolée., Créé: 2022-04-12 17:50:07, mis à jour: 2022-04-12 18:06:07

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

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

Dans cet article, nous expliquons principalement et apprenons de la conception des stratégies de type Martingale.

Obtenir une participation totale

L'équité totale est souvent utilisée lors de la conception d'une stratégie à terme de crypto-monnaie, car nous voulons calculer les bénéfices, en particulier lorsque nous devons calculer les bénéfices flottants.exchange.GetAccount()En fait, la plupart des plateformes de contrats à terme de crypto-monnaie fournissent les données du capital total, mais cette propriété n'est pas uniformément regroupée sur FMZ.

Par conséquent, nous concevons séparément des fonctions pour obtenir les données selon différentes plateformes:

// OKEX V5 obtains the 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("Fail to obtain the total equity of the account!")
            return null
        }
    }
    return totalEquity
}

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

LetotalEquitydans le code est la valeur totale dont nous avons besoin. puis nous écrivons une fonction comme l'entrée d'invocation, et appeler la fonction correspondante selon le nom de la plate-forme.

function getTotalEquity() {
    var exName = exchange.GetName()
    if (exName == "Futures_OKCoin") {
        return getTotalEquity_OKEX_V5()
    } else if (exName == "Futures_Binance") {
        return getTotalEquity_Binance()
    } else {
        throw "Do not support the platform"
    }
}

Conception de plusieurs fonctions auxiliaires

Avant de concevoir la fonction principale et la logique principale, nous devons également concevoir quelques fonctions auxiliaires pour la préparation.

  • 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)
        }
    }
    

    On pense que cette fonction est familière à ceux qui lisent souvent le code de l'exemple de stratégie sur le carré de stratégie FMZ, et de nombreuses stratégies ont utilisé la conception similaire.

  • L'opération consistant à placer des ordres à 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: position ouverte longue (openLong), position ouverte courte (openShort), position longue fermée (coverLong) et position fermée courte (coverShort). Par conséquent, nous avons conçu quatre fonctions d'ordre pour correspondre à ces opérations.

    Nous avons aussi conçu une fonction appelée:tradepour gérer l'opération lorsquedirection (distance), order price (price)etorder amount (amount)sont spécifiées.

    Les appels à la fonction des positions longues ouvertes (openLong), des positions courtes ouvertes (openShort), des positions longues fermées (coverLong) et des positions courtes fermées (coverShort) sont finalement complétés par letradeLa fonction, c'est-à-dire, selon la direction, le prix et le montant spécifiés, placer des ordres dans les plateformes à terme.

Fonction principale

L'idée de la stratégie est très simple; prendre le prix actuel comme la ligne de base, et à une certaine distance au-dessus et en dessous de la ligne de base pour placer des ordres de vente (short) et des ordres d'achat (long).

  • Travaux initiaux Pour que nous voulons des commandes en attente, nous avons besoin de deux variables pour enregistrer l'ID de commande.

    var buyOrderId = null
    var sellOrderId = null
    

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

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

    L'option de réinitialisation de toutes les informations est également conçue dans les paramètres de stratégie, donc un certain traitement doit être effectué 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 ici nous l'écrivons dans une boucle infinie, et nous le définissons uniquement sur le contrat perpétuel.

    exchange.SetContractType("swap")
    

    En outre, nous devons considérer les problèmes de précision du prix de l'ordre et du montant de l'ordre. Si la précision n'est pas réglée correctement, elle 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 de la plateforme.

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

    La simple fonction de récupération de données dans la conception

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

    Si vous voulez spécifier le capital total initial du compte lors de l'exécution de la stratégie, 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, le capital total actuellement lu est utilisé comme capital total initial dans la stratégie en cours d'exécution. Plus tard, si le capital total augmente, cela signifie qu'il a gagné un profit; si le capital total diminue, cela signifie qu'il y a une perte. Si les données de capital total sont lues, utilisez les données pour continuer à fonctionner.

  • La 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, in which we mainly use the latest trading price
          var pos = _C(exchange.GetPosition)       // read the current position data 
          if (pos.length > 1) {                    // judge the position data; due to the strategy logic, it is unlikely to have long and short positions at the same time, so if there are long and short positions at the same time, an error will be thrown
              Log(pos)
              throw "concurrently with long and short positions"                  // raise an error, and stop the strategy 
          }
          // according to the status 
          if (pos.length == 0) {                    // according to the position status, make different operations; if pos.length == 0, it means currently no position
              // when there is no position yet, calculate the equity 
              if (!IsVirtual()) {
                  var currTotalEq = getTotalEquity()
                  if (currTotalEq) {
                      LogProfit(currTotalEq - totalEq, "Current total equity:", currTotalEq)
                  }
              }
    
              buyOrderId = openLong(ticker.Last - targetProfit, amount)       // pend buy order of open long position 
              sellOrderId = openShort(ticker.Last + targetProfit, amount)     // pend sell order of open short position
          } else if (pos[0].Type == PD_LONG) {   // there are long positions; pending position and amount are 
              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) {   // there are short positions; pending position and amount 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 opending orders of one side fails, cancel all pending orders and try again 
              cancelAll()
              buyOrderId = null 
              sellOrderId = null
              continue
          } 
    
          while (1) {  // finish pending the order, and start to monitor 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) {    // both buy order and sell order are detected to be executed 
                  cancelAll()
                  break
              } else if (!isFindBuyId) {   // a buy order execution is detected 
                  Log("buy order executed")
                  cancelAll()
                  break
              } else if (!isFindSellId) {  // a sell order execution is detected 
                  Log("sell order executed")
                  cancelAll()
                  break
              }
              LogStatus(_D())
              Sleep(3000)
          }
          Sleep(500)
      }
    

Toute la logique et la conception sont alors complètement expliquées.

Test de retour

Laissez la stratégie traverser les cotations du marché le 19 mai 2021.

img

img

Comme nous pouvons le voir, la stratégie similaire à la stratégie de Martingale comporte encore certains risques.

Le bot test peut utiliser le bot simulé OKEX V5 pour exécuter

img

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

La stratégie est principalement utilisée pour l'étude, alors n'utilisez pas la stratégie dans un vrai bot!


Plus de