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.
A exchange -> B exchange
, B exchange -> A exchange
, und die horizontale Linie zu zeichnen, die die Ausbreitung auslöst.line drawing class library
Sie ist einfach zu bedienen, hier lernen wir auch, wie man dietemplate class library
Funktion des FMZ.Als nächstes werden wir diese Entwürfe einzeln umsetzen.
Nehmen Sie Binance Spot real bot als Beispiel, wechseln Sie zu Spot Hebelmodus, verwenden Sie den Codeexchanges[i].IO
, geben Sie den Parameter eintrade_normal
zur Umstellung auf Hebelposition nach Position und Eingabetrade_super_margin
Um auf die volle Position zu wechseln, wird Backtesting nicht unterstützt.
Zu der Vorbereitungsphase zu Beginn dermain
Funktion:
// 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.
Es ist sehr einfach, die bereits verpackte Zeichnungsvorlage zu verwenden.Line Drawing Library
Sie kann direkt auf dem Strategie-Feld der FMZ-Plattform gesucht werden.
Oder klicken Sie direkt auf den Link:https://www.fmz.com/strategy/27293um auf die Kopie-Seite für diese Vorlage zu springen.
Klicken Sie auf die Schaltfläche, um diese Vorlage-Klassenbibliothek in Ihre eigene Strategiebibliothek zu kopieren.
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 Library
wurde in der Vorlageleiste auf der Strategiebearbeitungsseite verwiesen.
Wir werden vor allem lernen, wie man die Funktionen derLine Drawing Library
um ein Diagramm zu zeichnen.
Wir planen, die Ausbreitung vonA->B
, die Verbreitung vonB->A
Wir 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->B
undB->A
Wir 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.
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änderttargetDiffPrice
Auf 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.
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.
Wie bereits erwähnt, wurde die Spread-Trigger-Linie in zwei geändert, die den Hedging-Trigger vonA->B
undB->A
Auf 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 Absicherungsfunktionhedge
Sie 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.
Das ist die Konstruktionsanforderung einer halbautomatischen Strategie, die auch hier als Lehrdemonstration implementiert wird. Das Strategie-Interaktionsdesign ist ebenfalls sehr einfach.
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:123
in der Eingabebox klicken Sie aufA2B
Sie 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])
}
}
}
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) + "`")
Backtesting ist nur eine Teststrategie, eine vorläufige Erkennungsfunktion, und viele Fehler können tatsächlich in der Backtestphase getestet werden.
Strategie-Quellcode:https://www.fmz.com/strategy/302834