Conception d'une stratégie de couverture de la monnaie numérique (2)

Auteur:Le petit rêve, Créé: 2021-07-30 16:36:48, Mis à jour: 2023-09-20 10:36:43

img

Conception d'une stratégie de couverture de la monnaie numérique (2)

Dans l'article précédent, nous avons mis en place une stratégie de couverture simple et nous avons appris comment l'améliorer. Les changements de stratégie ne seront pas importants, mais les détails des changements méritent d'être pris en compte.

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

  • Modifier le mode d'effet de levier de l'objet de l'échange Cette modification concerne uniquement le disque réel, et certaines transactions en direct ont toutes les interfaces de levier en direct, qui sont également enveloppées sur FMZ.
  • Le graphique de différence d'augmentation L'augmentation de la différence graphique montre parce que c'est juste un dessinA交易所->B交易所B交易所->A交易所Nous utilisons directement les lignes horizontales qui déclenchent les différences.画线类库L'avantage est que c'est simple et facile à utiliser.模版类库Les fonctionnalités.
  • Fonction de couverture unilatérale Ce changement est considérable, car il est difficile de faire un renversement complet des différences entre les deux échanges lors d'une transaction de couverture spécifique. La plupart du temps, le prix d'un échange reste supérieur à celui de l'autre. À ce moment-là, si nos actifs sont tous couverts (c'est-à-dire que les pièces sont sur les échanges à bas prix et l'argent sur les échanges à haut prix), le couvert est stagnant et ne peut plus dépendre des bénéfices fluctuants des différences.
  • Paramètres tels que les lignes de différence de couverture modifiées en interaction L'ajout de fonctionnalités d'interaction aux stratégies permet de modifier en temps réel les déclencheurs de la différence.
  • Sortir les informations du panneau d'état, en utilisant le formulaire Les données à afficher doivent être organisées pour être faciles à observer.

Nous allons ensuite les mettre en œuvre une par une.

Modifier le mode d'effet de levier de l'objet de l'échange

Utiliser le code pour passer au mode d'effet de levier en temps réel en utilisant le disque réel en bitcoinsexchanges[i].IO, les paramètres de transmissiontrade_normalLe jeu est basé sur le jeu d'échecs.trade_super_marginCommutation à plein levier, retouche non prise en charge. Ceci n'est utilisé que lors d'un jeu réel.

DansmainL'augmentation de la phase de préparation au début de la fonction:

    // 切换杠杆模式
    for (var i = 0 ; i < exchanges.length ; i++) {   // 遍历检测所有添加的交易所对象
        if (exchanges[i].GetName() == "Binance" && marginType != 0) {   // 如果当前i索引代表的交易所对象是币安现货,并且策略界面参数marginType选择的不是「普通币币」选项,执行切换
            if (marginType == 1) {
                Log(exchanges[i].GetName(), "设置为杠杆逐仓")
                exchanges[i].IO("trade_normal")
            } else if (marginType == 2) {
                Log(exchanges[i].GetName(), "设置为杠杆全仓")
                exchanges[i].IO("trade_super_margin")
            }
        }
    }

La stratégie n'est que l'ajout d'un code pour le mode d'effet de levier de change pour les devises en espèces, de sorte que le paramètre de la stratégie pour le changement est valable uniquement pour les devises en espèces.

Le graphique de différence d'augmentation

Il est très simple d'utiliser un modèle de dessin déjà emballé.画线类库Vous pouvez le trouver directement sur la plateforme FMZ Strategy Square.

img

Vous pouvez également cliquer sur le lien suivant:https://www.fmz.com/strategy/27293Le site Web de l'organisation est disponible en anglais, en espagnol et en espagnol.

img

En cliquant sur le bouton, vous pouvez copier cette bibliothèque de modèles dans votre propre bibliothèque de stratégies.

img

Ensuite, sur la page d'édition de la stratégie, vous pouvez cocher la bibliothèque de modèles dont vous avez besoin dans la barre de modèle. Après avoir coché la barre de modèle, la stratégie de sauvegarde fait référence à ce modèle. Ceci est une simple explication de l'utilisation de la bibliothèque de modèles, la stratégie a déjà fait référence à ce modèle, vous n'avez donc pas à répéter l'opération.画线类库Il y a eu des références à ce sujet.

Nous avons appris à l'utiliser.画线类库La fonction de tracer un diagramme.

img

Nous avons prévuA->BLe prix de l'électricité est en baisse.B->AIl est nécessaire de tracer deux courbes (les différences actuelles A à B et B à A) et deux lignes horizontales (les différences déclenchées), comme dans la figure ci-dessus.

Il y a une différence entre les deux types de couverture.A->BetB->ALe dessin de la ligne de déclenchement est différent. 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 différence.targetDiffPriceJe ne sais pas. Donc ici, nous allons modifier le code, nous allons modifier les paramètres d'abord.

img

Le code a été modifié:

        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
        }

Le prix de l'électricité a augmenté de plus en plus depuis le début de l'année.targetDiffPriceUne est devenue deux.targetDiffPriceA2BtargetDiffPriceB2AJe ne sais pas. Ensuite, vous pouvez utiliser la fonction de tracer des lignes dans la bibliothèque de lignes pour tracer cette donnée sur le graphique.

        // 画图
        $.PlotHLine(targetDiffPriceA2B, "A->B")  // 该函数第一个参数是水平线在Y轴方向上的值,第二个参数是显示文本
        $.PlotHLine(targetDiffPriceB2A, "B->A")

