JavaScript 策略設計における__Thread 関数の応用

作者: リン・ハーン小さな夢, 作成日:2023-07-04 16:35:42, 更新日:2023-09-18 19:32:51

img

JavaScript 策略設計における__Thread 関数の応用

初期FMZ策略設計では,非同期並行操作を使用する必要がある場合にのみ使用することが可能であった.exchange.Go()FMZパッケージインターフェースの並行を実現するための関数は,いくつかのカスタム操作 (関数) を同時に実行できない.このデザインは,策略プログラムを実行する効率を大幅に向上させるが,ネイティブプログラミング言語の並行設計経験のある同学にとって,一般的な感覚は非常に不慣れである.

FMZの入門量化取引を理解していない新生もいますexchange.Go()関数の使い方exchange.Go()FMZの新しい機能である同期スレッドの追加について,この記事で一緒に探してみましょう.__Thread()例えば,一連の関数の使い方と策略手順の非同期設計.

1 シンプルな並行設計

策略主文字列が実行されると同時に,子文字列が実行されるようにしたい場合は,以下のコードのようなデザインを使用します.GetTickerAsync()この関数は,この関数で実行する死回りです. この関数で実行する死回りとは,whileループ中のFMZのAPIインターフェース:GetTicker()市場データを入手する.

そして再利用します__threadSetData(0, "ticker", t)この文字は,主文字列にデータを書きます.tickerデータの値はtこれはGetTicker()返される値は,

__threadSetData(0, "ticker", t)

文字列を書き直すことができます. 文字列を書き直すことができます.main()この関数には,main()この関数から始めると,

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

実行を開始します. 実行を開始します. 実行を開始します.GetTickerAsync()この関数は,main()この関数は,while循環,循環の中で受け取るGetTickerAsync()機能が更新したデータをプリントします.

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

完全なコードの例:

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

リアルディスクでのテスト:

img

これは最もシンプルなアプリケーションデザインであり,次に他のニーズデザインについて見ていきましょう.

2 単一のデザイン

一つの関数を設計すると,同時に10個のスレッドを作成し,各スレッドが下記の操作関数を実行します.main()この関数で,whileループ,検知戦略 インタラクション指令、インタラクション指令を受信:placeMultipleOrdersこの関数は,この関数を呼び出します.testPlaceMultipleOrders()

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

ポリシーの編集ページにポリシーのインタラクションデザインを追加し,ボタンを設定し,コマンドは:placeMultipleOrders

img

完全なコードの例:

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)
    }
}
  • テストは,現在の価格から80%~90%増幅して,アンモニアディスク環境テストを使用して,インタラクティブボタンをクリックしてテストを起動する方法で行われます:

    img

  • "placeMultipleOrders"ボタンをクリックすると,次のメッセージが表示されます.

    img

  • 戦略ログには,次の操作が表示されています.

    img

3 連続するスレッド実行で WebSocket 接続を作成する

この要求は FMZ ユーザーによって提出され,並行スレッドでどのように使用するか示す簡単な例が期待されています.Webソケット接続し,データを主線に送る方法を設計します.main()この関数は,

この例では,同じ線を同時に作成する.ただし,線間通信は使用されます.__threadPeekMessage()函数と__threadPostMessage()関数. 仮想通貨取引所のWebSocket APIのインターフェース呼び出しの例として,WebSocket接続の終了操作についても設計で注意する必要がある.以下の例では,並行するスレッドに通知して停止させる方法も示されている.

完全なコードの例:

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("扫尾函数执行完毕")
}

リアルディスクでのテスト:

img

視覚障害者にとってmain()函数には,並行スレッドで作成された WebSocket 接続から受信された行程データが連続して受信されます.

実行する場合は,次の操作を実行します.

img


関連性

もっと

スパダは量化されている最後に,wsスレッドが多く,複数のトピックがサブスクリプションされている場合,スレッド間の通信では,get/setの方法かpeek/postの方法がどちらの性能が良いか.

スパダは量化されている糸間共有変数の基礎実装は,参照変数をサポートしないため,更新ごとにリセットする必要があります.これは低効率です.

小さな夢この2つの方法は,ほとんど同じですが,すべて可能です.