Die Ressourcen sind geladen. Beförderung...

Konzeption einer Spot-Hedging-Strategie für Kryptowährungen (2)

Schriftsteller:FMZ~Lydia, Erstellt: 2022-07-19 15:19:52, Aktualisiert: 2023-09-24 19:34:38

img

Konzeption einer Spot-Hedging-Strategie für Kryptowährungen (2)

Im vorherigen Artikel haben wir gemeinsam eine einfache Absicherungsstrategie implementiert und dann werden wir lernen, wie wir diese Strategie aktualisieren können. Die Strategieänderungen sind nicht groß, aber die Details der Änderungen bedürfen Aufmerksamkeit.

Die Notwendigkeit, diese Strategie zu verbessern

  • Wechseln des Leverage-Modus für Spot-Austauschobjekte Diese Änderung bezieht sich nur auf den echten Bot. Einige Spot-Börsen haben Spot-Leverage-Schnittstellen, die auch auf FMZ eingekapselt sind. Für Exchange-Objekte, die direkt auf FMZ verpackt wurden und Spot-Leverage unterstützen, kann der Modus direkt gewechselt werden.
  • Hinzufügen von Spread-Chart-Anzeige Fügen Sie Spread-Chart-Anzeige, denn es ist nur die Zeichnung der Spread-Linie vonA exchange -> B exchange, B exchange -> A exchange, und die horizontale Linie zu zeichnen, die die Ausbreitung auslöst.line drawing class librarySie ist einfach zu bedienen, hier lernen wir auch, wie man dietemplate class libraryFunktion des FMZ.
  • Einseitige Absicherungsfunktion Diese Veränderung kann ziemlich signifikant sein, da es schwierig ist, die Preisdifferenz zwischen den beiden Börsen während bestimmter Absicherungstransaktionen vollständig umzukehren. Meistens ist der Preis an einer Börse konsequent höher als der Preis an einer anderen Börse. Zu diesem Zeitpunkt, wenn unsere Vermögenswerte vollständig abgesichert wurden (d. h. die Münzen sind alle an Börsen mit niedrigen Preisen und das Geld ist an Börsen mit hohen Preisen). Die Absicherung ist stagniert, und es ist nicht mehr möglich, sich auf die Schwankungen des Spreads zu verlassen, um Gewinn zu erzielen. Zu diesem Zeitpunkt müssen wir die Strategie so machen, dass Sie ein wenig Geld verlieren können, um die Münzen zurück abzusichern (lassen Sie die Münzen wieder an der Börse mit hohem Preis existieren), und wenn die Preisunterschied wieder größer wird, können wir weiter absichern und Gewinn machen.
  • Interaktive Modifizierung von Parametern wie Absicherungsspreadlinien Hinzufügen einer interaktiven Funktion zur Strategie, um die Auslöserlinie in Echtzeit zu ändern.
  • Organisieren von Statusleisteninformationen und Anzeigen in Tabellenformat Die Daten, die angezeigt werden müssen, sind für eine einfache Anzeige zu ordnen.

Als nächstes werden wir diese Entwürfe einzeln umsetzen.

Wechseln Sie den Leverage-Modus für Spot-Austauschobjekte

Nehmen Sie Binance Spot real bot als Beispiel, wechseln Sie zu Spot Hebelmodus, verwenden Sie den Codeexchanges[i].IO, geben Sie den Parameter eintrade_normalzur Umstellung auf Hebelposition nach Position und Eingabetrade_super_marginUm auf die volle Position zu wechseln, wird Backtesting nicht unterstützt.

Zu der Vorbereitungsphase zu Beginn dermainFunktion:

    // 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")
            }
        }
    }

Die Strategie hier fügt nur den Code zum Umschalten des Coin-to-coin-Leverage-Modus von Binance-Spot hinzu, so dass die Einstellung der Strategieparameter nur für Binance-Spot gültig ist.

Hinzugefügtes Spread-Chart

Es ist sehr einfach, die bereits verpackte Zeichnungsvorlage zu verwenden.Line Drawing LibrarySie kann direkt auf dem Strategie-Feld der FMZ-Plattform gesucht werden.

img

Oder klicken Sie direkt auf den Link:https://www.fmz.com/strategy/27293um auf die Kopie-Seite für diese Vorlage zu springen.

img

Klicken Sie auf die Schaltfläche, um diese Vorlage-Klassenbibliothek in Ihre eigene Strategiebibliothek zu kopieren.

