Strategieanalyse von LeeksReaper (2)

Schriftsteller:Lydia., Erstellt: 2022-11-07 16:38:41, Aktualisiert: 2023-09-15 21:07:34

img

Strategieanalyse von LeeksReaper (2)

Lassen Sie uns den Inhalt des letzten Kapitels weiter erläutern (https://www.fmz.com/bbs-topic/9725).

Die dritte zusätzliche Funktion:

    self.balanceAccount = function() {
        var account = exchange.GetAccount()
        if (!account) {
            return
        }
        self.account = account
        var now = new Date().getTime()
        if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)) {
            self.preCalc = now
            var net = _N(account.Balance + account.FrozenBalance + self.orderBook.Bids[0].Price * (account.Stocks + account.FrozenStocks))
            if (net != self.preNet) {
                self.preNet = net
                LogProfit(net)
            }
        }
        self.btc = account.Stocks
        self.cny = account.Balance
        self.p = self.btc * self.prices[self.prices.length-1] / (self.btc * self.prices[self.prices.length-1] + self.cny)
        var balanced = false
        
        if (self.p < 0.48) {
            Log ( \"\" Start Balance \"\", self. P)
            self.cny -= 300
            if (self.orderBook.Bids.length >0) {
                exchange.Buy(self.orderBook.Bids[0].Price + 0.00, 0.01)
                exchange.Buy(self.orderBook.Bids[0].Price + 0.01, 0.01)
                exchange.Buy(self.orderBook.Bids[0].Price + 0.02, 0.01)
            }
        } else if (self.p > 0.52) {
            Log ( \"\" Start Balance \"\", self. P)
            self.btc -= 0.03
            if (self.orderBook.Asks.length >0) {
                exchange.Sell(self.orderBook.Asks[0].Price - 0.00, 0.01)
                exchange.Sell(self.orderBook.Asks[0].Price - 0.01, 0.01)
                exchange.Sell(self.orderBook.Asks[0].Price - 0.02, 0.01)
            }
        }
        Sleep(BalanceTimeout)
        var orders = exchange.GetOrders()
        if (orders) {
            for (var i = 0; i < orders.length; i++) {
                if (orders[i].Id != self.tradeOrderId) {
                    exchange.CancelOrder(orders[i].Id)
                }
            }
        }
    }

Wenn der KonstrukteurLeeksReaper ()Konstruiert ein Objekt, diebalanceAccount ()Funktion, die dem Objekt hinzugefügt wird, aktualisiert die in der Konto-Aktivausgabe gespeicherten Informationen.self.account, d. h. dieaccountBerechnen Sie den Umsatzwert und drucken Sie ihn rechtzeitig. Berechnen Sie dann nach den aktuellen Kontovermögensdaten die Spot-Währungsbilanzquote (Spot-Positionsbilanz), schließen Sie die Position mit einer kleinen Bestellung, damit die Währung (Position) wieder in den Gleichgewichtszustand zurückkehrt. Warten Sie eine gewisse Zeit, um zu handeln, dann stornieren Sie alle Maker, die nächste Runde der Ausführung der Funktion wird nach dem Gleichgewicht suchen und die entsprechende Verarbeitung erneut durchführen.

Schauen wir uns den Code dieser Funktion Satz für Satz an: Erstens, der erste Satz.var account = exchange.GetAccount ()erklärt eine lokale Variableaccountund ruft die Funktion vonexchange.GetAccountAuf FMZ API-Schnittstelle. Holen Sie sich die neuesten Daten des Girokontos und zuordnen Sie es an die VariableaccountDann beurteilen Sie die Variable.account. Wenn die Variable istnull(z.B. Timeout, Netzwerk, Exchange-Interface-Ausnahme usw.), wird es zurückkehren (entsprechendif (!account) {...}) direkt.

self.account = accountist die lokale Variable zuzuweisenaccountDieaccountAttribut des konstruierten Objekts zur Aufzeichnung der neuesten Kontoinformationen im konstruierten Objekt.

Var now = new Date().getTime ()erklärt eine lokale Variablenowund ruft diegetTime()Funktion des Zeitdatumsobjekts der JavaScript-Sprache, um den aktuellen Zeitstempel zurückzugeben.now.

if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)){...}bestimmt, dass, wenn die Differenz zwischen dem aktuellen Zeitstempel und dem Zeitstempel, der zuletzt aufgezeichnet wurde, den Parameter übersteigtCalcNet Interval * 1000, bedeutet, daß es seit dem letzten Mal aktualisiert wurde.CalcNetInterval * 1000in Millisekunden (CalcNetIntervalDer Preis für den Kauf eines Druckers wird für die Berechnung des Einkommens verwendet.self.orderBook.Bids.length > 0ist auch in der Bedingung definiert (Tiefe Daten, es muss gültige Ebene Informationen in der Reihenfolge Liste).self.PreCalc = nowwird ausgeführt, um die Zeitstempelvariable der zuletzt gedruckten Rückkehr zu aktualisierenself.preCalcbis zum aktuellen ZeitstempelnowHier wird die Berechnungsmethode des Nettovermögens für die Renditestatistik verwendet.var net = _N(account.Balance + account.FrozenBalance + self.orderBook.Bids[0].Price * (account.Stocks + account.FrozenStocks)), d. h. die Währung in Geld (in Währung) umwandeln, entsprechend dem aktuellen Kaufpreis, und sie dann dem Geldbetrag auf dem Konto hinzufügen und der angegebenen lokalen Variablen zuordnennetBeurteilen Sie, ob der aktuelle Gesamtnettowert mit dem letztmalig erfassten Gesamtnettowert übereinstimmt:

            if (net != self.preNet) {
                self.preNet = net
                LogProfit(net)
            }

Wenn es nicht konsistent ist, das heißt,net! = self.preNetist wahr, aktualisieren Sie das Attribut vonself.preNetverwendet, um den Nettowert mit der Variablen zu erfassennet. Dann drucken Sie die Netto-Gesamtzahl vonnetDaten für das Rendite-Kurvendiagramm des FMZ Quant Trading-Plattformrobot (dieLogProfitFunktion im FMZ-API-Dokument abgefragt werden kann).

Wenn die regelmäßige Ausgabe des Gewinns nicht ausgelöst wird, geht man mit dem folgenden Verfahren fort, um dieaccount.Stocks(Währung auf dem Girokonto) undaccount.Balance(in der Leistungsbilanz verfügbare Währung)self.BTCundself.CNY. Berechnen Sie die Offset-Skala und notieren Sie die Zuweisung in derself.p.

self.p = self.btc * self.prices[self.prices.length-1] / (self.btc * self.prices[self.prices.length-1] + self.cny)

Der Algorithmus ist auch sehr einfach, nämlich den Prozentsatz des aktuellen Wertes der Währung zum Gesamtnettowert des Kontos zu berechnen.

Was ist mit der Beurteilung, wann die Geldbilanz (Position) ausgelöst werden soll? Hier nehme ich 50% plus oder minus 2 Prozentpunkte als Puffer, und führt den Saldo über den Puffer, das heißt, wenn dieself.p < 0.48Wenn das Geld weniger ist, steigt der Preis jedes Mal um 0,01 von der Kaufposition bei der Marktöffnung und drei kleine Aufträge werden angeordnet.self.p > 0.52, wenn die Währung mehr ist, verkaufen Sie eine und kleine Aufträge freigeben.Sleep(BalanceTimeout)für eine bestimmte Zeit gemäß den Parametereinstellungen.

        Var orders = exchange. Get Orders () # Get all current makers, with orders variable
        If (orders) { # If the variable orders used to obtain the current order data is not null
            for (var i = 0; i < orders.length; I + +) { # Loop through orders and cancel orders one by one
                if (orders[i].Id != self.tradeOrderId) {
                    Exchange. CancelOrder (orders [I]. Id) # Call exchange. CancelOrder to cancel orders based on orders [I]. Id
                }
            }
        }

Die vierte zusätzliche Funktion:

Der Kern der Strategie ist das Hauptstück.self.poll = function(){...}Die wichtigste Strategie ist, daß diemain()Funktion beginnt auszuführen und geht in die endlosewhileSchleife, wir verwendenvar reaper = LeeksReaper()um das Leeksreaper-Objekt zu konstruieren und dann den Loop-Aufruf vonreaper.poll()in dermain() function.

Dieself.pollDie Funktion beginnt, vor jeder Schleife einige Vorbereitungsarbeiten durchzuführen.self.numTick++Die Zahl derself.updateTrades()Die Daten werden in den letzten Jahren auf dem Markt gehandelt und berechnet.self.updateOrderBook()Die Daten über die Bestellungen werden aktualisiert und berechnet.self.balanceAccount()Überprüfen Sie den Geldstand.

        Var burstPrice = self. Prices [self. Prices. Length-1] * BurstThresholdPct # Calculate Burst Price
        Var bull = false                   # Declare a bull-marked variable, initially false
        Var bear = false                  # Declare a bear marked variable, initially false
        Var tradeAmount = 0         # Declare the transaction amount variable, initially 0

Der nächste Schritt besteht darin, zu beurteilen, ob der aktuelle kurzfristige Markt ein Bullenmarkt oder ein Bärenmarkt ist.

        if (self.numTick > 2 && (
            self.prices[self.prices.length-1] - _.max(self.prices.slice(-6, -1)) > burstPrice ||
            self.prices[self.prices.length-1] - _.max(self.prices.slice(-6, -2)) > burstPrice && self.prices[self.prices.length-1] > self.prices[self.prices.length-2]
            )) {
            bull = true
            tradeAmount = self.cny / self.bidPrice * 0.99
        } else if (self.numTick > 2 && (
            self.prices[self.prices.length-1] - _.min(self.prices.slice(-6, -1)) < -burstPrice ||
            self.prices[self.prices.length-1] - _.min(self.prices.slice(-6, -2)) < -burstPrice && self.prices[self.prices.length-1] < self.prices[self.prices.length-2]
            )) {
            bear = true
            tradeAmount = self.btc
        }

Erinnern Sie sich an denself.updateOrderBook()Funktion aus dem vorherigen Artikel, wo wir einen gewichteten Durchschnittsalgorithmus verwendet haben, um eine zeitlich geordnetepricesDrei neue Funktionen:_.min, _.max, undsliceSie werden im Code verwendet und sind leicht verständlich.

· _. min: Die Funktion besteht darin, den Mindestwert im Parameter-Array zu finden.

· _.max: Die Funktion besteht darin, den maximalen Wert im Parameter-Array zu finden.

· slice: Die Funktion ist ein Mitglied derJavaScriptEs wird verwendet, um einen Teil des Arrays nach dem Index zurückzugeben. Zum Beispiel:

function main() {
    // index     .. -8 -7 -6 -5 -4 -3 -2 -1
    var arr = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    Log (arr. Slice (-5, -1))   // it will intercept the elements from 4 to 1 and return a new array: [4,3,2,1]
}

img

Die Voraussetzungen für die Beurteilung eines Bären- oder Bullenmarktes sind:

· Dieself.numTick > 2muss wahr sein, d. h. wenn eine neue Runde des Detektionspreises ausbricht, muss sie nach mindestens drei Detektionsrunden ausgelöst werden, um zu vermeiden, dass sie zu Beginn ausgelöst wird. · Die Differenz zwischen den letzten Daten in derself.pricesDer Preisverlauf, d. h. die jüngsten Daten, und der Höchst- oder Mindestpreis im vorherigen Bereich in derself.pricesDie Anlage sollte den Burst-Preis vonburstPrice.

Wenn alle Bedingungen wahr sind, markierenbulloderbearals wahr, und einen Wert für die Variable zuweisentradeAmountum die Stud-Transaktion zu planen.

Dann, nach derself.voldie in den vorangegangenenself.updateTrades()Funktion, dieBurstThresholdVolParameter bestimmt, ob die Transaktionsintensität reduziert werden soll (das geplante Transaktionsvolumen reduzieren).

        if (self.vol < BurstThresholdVol) {
            TradeAmount * = self. Vol/BurstThresholdVol      //Reduce the planned volume by self. Vol/BurstThresholdVol times of the previous volume
        }
        
        if (self.numTick < 5) {
            TradeAmount * = 0.8      // reduced to 80% of the plan
        }
        
        If (self. NumTick < 10) {       // reduce to 80% of the plan
            tradeAmount *= 0.8
        }

Beurteilen Sie anschließend, ob das Handelssignal und das Volumen die Anforderungen erfüllen:

        If ( (!Bull && !Bear) | | tradeAmount &lt; MinStock) {     # If it is not a bull market and not a bear market, or the amount tradeAmount planned to trade is less than the minimum trading volume MinStock set by the parameter, the poll function returns without trading operations directly
            return
        }

Nach dem oben genannten Urteil, vollstreckenvar tradePrice = bull ? self.bidPrice: self.askPricestellt den Transaktionspreis entsprechend dem Bären- oder Bullenmarkt fest und weist den Wert mit dem entsprechenden Frachtbriefpreis an.

Schließlich einewhileDie Schleife wird eingegeben, und die einzige Haltbedingung der Schleife ist, dass das geplante Handelsvolumen vontradeAmount > = MinStockunter dem Mindesthandelsvolumen liegt. In der Schleife wird der Auftrag nach dem aktuellen Marktzustand ausgeführt.orderId. Sleep(200)Die Schleife bestimmt dann, ob dieorderIdist wahr (wenn die Bestellung fehlschlägt, wird die Order-ID nicht zurückgegeben und die if-Bedingung wird nicht ausgelöst). Wenn die Bedingung wahr ist.self.tradeOrderId.

Eine Variable deklarierenorderfür die Speicherung von Auftragsdaten mit einem Anfangswert vonnull. Dann werden die Auftragsdaten der ID in einer Schleife erhalten und beurteilt, ob die Bestellung der Maker-Zustand ist, wenn ja, wird die Bestellung der ID annulliert, und wenn nicht, wird die Detektionsschleife beendet.

                Var order = null         // Declare a variable to hold the order data
                While (true) {             // a while loop
                    Order = exchange. GetOrder (orderId)          // Call GetOrder to query the order data whose order ID is orderId
                    If (order) {                                                   // If the order data is queried and the query fails and the order is null, the current if condition will not be triggered
                        If (order. Status = = ORDER _ STATE _ PENDING) {              // Judge whether the order status is maker
                            Exchange. CancelOrder (orderId)                                    // If the order is maker, cancel the order
                            Sleep(200)
                        } else {                                                                               // otherwise execute break to end the current while loop
                            break
                        }
                    }
                }

Anschließend wird folgender Vorgang durchgeführt:

                Self. TradeOrderId = 0                         // Reset self. TradeOrderId.
                TradeAmount-= order. DealAmount    // Update tradeAmount, subtract the quantity of the order on the bill of lading that has been completed
                TradeAmount * = 0.9                          //Decrease the order amount
                If (order. Status = = ORDER _ STATE _ CANCELED) {                   // if the order is already cancelled
                    Self. UpdateOrderBook ()                                                      // Update data such as order book
                    While (bull & & self. BidPrice-tradePrice &gt; 0.1) {               // In a bull market, if the updated bill of lading price exceeds the current trading price by 0.1, the trading amount will be reduced and the trading price will be adjusted slightly
                        tradeAmount *= 0.99
                        tradePrice += 0.1
                    }
                    While (bear & & self. AskPrice-tradePrice &lt; -0.1) {             // In a bear market, if the updated bill of lading price exceeds the current trading price by 0.1, the trading amount will be reduced and the trading price will be adjusted slightly
                        tradeAmount *= 0.99
                        tradePrice -= 0.1
                    }
                }

Wenn der Programmprozess endet der Schleife vonwhile (tradeAmount > = MinStock){...}, bedeutet, dass die Ausführung dieses Preis-Break-Transaktionsprozesses abgeschlossen ist. Ausführen derself.numTick = 0, d. h. dieself.numTickauf 0.

DieLeeksReaper()Konstruktor gibt dieselfGegenstand am Ende der Ausführung, d. h. wennvar reaper = LeeksReaper(), wird es an diereaper.

Wir haben bisher analysiert, wie dieLeeksReaper()Ich glaube, dass Sie nach dem Lesen dieses Artikels ein klares Verständnis für diesen Hochfrequenz-Strategie-Algorithmus-Prozess haben werden.


Verwandt

Mehr