Conception d'une stratégie de couverture au comptant de crypto-monnaie (2)

Auteur:Je ne sais pas., Créé: 2022-07-19 15:19:52, Mis à jour: 2023-09-24 19:34:38

img

Conception d'une stratégie de couverture au comptant des crypto-monnaies (2)

Dans l'article précédent, nous avons mis en œuvre une stratégie de couverture simple ensemble, et puis nous allons apprendre comment améliorer cette stratégie. Les changements de stratégie ne sont pas importants, mais les détails des changements nécessitent une attention particulière.

La nécessité d'améliorer cette stratégie

  • Modification du mode d'effet de levier de l'objet de change au comptant Ce changement n'est lié qu'au bot réel. Certains échanges au comptant ont des interfaces de levier au comptant, qui sont également encapsulées sur FMZ. Pour les objets d'échange qui ont été directement emballés sur FMZ et prennent en charge le levier au comptant, le mode peut être basculé directement.
  • Ajouter l' affichage du graphique de spread Ajoutez l'affichage du graphique des spreads, parce que c'est juste dessiner la ligne de spreads deA exchange -> B exchange, B exchange -> A exchange, et de tracer la ligne horizontale qui déclenche la propagation.line drawing class libraryL'avantage est qu'il est facile à utiliser, ici nous apprenons également à utiliser letemplate class libraryfonction de la FMZ.
  • Fonction de couverture unilatérale Ce changement peut être assez important, car il est difficile d'inverser complètement la différence de prix entre les deux bourses lors de transactions de couverture spécifiques. La plupart du temps, le prix sur une bourse est constamment plus élevé que le prix sur une autre bourse. À ce moment-là, si nos actifs ont été entièrement couverts (c'est-à-dire que les pièces sont toutes sur des échanges à bas prix et que l'argent est sur des échanges à prix élevés). La couverture est stagnante et il n'est plus possible de compter sur la fluctuation de l'écart pour réaliser un profit. À ce moment-là, nous devons faire la stratégie de sorte que vous puissiez perdre un peu d'argent pour couvrir les pièces (laissez les pièces exister à nouveau sur l'échange à prix élevé), et lorsque la différence de prix devient de nouveau plus grande, nous pouvons continuer à couvrir et à réaliser des bénéfices.
  • Modifier de manière interactive des paramètres tels que les lignes de couverture des spreads Ajoutez une fonction interactive à la stratégie pour modifier la ligne de déclenchement de la propagation en temps réel.
  • Organiser les informations de la barre d'état et les afficher sous forme de tableau Organisez les données qui doivent être affichées pour une visualisation facile.

Ensuite, mettons en œuvre ces conceptions une par une.

Modifier le mode d'effet de levier de l'objet de change au comptant

Prenez Binance spot vrai bot comme un exemple, passer à la place mode de levier, utiliser le codeexchanges[i].IO, entrez le paramètretrade_normalpour passer à l'effet de levier position par position et entréetrade_super_marginPour passer à la position de levier, le backtesting n'est pas pris en charge.

Ajouter à la phase de préparation au début de lamainfonction:

    // Switch leverage mode
    for (var i = 0 ; i < exchanges.length ; i++) {   // Traverse and detect all added exchange objects
        if (exchanges[i].GetName() == "Binance" && marginType != 0) {   //If the exchange object represented by the current i-index is Binance spot, and the parameter marginType of the strategy interface is not the option of "common currency", execute the switch operation
            if (marginType == 1) {
                Log(exchanges[i].GetName(), "Set to leveraged position-by-position")
                exchanges[i].IO("trade_normal")
            } else if (marginType == 2) {
                Log(exchanges[i].GetName(), "Set to leveraged full position")
                exchanges[i].IO("trade_super_margin")
            }
        }
    }

La stratégie ici n'ajoute que le code pour changer le mode d'effet de levier de pièce à pièce de Binance spot, de sorte que le réglage du commutateur sur les paramètres de la stratégie n'est valable que pour Binance spot.

Affichage du graphique de propagation ajouté

Il est très facile d'utiliser le modèle de dessin déjà enveloppé.Line Drawing LibraryIl peut être obtenu en effectuant une recherche directement sur la plateforme de stratégie FMZ.

img

Ou cliquez directement sur le lien:https://www.fmz.com/strategy/27293pour accéder à la page de copie de ce modèle.

img

Cliquez sur le bouton pour copier cette bibliothèque de classe de modèle dans votre propre bibliothèque de stratégie.

img

Ensuite, vous pouvez vérifier la bibliothèque de classe de modèle à utiliser dans la colonne de modèle sur la page d'édition de stratégie. Enregistrer la stratégie après la vérification, et la stratégie se référera à ce modèle. Ceci est juste une brève description de l'utilisation de la bibliothèque de classe de modèle. Cette stratégie a déjà fait référence à ce modèle, il n'y a donc pas besoin de répéter l'opération. Lorsque vous copiez cette stratégie dans le carré de stratégie, vous pouvez voir queLine Drawing Librarya fait l'objet d'une référence dans la barre de modèle de la page d'édition de stratégie.

Nous apprendrons principalement à utiliser les fonctions de laLine Drawing Librarypour dessiner un graphique.

img

Nous avons l'intention de dessiner la propagation deA->B, la diffusion deB->A, et la ligne de déclenchement de l'écart. nous devons dessiner deux courbes (actuel A à B, B à A écart), deux lignes horizontales (ligne de déclenchement de l'écart), comme indiqué dans la figure ci-dessus.

Parce que nous voulons concevoir une couverture unilatérale, les lignes de déclenchement deA->BetB->ANous ne pouvons pas utiliser le dessin de l'article précédent. Dans l'article précédent:

      var targetDiffPrice = hedgeDiffPrice
      if (diffAsPercentage) {
          targetDiffPrice = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentage
      }

Il n' y a qu' un seul déclencheurtargetDiffPriceJe suis désolée. Donc ici nous devons transformer le code, transformer les paramètres d'abord.

img

Puis modifiez le code:

        var targetDiffPriceA2B = hedgeDiffPriceA2B
        var targetDiffPriceB2A = hedgeDiffPriceB2A
        if (diffAsPercentage) {
            targetDiffPriceA2B = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentageA2B
            targetDiffPriceB2A = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentageB2A
        }

De cette façon, la différence ligne de déclenchement a changé de la précédentetargetDiffPriceÀ deux.targetDiffPriceA2B, targetDiffPriceB2AJe suis désolée. L'étape suivante consiste à dessiner ces données sur le graphique en utilisant la fonction de ligne de dessin de la bibliothèque de dessin de ligne.

        // drawing
        $.PlotHLine(targetDiffPriceA2B, "A->B")  // The first parameter of this function is the value of the horizontal line in the Y-axis direction, and the second parameter is the display text
        $.PlotHLine(targetDiffPriceB2A, "B->A")

Quand la stratégie est en cours d'exécution, il y a un graphique comme celui-ci.

img

Ensuite, tracez la courbe de propagation en temps réel, pour éviter de sur-tracer la ligne.

        if (ts - lastKeepBalanceTS > keepBalanceCyc * 1000) {
            nowAccs = _C(updateAccs, exchanges)
            var isBalance = keepBalance(initAccs, nowAccs, [depthA, depthB])
            cancelAll()
            if (isBalance) {
                lastKeepBalanceTS = ts
                if (isTrade) {
                    var nowBalance = _.reduce(nowAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
                    var initBalance = _.reduce(initAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
                    LogProfit(nowBalance - initBalance, nowBalance, initBalance, nowAccs)
                    isTrade = false 
                }                
            }

            $.PlotLine("A2B", depthA.Bids[0].Price - depthB.Asks[0].Price)  // Draw real-time spread curves
            $.PlotLine("B2A", depthB.Bids[0].Price - depthA.Asks[0].Price)  // The first parameter is the name of the curve, and the second parameter is the value of the curve at the current moment, that is, the value in the Y-axis direction at the current moment
        }

De cette façon, le code de dessin est de seulement 4 lignes, ce qui permet à la stratégie d'avoir un graphique affiché au moment de l'exécution.

Fonction de couverture unilatérale

Comme mentionné ci-dessus, la ligne de déclenchement du spread a été modifiée en deux, contrôlant le déclencheur de la couverture deA->BetB->ADe cette façon, l'algorithme du prix de commande précédent ne peut pas être utilisé, et la méthode d'addition du prix d'entrée au prix de marché est utilisée à la place.

        if (depthA.Bids[0].Price - depthB.Asks[0].Price > targetDiffPriceA2B && Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount) >= minHedgeAmount) {          // A -> B market conditions are met            
            var priceSell = depthA.Bids[0].Price - slidePrice
            var priceBuy = depthB.Asks[0].Price + slidePrice
            var amount = Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount)
            if (nowAccs[0].Stocks > minHedgeAmount && nowAccs[1].Balance * 0.8 / priceSell > minHedgeAmount) {
                amount = Math.min(amount, nowAccs[0].Stocks, nowAccs[1].Balance * 0.8 / priceSell, maxHedgeAmount)
                Log("trigger A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[1].Balance * 0.8 / priceSell, nowAccs[0].Stocks)  // Tips
                hedge(exB, exA, priceBuy, priceSell, amount)
                cancelAll()
                lastKeepBalanceTS = 0
                isTrade = true 
            }            
        } else if (depthB.Bids[0].Price - depthA.Asks[0].Price > targetDiffPriceB2A && Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount) >= minHedgeAmount) {   // B -> A market conditions are met
            var priceBuy = depthA.Asks[0].Price + slidePrice
            var priceSell = depthB.Bids[0].Price - slidePrice
            var amount = Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount)
            if (nowAccs[1].Stocks > minHedgeAmount && nowAccs[0].Balance * 0.8 / priceBuy > minHedgeAmount) {
                amount = Math.min(amount, nowAccs[1].Stocks, nowAccs[0].Balance * 0.8 / priceBuy, maxHedgeAmount)
                Log("trigger B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[0].Balance * 0.8 / priceBuy, nowAccs[1].Stocks)  //Tips
                hedge(exA, exB, priceBuy, priceSell, amount)
                cancelAll()
                lastKeepBalanceTS = 0
                isTrade = true 
            }            
        }

Comme les prix d'achat et de vente sont séparés en deux données, la fonction de couverturehedgeIl faut aussi modifier.

function hedge(buyEx, sellEx, priceBuy, priceSell, amount) {
    var buyRoutine = buyEx.Go("Buy", priceBuy, amount)
    var sellRoutine = sellEx.Go("Sell", priceSell, amount)
    Sleep(500)
    buyRoutine.wait()
    sellRoutine.wait()
}

Il y a aussi quelques ajustements mineurs basés sur ces changements, qui ne seront pas répétés ici.

Modifier de manière interactive des paramètres tels que les lignes de couverture des spreads

Ajouter une interaction à la stratégie, de sorte que la stratégie puisse modifier la ligne de déclenchement de la propagation en temps réel. La conception de l'interaction de stratégie est également très simple. Premièrement, ajoutez des contrôles d'interaction à la stratégie sur la page de modification de stratégie.

img

Ajout de deux commandes, l'une appelée A2B et l'autre appelée B2A. Après avoir entré une valeur dans la zone d'entrée de contrôle, cliquez sur le bouton à droite de la zone d'entrée. Une instruction sera envoyée à la stratégie immédiatement, par exemple: entrez la valeur123dans la zone d'entrée, cliquez surA2BUne instruction sera immédiatement envoyée à la stratégie.

A2B:123

Concevoir un code de détection et de traitement interactif dans le code de stratégie.

        // interact
        var cmd = GetCommand()   // Every time the loop is executed here, it checks whether there is an interactive command, and returns to an empty string if not.
        if (cmd) {               // An interactive command was detected, such as A2B:123
            Log("command received:", cmd)
            var arr = cmd.split(":")   // Split out the interactive control name and the value in the input box, arr[0] is A2B, arr[1] is 123
            if (arr[0] == "A2B") {     // Determine whether the triggered interactive control is A2B
                Log("Modify the parameters of A2B, ", diffAsPercentage ? "The parameter is the difference percentage" : "The parameter is the difference:", arr[1])
                if (diffAsPercentage) {
                    hedgeDiffPercentageB2A = parseFloat(arr[1])     // Modify the trigger spread line
                } else {
                    hedgeDiffPriceA2B = parseFloat(arr[1])          // Modify the trigger spread line
                }
            } else if (arr[0] == "B2A") {           // Triggered control detected is B2A     
                Log("Modify the parameters of B2A, ", diffAsPercentage ? "The parameter is the difference percentage" : "The parameter is the difference:", arr[1])
                if (diffAsPercentage) {
                    hedgeDiffPercentageA2B = parseFloat(arr[1])
                } else {
                    hedgeDiffPriceB2A = parseFloat(arr[1])
                }
            }
        }

Organiser les informations de la barre d'état et les afficher sous forme de table

Rendre l'affichage des données de la barre d'état plus organisé et facile à observer.

        var tbl = {
            "type" : "table", 
            "title" : "data", 
            "cols" : ["exchange", "coin", "freeze coin", "denominated currency", "freeze denominated currency", "trigger spread", "current spread"], 
            "rows" : [], 
        }
        tbl.rows.push(["A:" + exA.GetName(), nowAccs[0].Stocks, nowAccs[0].FrozenStocks, nowAccs[0].Balance, nowAccs[0].FrozenBalance, "A->B:" + targetDiffPriceA2B, "A->B:" + (depthA.Bids[0].Price - depthB.Asks[0].Price)])
        tbl.rows.push(["B:" + exB.GetName(), nowAccs[1].Stocks, nowAccs[1].FrozenStocks, nowAccs[1].Balance, nowAccs[1].FrozenBalance, "B->A:" + targetDiffPriceB2A, "B->A:" + (depthB.Bids[0].Price - depthA.Asks[0].Price)])

        LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")

img

Tests de retour

Le backtesting n'est qu'une stratégie de test, une fonction de détection préliminaire, et de nombreux bugs peuvent être testés au stade du backtesting en fait.

img

Le code source de la stratégie:https://www.fmz.com/strategy/302834


Relationnée

Plus de