img

Dann können Sie die zu verwendende Template-Klassenbibliothek in der Template-Spalte auf der Strategiebearbeitungsseite überprüfen. Speichern Sie die Strategie nach dem Überprüfen, und die Strategie wird auf diese Vorlage verweisen. Dies ist nur eine kurze Beschreibung der Verwendung der Template-Klassenbibliothek. Diese Strategie hat bereits auf diese Vorlage verwiesen, so dass es keine Notwendigkeit gibt, den Vorgang zu wiederholen. Wenn Sie diese Strategie im Strategiefeld kopieren, können Sie sehen, dassLine Drawing Librarywurde in der Vorlageleiste auf der Strategiebearbeitungsseite verwiesen.

Wir werden vor allem lernen, wie man die Funktionen derLine Drawing Libraryum ein Diagramm zu zeichnen.

img

Wir planen, die Ausbreitung vonA->B, die Verbreitung vonB->AWir müssen zwei Kurven (aktuelle A bis B, B bis A-Spread), zwei horizontale Linien (Trigger-Spread-Linie) ziehen, wie in der Abbildung oben gezeigt.

Weil wir eine einseitige Absicherung entwerfen wollen, die Auslöserlinien vonA->BundB->AWir können nicht den Entwurf im vorherigen Artikel verwenden. Im vorherigen Artikel:

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

Es gibt nur einen Auslöser.targetDiffPrice- Ich weiß. Hier müssen wir den Code transformieren, zuerst die Parameter.

img

Dann ändern Sie den 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
        }

Auf diese Weise hat sich die Differenz Triggerlinie von der vorherigen geänderttargetDiffPriceAuf zwei.targetDiffPriceA2B, targetDiffPriceB2A- Ich weiß. Der nächste Schritt besteht darin, diese Daten mit der Zeichnungslinie-Funktion der Zeichnungsbibliothek auf das Diagramm zu ziehen.

        // 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")

Wenn die Strategie läuft, gibt es ein Diagramm wie dieses.

img

Dann zeichnen Sie die Echtzeit-Spread-Kurve, um zu vermeiden, dass die Linie überzogen wird.

        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
        }

Auf diese Weise ist der Zeichnungscode nur 4 Zeilen, so dass die Strategie eine Grafik zur Laufzeit angezeigt wird.

Einseitige Absicherungsfunktion

Wie bereits erwähnt, wurde die Spread-Trigger-Linie in zwei geändert, die den Hedging-Trigger vonA->BundB->AAuf diese Weise kann der vorherige Bestellpreis-Algorithmus nicht verwendet werden, sondern stattdessen wird die Methode der Hinzufügung des Slippreises zum Marktpreis verwendet.

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

Da die Kauf- und Verkaufspreise in zwei Daten aufgeteilt sind, ist die AbsicherungsfunktionhedgeSie müssen auch geändert werden.

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

Es gibt auch einige kleinere Anpassungen, die auf diesen Änderungen basieren, die hier nicht wiederholt werden.

Interaktive Modifikation von Parametern wie zum Beispiel Absicherungsspreadlinien

Das ist die Konstruktionsanforderung einer halbautomatischen Strategie, die auch hier als Lehrdemonstration implementiert wird. Das Strategie-Interaktionsdesign ist ebenfalls sehr einfach.

img

Hinzugefügt zwei Steuerelemente, eine namens A2B und eine namens B2A. Nachdem Sie einen Wert in das Steuereingabefeld eingegeben haben, klicken Sie auf die Schaltfläche rechts vom Eingabefeld. Eine Anweisung wird sofort an die Strategie gesendet, zum Beispiel:123in der Eingabebox klicken Sie aufA2BSie werden sofort an die Strategie geschickt.

A2B:123

Entwerfen von interaktiven Erkennungs- und Verarbeitungskoden im Strategiecode.

        // 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])
                }
            }
        }

Organisieren von Statusleisteninformationen und Anzeigen in Tabellenformat

Die Datenanzeige in der Statusleiste besser organisiert und einfach zu beobachten.

        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

Zurückprüfung

Backtesting ist nur eine Teststrategie, eine vorläufige Erkennungsfunktion, und viele Fehler können tatsächlich in der Backtestphase getestet werden.

img

Strategie-Quellcode:https://www.fmz.com/strategy/302834


Verwandt

Mehr