Anwendung der _Thread-Funktion im JavaScript-Strategiedesign

Schriftsteller:Kleine Träume, Erstellt: 2023-07-04 16:35:42, Aktualisiert: 2023-09-18 19:32:51

img

Anwendung der _Thread-Funktion im JavaScript-Strategiedesign

In der ursprünglichen FMZ-Strategie-Konstruktion wurden asynchrone Paralleloperationen nur verwendet, wenn sie benötigt wurden.exchange.Go()Funktionen, die die FMZ-Verpackungs-Schnittstelle ermöglichen, können nicht gleichzeitig einige benutzerdefinierte Operationen ("Funktionen") ausführen. Obwohl dieses Design die Effizienz der Ausführung von Strategieprogrammen erheblich verbessert, ist es für Schüler, die Erfahrung mit Paralleldesign in einheimischen Programmiersprachen haben, sehr ungewöhnlich.

Selbst neue Schüler, die mit FMZ-Eintrittsquantifikationsgeschäften arbeiten, verstehen das nichtexchange.Go()Funktionen, deren Nutzungexchange.Go()Es scheint, dass es sich immer noch um einen Satz für einen Satz in der Reihenfolge handelt.__Thread()Die Verwendung von Serial-Funktionen, etc., ist nicht synchron mit der Strategie.

1. Einfache Parallelgestaltung

Wenn wir einen Haupttread der Strategie laufen lassen wollen, und gleichzeitig einen Unterthread laufen lassen wollen, um eine von uns geschriebene Custom Function auszuführen, können wir eine ähnliche Designart verwenden.GetTickerAsync()Die Funktion führt einen toten Kreislauf aus, in dem die Funktion in einem Kreislauf geschrieben wird.whileDie API-Schnittstelle für FMZs, die ständig in den Loop gerufen werden:GetTicker()Ich habe eine Liste von Kunden gefunden, die sich mit dem Markt beschäftigen.

Dann benutzen Sie es wieder.__threadSetData(0, "ticker", t)Das ist ein Date, das in den Hauptsträngen geschrieben wird.tickerDie Datenwerte sind:tDas heißtGetTicker()Der Wert wird zurückgegeben.

__threadSetData(0, "ticker", t)

Wenn wir die benutzerdefinierten Funktionen, die parallel ausgeführt werden, ausarbeiten können, können wir diese Funktionen schreiben.main()Wir haben den Code in der Funktion.main()Die Funktion beginnt mit:

__Thread(GetTickerAsync, 0)   // GetTickerAsync为需要并发执行的自定义函数,0为这个传入GetTickerAsync函数的参数

Wir erstellen einen parallel laufenden Thread, und dieser Thread beginnt zu laufen.GetTickerAsync()Die Funktion.main()Die Funktion beginnt ihre eigene Ausführung.whileKreislauf, Empfang im KreislaufGetTickerAsync()Die Funktion aktualisiert die Daten und druckt:

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

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

Tests auf der Festplatte:

img

Dies ist die einfachste Art des App-Designs, und wir werden einige weitere Bedarfsgestaltungen anschauen.

2, gleichzeitig ein Design veröffentlichen

Eine Funktion kann so gestaltet werden, dass 10 Threads gleichzeitig erstellt werden, wobei jeder Thread eine Unterordnungsfunktion ausführt.main()Wir haben eine Funktion entworfen.whileSie werden von einem Netzwerk, das sich mit dem Internet beschäftigt, übertragen.placeMultipleOrdersWir können diese Funktion einfach aufrufen.testPlaceMultipleOrders()

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

Hinzufügen von Policy Interaction Design auf der Policy-Editing-Seite, Einstellung eines Buttons mit dem Befehl: placeMultipleOrders

img

Ein 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)
    }
}
  • Tests werden mit einem Hangover-Modus durchgeführt, der von 80% bis 90% des aktuellen Preises inkrementell getestet wird, und mit einem Analogdisk-Umgebungstest, bei dem der Test mit dem Klick auf die interaktive Taste ausgelöst wird:

    img

  • Wenn Sie auf die "placeMultipleOrders"-Taste klicken, werden Sie aufgefordert:

    img

  • Das Strategie-Log zeigt folgende Simulationen an:

    img

3. Erstellen von WebSocket-Verbindungen in parallel laufenden Thread-Exekutionsfunktionen

Diese Anforderung wurde von einem FMZ-Benutzer gestellt, der sich ein einfaches Beispiel wünschte, um zu demonstrieren, wie man es in Parallelthemen verwendet.WebSocketWir haben eine Reihe von Programmen entwickelt, um Daten zu vernetzen und zu entwerfen, wie sie an den Hauptstrang weitergeleitet werden.main()Die Funktion.

Es ist sehr einfach, ähnlich wie im vorherigen Beispiel gleichzeitige Threads zu erstellen.__threadPeekMessage()Funktionen und__threadPostMessage()Funktionen. Bei den WebSocket-API-Anrufen der Bitcoin-Börse müssen wir uns auch bei der Konstruktion der Schließung von WebSocket-Verbindungen bewusst sein. In den folgenden Beispielen wird auch gezeigt, wie man einen parallel verlaufenden Thread benachrichtigt, um ihn zu stoppen.

Ein 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("创建WS连接:", stream)
    
    while (true) {
        var data = ws.read()
        if (data) {            
            __threadPostMessage(0, data)
        }
        Log("接收到WS链接推送的数据,data:", data)
        
        // __threadPeekMessage 超时参数设置-1,不阻塞
        var msg = __threadPeekMessage(-1)
        if (msg) {
            if (msg == "stop") {
                Log("并发线程Id:", __threadId(), "接收到stop指令")
                break
            }
        }
    }

    Log("并发线程执行完毕,关闭ws连接")
    ws.close()
}

function main() {
    tid = __Thread(createWS)
    Log("创建并发线程,线程Id:", tid)

    while(true) {
        // __threadPeekMessage 的超时参数设置为0,阻塞等待数据
        var data = __threadPeekMessage(0)
        Log("接收到并发线程", ", Id:", tid, ", 发送的数据,data:", data, "#FF0000")
        
        var tbl = {
            type : "table", 
            title : "<symbol>@ticker频道推送消息",
            cols : ["事件类型", "事件时间", "交易对", "24小时价格变化", "24小时价格变化百分比", "平均价格", "最新成交价格", "24小时内成交量", "24小时内成交额"],
            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("扫尾函数,向Id为", tid, "的并发线程发送stop指令")
    __threadPostMessage(tid, "stop")
    Log("等待Id为", tid, "的并发线程停止")
    __threadJoin(tid)
    Log("扫尾函数执行完毕")
}

Tests auf der Festplatte:

img

Sie sehen.main()Die Funktion empfängt ständig Transaktionsdaten von WebSocket-Verbindungen, die von gleichzeitigen Threads erstellt wurden.

Wenn man die Strategie auf dem Festplatte hält, wird die Wickelfunktion ausgeführt:

img


Verwandt

Mehr

Spartan spielt QuantumEin letztes Beispiel: Wenn es viele ws-Themen gibt, und man hat mehrere Themen abonniert, welche Funktion ist besser, wenn man zwischen den Themen kommuniziert, mit dem get/set oder dem peek/post?

Spartan spielt QuantumDie Basisimplementierung von String-Shared-Variablen unterstützt keine Referenzvariablen, die bei jedem Update neu gesetzt werden müssen, was sehr uneffizient ist.

Kleine TräumeEs gibt keine Unterschiede zwischen den beiden Möglichkeiten.