Le graphique suivant montre que la stratégie fonctionne.

img

Ensuite, une courbe de différenciation en temps réel est dessinée, afin d'éviter une courbe excessive. Le code de la courbe des données de différenciation en temps réel est placé dans le test d'équilibre.

        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)  // 画实时差价曲线
            $.PlotLine("B2A", depthB.Bids[0].Price - depthA.Asks[0].Price)  // 第一个参数是曲线名称,第二个参数是曲线当前时刻的值,即当前时刻Y轴方向上的值
        }

Cela permet d'afficher des graphiques à l'exécution, avec seulement 4 lignes de code.

Fonction de couverture unilatérale

Dans l'article ci-dessus, il est mentionné que la ligne de déclenchement de la différence a été transformée en deux lignes, contrôlées séparément.A->BLe gouvernement a décidé d'arrêter les opérations de détournement.B->ALe prix de l'offre est alors supprimé et le prix de l'offre est réduit.

        if (depthA.Bids[0].Price - depthB.Asks[0].Price > targetDiffPriceA2B && Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount) >= minHedgeAmount) {          // A -> B 盘口条件满足            
            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("触发A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[1].Balance * 0.8 / priceSell, nowAccs[0].Stocks)  // 提示信息
                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 盘口条件满足
            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("触发B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[0].Balance * 0.8 / priceBuy, nowAccs[1].Stocks)  // 提示信息
                hedge(exA, exB, priceBuy, priceSell, amount)
                cancelAll()
                lastKeepBalanceTS = 0
                isTrade = true 
            }            
        }

Et puis comme le prix d'achat est divisé en deux données, nous avons une fonction de couverture.hedgeIl faut aussi que ce soit modifié.

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 des ajustements mineurs basés sur ces modifications, qui ne sont pas présentés ici, mais vous pouvez voir le code spécifique.

Paramètres tels que les lignes de différence de couverture modifiées en interaction

L'augmentation de l'interaction avec les stratégies permet de modifier en temps réel les déclencheurs de la différence. La conception de l'interaction des stratégies est également très simple, d'abord en ajoutant des contrôles d'interaction à la stratégie sur la page d'édition de la politique.

img

Deux contrôles ont été ajoutés, l'un appelé A2B et l'autre appelé B2A. Après avoir entré une valeur dans la zone d'entrée du contrôle, cliquez sur le bouton d'entrée à droite. Une instruction est immédiatement envoyée à la stratégie, par exemple: entrez une valeur dans la zone d'entrée.123Cliquez ici.A2BCe bouton envoie immédiatement des instructions à la politique.

A2B:123

Détection d'interactions et traitement de code par conception dans le code stratégique.

        // 交互
        var cmd = GetCommand()   // 每次循环执行到这里时,都检测有没有交互指令过来,没有则返回空字符串
        if (cmd) {               // 检测到有交互指令,例如:A2B:123
            Log("接收到命令:", cmd)
            var arr = cmd.split(":")   // 拆分出交互控件名称和输入框中的值,arr[0]就是A2B,arr[1]就是123
            if (arr[0] == "A2B") {     // 判断触发的交互控件是不是A2B
                Log("修改A2B的参数,", diffAsPercentage ? "参数为差价百分比" : "参数为差价:", arr[1])
                if (diffAsPercentage) {
                    hedgeDiffPercentageB2A = parseFloat(arr[1])     // 修改触发差价线
                } else {
                    hedgeDiffPriceA2B = parseFloat(arr[1])          // 修改触发差价线
                }
            } else if (arr[0] == "B2A") {           // 检测到触发的控件是B2A     
                Log("修改B2A的参数,", diffAsPercentage ? "参数为差价百分比" : "参数为差价:", arr[1])
                if (diffAsPercentage) {
                    hedgeDiffPercentageA2B = parseFloat(arr[1])
                } else {
                    hedgeDiffPriceB2A = parseFloat(arr[1])
                }
            }
        }

Sortir les informations de la barre d'état, en utilisant le formulaire

Pour que les données de la barre d'état soient plus ordonnées et plus faciles à observer.

        var tbl = {
            "type" : "table", 
            "title" : "数据", 
            "cols" : ["交易所", "币", "冻结币", "计价币", "冻结计价币", "触发差价", "当前差价"], 
            "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

Réécriture

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

img

img

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


Relationnée

Plus de

15570686905La stratégie de transaction est d'ajouter les fonctions de contrat, et c'est bien, d'ajouter les contrats permanents, les contrats de taux de change.

Des nuages légersTypeError: Cannot read property 'SetPrecision' of undefined (Erreur de type: Impossible de lire la propriété 'SetPrecision' d'un fichier non défini) Stratégie de couverture de la trésorerie par devises différentes Ver 1.1

Le petit rêveBon, j'ai une chance de faire une leçon.

Des nuages légersC'est clair, merci beaucoup.

Le petit rêveIl faut ajouter deux objets d'échange.