Anwendung der Funktion "__Thread" im JavaScript-Strategiedesign

Schriftsteller:Lydia., Erstellt: 2023-07-07 13:56:17, Aktualisiert: 2023-09-18 19:31:40

img

Anwendung der __Thread-Funktion im JavaScript-Strategie-Design

Bei der ursprünglichen Konzeption der FMZ-Strategie, wenn asynchrone gleichzeitige Operationen erforderlich sind, wird dieexchange.Go()Funktion kann nur zur gleichzeitigen Ausführung der FMZ-verkapselten Schnittstelle verwendet werden, und es ist nicht möglich, einige benutzerdefinierte Operationen (Funktionen) gleichzeitig auszuführen. Obwohl dieses Design die Effizienz des Strategieprogramms erheblich verbessert, fühlen sich Studenten, die Erfahrung mit gleichzeitiger Ausführung in nativen Programmiersprachen haben, oft sehr unwohl.

Selbst neue Studenten, die FMZ für einführende quantitative Handelsmethoden verwenden, können die Verwendung desexchange.Go()Funktionexchange.Go()In diesem Artikel werden wir die Verwendung der neu hinzugefügten gleichzeitigen Thread-Funktionalität in der FMZ-Plattform untersuchen:__Thread()und andere verwandte Funktionen sowie die asynchrone Gestaltung von Strategieprogrammen.

1. Einfache gleichzeitige Konstruktion

Wenn wir möchten, dass der Hauptthread der Strategie gleichzeitig mit einem Unterthread ausgeführt wird, der eine benutzerdefinierte Funktion ausführt, die wir geschrieben haben, können wir ein Design ähnlich dem folgenden Code verwenden.GetTickerAsync()Diese Funktion führt eine unendliche Schleife aus und ruft kontinuierlich die FMZ API-SchnittstelleGetTicker()Um Marktdaten abzurufen.

Dann benutzen Sie die Aussage__threadSetData(0, "ticker", t)Der Datenname isttickerund der Datenwert istt, was der Rückgabewert vonGetTicker().

__threadSetData(0, "ticker", t)

Nachdem wir die benutzerdefinierte Funktion für die gleichzeitige Ausführung von Threads entworfen haben, können wir den Code in diemain()In den letzten Jahren hat sich die Zahl dermain()Funktion, die wir verwenden:

__Thread(GetTickerAsync, 0)   // GetTickerAsync is a custom function that needs to be executed concurrently, and 0 is the parameter that is passed to the GetTickerAsync function.

Erstellen Sie einen gleichzeitigen Thread, der die Ausführung desGetTickerAsync()Diemain()Funktion beginnt die Ausführung seiner eigenenwhileSchleife, in der sie die von derGetTickerAsync()Funktion und druckt es aus:

var t = __threadGetData(0, "ticker")
Log(t)

Beispiel für den vollständigen Code:

function GetTickerAsync(index) {
    while (true) {
        var t = exchanges[index].GetTicker()
        __threadSetData(0, "ticker", t)
        Sleep(500)
    }
}

function main() {
    __Thread(GetTickerAsync, 0)

    while(true) {
        var t = __threadGetData(0, "ticker")
        Log(t)
        Sleep(1000)
    }
}

Live-Handelstest:

img

Dies ist eines der einfachsten Anwendungsdesigns, also schauen wir uns einige andere Anforderungendesigns an.

2. Konzeption der gleichzeitigen Auftragsvergabe

Wir können eine Funktion entwerfen, um 10 Threads gleichzeitig zu erstellen, von denen jeder eine Bestellfunktion ausführt.main()Wir können eine Funktion entwerfen.whileWenn wir den Interaktionsbefehl empfangenplaceMultipleOrders, nennen wir die gleichzeitige BestellfunktiontestPlaceMultipleOrders().

if (cmd == "placeMultipleOrders") {
    // ...
}

Fügen Sie das Strategieinteraktionsdesign auf der Strategiebearbeitungsseite hinzu, indem Sie eine Schaltfläche mit dem Befehl: placeMultipleOrders hinzufügen.

img

Beispiel für den vollständigen Code:

function placeOrder(exIndex, type, price, amount) {
    var id = null 
    if (type == "Buy") {
        id = exchanges[exIndex].Buy(price, amount)
    } else if (type == "Sell") {
        id = exchanges[exIndex].Sell(price, amount)
    } else {
        throw "type error! type:" + type
    }
}

