Stratégie de couverture au comptant des crypto-monnaies (2)

Auteur:Je suis désolée., Créé à: 2022-04-14 16:17:46, mis à jour à: 2022-04-15 14:16:23

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 la stratégie. Il n'y a pas beaucoup de modifications dans la stratégie, mais les détails des modifications nécessitent une attention particulière.

Exigences relatives à l'amélioration de la stratégie

  • Modifier le mode de marge des objets d'échange spot La modification n'est liée qu'au bot. Certaines plateformes spot ont des interfaces de marge spot, qui sont également encapsulées sur FMZ. Pour les objets d'échange qui sont directement encapsulés sur FMZ et supportent la marge spot, vous pouvez directement basculer le mode.
  • Ajouter plus d'affichage de graphique de propagation Pour ajouter plus d'affichage de graphique de propagation, et nous ne traçons les courbes de propagation deA->BetB->A, ainsi que les lignes de déclenchement horizontales, nous pouvons utiliser directement lechart plot library; l'avantage est la simplicité et la facilité d'utilisation.template library together.
  • Fonction de la couverture à un seul côté Cette modification est relativement importante, car il est difficile d'inverser complètement l'écart de prix entre les deux plates-formes pendant le trading de couverture spécifique. La plupart du temps, le prix sur une plate-forme est constamment plus élevé que le prix sur une autre plate-forme. À ce moment-là, si nos actifs ont été entièrement couverts (c'est-à-dire que tous les symboles de devises sont dans la plate-forme avec les prix les plus bas, et les actifs sont tous dans la plate-forme avec les prix les plus élevés). La couverture est stagnante, et il n'est plus possible de dépendre de la volatilité de l'écart pour réaliser un profit. À ce moment-là, vous devez faire la stratégie de couverture et de retourner les symboles de devises en perdant seulement une petite quantité d'actifs (laissez les symboles de devises revenir à la plate-forme avec les prix plus élevés à nouveau).
  • Modifier de manière interactive des paramètres tels que la ligne de couverture
    Ajouter la fonction interactive à la stratégie, afin de modifier la ligne de déclenchement de la propagation en temps réel.
  • Gérer les informations de la barre d'état et les afficher au format de table Organiser et gérer les données qui doivent être affichées, pour une observation pratique.

Ensuite, réalisons ces idées de conception une par une.

Modifier le mode de marge des objets d'échange

Prenez Binance spot bot comme exemple. Pour passer au mode de marge au comptant, utiliser le codeexchanges[i].IO, importez le paramètretrade_normalde passer à la marge isolée et d'importertrade_super_marginpour passer à la marge croisée, qui n'est pas prise en charge dans le backtest.

Dans la préparation au début de lamainfonction, ajouter:

    // switch the margin mode 
    for (var i = 0 ; i < exchanges.length ; i++) {   // traverse and detect all exchange objects added
        if (exchanges[i].GetName() == "Binance" && marginType != 0) {   // if the exchange object represented by the current index i is Binance Spot, and the parameter marginType on the strategy interface is not selected as the "common spot" option, execute the switch
            if (marginType == 1) {
                Log(exchanges[i].GetName(), "set to isolated margin")
                exchanges[i].IO("trade_normal")
            } else if (marginType == 2) {
                Log(exchanges[i].GetName(), "set to cross margin")
                exchanges[i].IO("trade_super_margin")
            }
        }
    }

La stratégie ici n'ajoute que le code pour changer le mode de marge au comptant de Binance Spot, donc le réglage du commutateur dans les paramètres de stratégie ne fonctionne que pour Binance Spot.

Ajouter plus d'affichage de graphique de propagation

L'utilisation des modèles de traçage encapsulés est très simple.chart plot LibraryVous pouvez le rechercher directement sur la plateforme Square of FMZ.

img

Ou vous pouvez directement cliquer sur le lien:https://www.fmz.com/strategy/27293pour passer à la page de copie du modèle.

img

Cliquez sur le bouton et vous pouvez facilement copier le modèle dans votre propre bibliothèque de stratégie.

img

Ensuite, sur la page d'édition de stratégie, vous pouvez vérifier la bibliothèque de modèle à utiliser dans la colonne de modèle. Enregistrer la stratégie après la vérification, et la stratégie utilisera ce modèle. Ceci est juste une brève description de l'utilisation de la bibliothèque de modèle. Puisque la stratégie a déjà fait référence à ce modèle, il n'est pas nécessaire de répéter l'opération. Lorsque vous copiez le code de stratégie dans Square, vous pouvez voir quechart plot Librarya été référencé dans la barre de modèle de la page d'édition de stratégie.

Ici, nous apprenons principalement à utiliser les fonctions duchart plot librarypour comploter.

img

Nous prévoyons de tracer les écarts deA->BetB->ANous devons tracer deux courbes (actuellement, les spreads de A à B et de B à A), et deux lignes horizontales (lignes de déclenchement des spreads), comme indiqué sur la figure ci-dessus.

Parce que nous voulons concevoir une haie à un seul côté, les lignes de déclenchement deA->BetB->ANous ne pouvons pas utiliser la conception 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' une seule propagation activée.targetDiffPriceJe suis désolée. Par conséquent, ici nous devons modifier le code, et nous devons modifier les paramètres d'abord.

img

modifier 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
        }

