Áp dụng hàm "__Thread" trong thiết kế chiến lược JavaScript

Tác giả:Lydia., Tạo: 2023-07-07 13:56:17, Cập nhật: 2023-09-18 19:31:40

img

__Thread trong thiết kế chiến lược JavaScript

Trong thiết kế ban đầu của chiến lược FMZ, nếu các hoạt động đồng bộ không đồng bộ được yêu cầu, cácexchange.Go()Mặc dù thiết kế này cải thiện đáng kể hiệu quả của chương trình chiến lược, nhưng sinh viên có kinh nghiệm trong thiết kế đồng thời trong ngôn ngữ lập trình bản địa thường cảm thấy rất khó chịu.

Ngay cả những sinh viên mới sử dụng FMZ cho giao dịch định lượng giới thiệu cũng có thể không hiểu được việc sử dụng FMZ.exchange.Go()sử dụngexchange.Go()Trong bài viết này, chúng tôi sẽ khám phá việc sử dụng chức năng luồng đồng thời mới được thêm vào trong nền tảng FMZ:__Thread()và các chức năng liên quan khác, cũng như thiết kế không đồng bộ của các chương trình chiến lược.

1. Thiết kế đồng thời đơn giản

Nếu chúng ta muốn chủ đề chính của chiến lược chạy đồng thời với một chủ đề con thực hiện một hàm tùy chỉnh mà chúng ta đã viết, chúng ta có thể sử dụng một thiết kế tương tự như mã sau.GetTickerAsync()và viết các chức năng cụ thể của hàm này. hàm này thực hiện một vòng lặp vô hạn và liên tục gọi giao diện FMZ APIGetTicker()để lấy dữ liệu thị trường.

Sau đó, sử dụng tuyên bố__threadSetData(0, "ticker", t)để viết dữ liệu vào chủ đề. Tên dữ liệu làtickervà giá trị dữ liệu làt, đó là giá trị trả về củaGetTicker().

__threadSetData(0, "ticker", t)

Sau khi thiết kế các chức năng tùy chỉnh cho thực thi luồng đồng thời, chúng ta có thể viết mã trongmain()Các chức năngmain()chức năng, chúng ta sử dụng:

__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.

Tạo một chủ đề đồng thời bắt đầu thực hiệnGetTickerAsync()Sau đó, cácmain()chức năng bắt đầu thực hiện của riêng mìnhwhilevòng lặp, trong đó nó nhận được dữ liệu được cập nhật bởi cácGetTickerAsync()chức năng và in nó:

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

Ví dụ mã đầy đủ:

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

Thử nghiệm giao dịch trực tiếp:

img

Đây là một trong những thiết kế ứng dụng đơn giản nhất, vì vậy hãy xem xét một số thiết kế yêu cầu khác.

2. Thiết kế đặt hàng đồng thời

Chúng ta có thể thiết kế một chức năng để tạo 10 chủ đề đồng thời, mỗi thực hiện một chức năng đặt hàng.main()chức năng, chúng ta có thể thiết kế mộtwhilevòng lặp để phát hiện các lệnh tương tác chiến lược. khi chúng tôi nhận được lệnh tương tácplaceMultipleOrders, chúng ta gọi là hàm đặt hàng đồng thờitestPlaceMultipleOrders().

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

Thêm thiết kế tương tác chiến lược trên trang chỉnh sửa chiến lược bằng cách thêm một nút với lệnh: placeMultipleOrders.

img

Ví dụ mã đầy đủ:

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)
    }
}
  • Thử nghiệm chấp nhận các lệnh đang chờ, tăng từ 80% đến 90% giá hiện tại, trong môi trường giao dịch mô phỏng.

Sau khi nhấp vào nút placeMultipleOrders, một thông báo được nhắc: lệnh placeMultipleOrders đã được gửi thành công, xin vui lòng chờ phản hồi từ giao dịch trực tiếp!

  • Lịch chiến lược hiển thị các hoạt động đặt hàng đồng thời:

img

3. Tạo một kết nối WebSocket trong một hàm thực thi luồng đồng thời

Yêu cầu này được đưa ra bởi một người dùng FMZ muốn một ví dụ đơn giản chứng minh cách sử dụng mộtWebSocketkết nối trong các luồng đồng thời và làm thế nào để truyền dữ liệu đếnmain()chức năng trong đường dây chính.

Thực tế, nó khá đơn giản và tương tự như việc tạo các chủ đề đồng thời trong các ví dụ trước.__threadPeekMessage()__threadPostMessage()lấy WebSocket API gọi cho sàn giao dịch Binance làm ví dụ, chúng ta cũng cần xử lý hoạt động đóng kết nối WebSocket. Ví dụ sau đây cho thấy cách thông báo cho một luồng đồng thời dừng lại.

Ví dụ mã đầy đủ:

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

Trong quá trình thử nghiệm giao dịch trực tiếp, chúng ta có thể thấy rằngmain()chức năng liên tục nhận dữ liệu thị trường từ các kết nối WebSocket được tạo bởi các luồng đồng thời.

Khi dừng chiến lược giao dịch trực tiếp, chức năng finalize sẽ bắt đầu hoạt động.


Có liên quan

Thêm nữa