function testPlaceMultipleOrders(index, beginPrice, endPrice, step, type, amount) {
    Log("beginPrice:", beginPrice, ", endPrice:", endPrice, ", step:", step, ", type:", type, ", amount:", amount)
    var tids = []
    for (var p = beginPrice; p <= endPrice; p += step) {
        var tid = __Thread(placeOrder, index, type, p, amount)
        tids.push(tid)
        Sleep(10)
    }
    Sleep(1000)
    for (var i = 0; i < tids.length; i++) {
        __threadTerminate(tids[i])
    }
}

function main() {
    while(true) {
        LogStatus(_D())
        var cmd = GetCommand()
        if (cmd) {
            if (cmd == "placeMultipleOrders") {
                var t = _C(exchange.GetTicker)
                var beginPrice = t.Last * 0.8
                var endPrice = t.Last * 0.9
                var step = t.Last * 0.01
                testPlaceMultipleOrders(0, beginPrice, endPrice, step, "Buy", 0.01)
                var orders = exchange.GetOrders()
                for (var i = 0; i < orders.length; i++) {
                    Log(orders[i])
                }
            }
        }
        Sleep(1000)
    }
}
  • Der Test nimmt ausstehende Aufträge an, die in einer simulierten Handelsumgebung von 80% auf 90% des aktuellen Preises steigen.

Nach dem Klicken auf die Schaltfläche placeMultipleOrders wird eine Meldung angezeigt: Der Befehl placeMultipleOrders wurde erfolgreich gesendet, bitte warten Sie auf eine Antwort des Live-Handels!

  • Strategieprotokoll zeigt gleichzeitige Auftragsvergabevorgänge:

img

3. Erstellen Sie eine WebSocket-Verbindung in einer gleichzeitigen Thread-Ausführungsfunktion

Diese Anforderung wurde von einem FMZ-Benutzer gestellt, der ein einfaches Beispiel für die Verwendung einesWebSocketAnschluss in gleichzeitigen Threads und wie Daten an diemain()Funktion im Hauptfaden.

Eigentlich ist es ziemlich einfach und ähnlich wie das Erstellen von gleichzeitigen Threads in den vorherigen Beispielen.__threadPeekMessage()und__threadPostMessage()Wir müssen auch die Schließung der WebSocket-Verbindung verarbeiten. Das folgende Beispiel zeigt, wie man einen gleichzeitigen Thread zum Stoppen benachrichtigt.

Beispiel für den vollständigen Code:

var tid = null 

function createWS() {
    // wss://stream.binance.com:9443/ws/<streamName> , <symbol>@ticker
    
    var stream = "wss://stream.binance.com:9443/ws/btcusdt@ticker"    
    var ws = Dial(stream)
    Log("Create a WS connection:", stream)
    
    while (true) {
        var data = ws.read()
        if (data) {            
            __threadPostMessage(0, data)
        }
        Log("receiving data pushed by the WS link, data:", data)
        
        // __threadPeekMessage timeout parameter set to -1, no blocking
        var msg = __threadPeekMessage(-1)
        if (msg) {
            if (msg == "stop") {
                Log("Concurrent Thread Id:", __threadId(), "Received stop command")
                break
            }
        }
    }

    Log("Concurrent threads finish execution, close ws connection")
    ws.close()
}

function main() {
    tid = __Thread(createWS)
    Log("Create concurrent threads, thread Id:", tid)

    while(true) {
        // __threadPeekMessage's timeout parameter is set to 0, blocking for data
        var data = __threadPeekMessage(0)
        Log("Received from concurrent thread", ", Id:", tid, ", the data sent, data:", data, "#FF0000")
        
        var tbl = {
            type : "table", 
            title : "<symbol>@ticker channel push message",
            cols : ["Event Type", "Event Time", "Trading Pairs", "24 Hour Price Change", "24 Hour Price Change %", "Average Price", "Last Traded Price", "Volume in 24 Hours", "Turnover in 24 Hours"],
            rows : []
        }

        try {
            data = JSON.parse(data)
            tbl.rows.push([data.e, _D(data.E), data.s, data.p, data.P, data.w, data.c, data.v, data.q])
        } catch (e) {
            Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
        }
        LogStatus(_D(), "\n`" + JSON.stringify(tbl) + "`")
    }
}

function onexit() {
    Log("Finalize function, send a stop command to the concurrent thread with ID ", tid,"")
    __threadPostMessage(tid, "stop")
    Log("Wait for the concurrent thread with ID ", tid, " to stop")
    __threadJoin(tid)
    Log("Finalize function execution completed")
}

Während des Live-Trading-Tests können wir sehen, dass diemain()Funktion erhält kontinuierlich Marktdaten von WebSocket-Verbindungen, die von gleichzeitigen Threads erstellt werden.

Wenn die Live-Handelsstrategie gestoppt wird, wird die Finalisierungsfunktion funktionieren.


Verwandt

Mehr