Ainsi, la ligne de déclenchement de la propagation a changé de la précédentetargetDiffPriceà deux, à savoirtargetDiffPriceA2BettargetDiffPriceB2AJe suis désolée. Ensuite, vous pouvez utiliser la fonction de traçage de graphiques de la bibliothèque de graphiques pour dessiner les données sur le graphique.

        // plot
        $.PlotHLine(targetDiffPriceA2B, "A->B")  // the first parameter of the 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")

Lorsque la stratégie est exécutée, le graphique sera affiché comme ceci.

img

Ensuite, tracez la courbe des écarts en temps réel; afin d'éviter de trop tracer, placez le code qui trace les courbes des écarts en temps réel dans la détection du solde. s

        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)  // plot real-time spread curves
            $.PlotLine("B2A", depthB.Bids[0].Price - depthA.Asks[0].Price)  // the first parameter is the curve name, and the second parameter is the curve value at the current moment, that is, the value in the Y-axis direction at the current moment
        }

Le code de traçage n'a besoin que de 4 lignes pour permettre la stratégie avec un affichage de graphique pendant l'exécution.

Fonction de la haie à un seul côté

Comme mentionné ci-dessus, le nombre de lignes de déclenchement du spread a été modifié en deux, qui contrôlent respectivement 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 de glissement au prix du 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 condition satisfied             
            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("triggerA->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[1].Balance * 0.8 / priceSell, nowAccs[0].Stocks)  // prompt message
                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 condition satisfied 
            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("triggerB->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[0].Balance * 0.8 / priceBuy, nowAccs[1].Stocks)  // prompt message
                hedge(exA, exB, priceBuy, priceSell, amount)
                cancelAll()
                lastKeepBalanceTS = 0
                isTrade = true 
            }            
        }

Comme les prix d'achat et de vente sont divisés en deux parties de données, leshedgeLa fonction doit également être modifiée.

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 modifications, qui ne seront pas décrits ici.

Modifier de manière interactive des paramètres tels que la ligne de couverture

Ajouter de l'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 commandes interactives à la stratégie sur la page de modification de stratégie.

img

Il y avait deux commandes ajoutées, 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 commande sera envoyée à la stratégie immédiatement, par exemple: entrer la valeur123dans la zone d'entrée, cliquez surA2Ble bouton, et une commande sera envoyée à la stratégie immédiatement.

A2B:123

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

        // interaction 
        var cmd = GetCommand()   // every time when the loop is operated here, it will detect whether an interactive command is sent; if no, return null string 
        if (cmd) {               // interactive command detected, such as A2B:123
            Log("received command:", cmd)
            var arr = cmd.split(":")   // split out the interactive control name and the value in the input box; arr[0] means A2B, and arr[1] means 123
            if (arr[0] == "A2B") {     // judge whether the triggered interactive control is A2B
                Log("modify parameterA2B,", diffAsPercentage ? "parameter of spread ratio:" : "parameter of spread:", arr[1])
                if (diffAsPercentage) {
                    hedgeDiffPercentageB2A = parseFloat(arr[1])     // modify the spread trigger line 
                } else {
                    hedgeDiffPriceA2B = parseFloat(arr[1])          // modify the spread trigger line 
                }
            } else if (arr[0] == "B2A") {           // detected the triggered control is B2A 
                Log("modify parameterB2A,", diffAsPercentage ? "parameter of spread ratio:" : "parameter of spread:", arr[1])
                if (diffAsPercentage) {
                    hedgeDiffPercentageA2B = parseFloat(arr[1])
                } else {
                    hedgeDiffPriceB2A = parseFloat(arr[1])
                }
            }
        }

Gérer les informations de la barre d'état et les afficher au format de table

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

        var tbl = {
            "type" : "table", 
            "title" : "data", 
            "cols" : ["platform", "Currency", "frozenCurrrency", "quoteCurrency", "frozenQuoteCurrency", "triggerSpread", "currentSpread"], 
            "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

Test de retour

Le backtest n'est qu'un test de la stratégie, en tant que fonction de détection préliminaire. De nombreux bugs peuvent en fait être testés au stade du backtest. Il n'est pas nécessaire de se soucier trop des résultats du backtest. Finalement, la stratégie doit encore être testée dans l'environnement réel avec de vrais bots.

img

img

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


Plus de