Aplikasi fungsi "__Thread" dalam reka bentuk strategi JavaScript

Penulis:Lydia, Dicipta: 2023-07-07 13:56:17, Dikemas kini: 2023-09-18 19:31:40

img

Aplikasi fungsi __Thread dalam reka bentuk strategi JavaScript

Dalam reka bentuk awal strategi FMZ, jika operasi serentak asynchronous diperlukan,exchange.Go()Walaupun reka bentuk ini sangat meningkatkan kecekapan program strategi, pelajar yang mempunyai pengalaman dalam reka bentuk serentak dalam bahasa pengaturcaraan asli sering merasa sangat tidak selesa.

Malah pelajar baru yang menggunakan FMZ untuk perdagangan kuantitatif pengenalan mungkin tidak memahami penggunaanexchange.Go()Menggunakanexchange.Go()Dalam artikel ini, kita akan meneroka penggunaan fungsi benang serentak yang baru ditambah dalam platform FMZ:__Thread()dan fungsi lain yang berkaitan, serta reka bentuk asynchronous program strategi.

1. Reka bentuk serentak yang mudah

Jika kita mahu benang utama strategi untuk berjalan serentak dengan sub-benang menjalankan fungsi tersuai yang kita telah menulis, kita boleh menggunakan reka bentuk yang serupa dengan kod berikut.GetTickerAsync()Fungsi ini menjalankan gelung tanpa akhir dan terus memanggil antara muka FMZ APIGetTicker()untuk mendapatkan data pasaran.

Kemudian, gunakan pernyataan__threadSetData(0, "ticker", t)untuk menulis data ke benang utama. Nama data adalahtickerdan nilai data adalaht, yang merupakan nilai pulanganGetTicker().

__threadSetData(0, "ticker", t)

Selepas mereka bentuk fungsi tersuai untuk pelaksanaan benang serentak, kita boleh menulis kod dalammain()Pada permulaanmain()fungsi, kita gunakan:

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

Buat thread serentak yang memulakan pelaksanaanGetTickerAsync()fungsi.main()fungsi mula menjalankan sendiriwhilegelung, di mana ia menerima data dikemas kini olehGetTickerAsync()fungsi dan mencetak ia:

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

Contoh kod lengkap:

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

Ujian perdagangan langsung:

img

Ini adalah salah satu reka bentuk aplikasi yang paling mudah, jadi mari kita lihat beberapa reka bentuk keperluan lain.

2. Reka bentuk penempatan pesanan serentak

Kita boleh merancang fungsi untuk mencipta 10 benang secara serentak, masing-masing melaksanakan fungsi penempatan pesanan.main()fungsi, kita boleh merancangwhileloop untuk mengesan arahan interaksi strategi.placeMultipleOrders, kita memanggil fungsi penempatan pesanan serentaktestPlaceMultipleOrders().

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

Tambah reka bentuk interaksi strategi pada halaman penyuntingan strategi dengan menambah butang dengan perintah: tempatMultipleOrders.

img

Contoh kod lengkap:

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)
    }
}
  • Ujian ini menggunakan pesanan yang menunggu, meningkat dari 80% hingga 90% daripada harga semasa, dalam persekitaran perdagangan yang disimulasikan.

Selepas mengklik butang placeMultipleOrders, mesej akan muncul: Perintah placeMultipleOrders telah dihantar dengan berjaya, sila tunggu tindak balas dari perdagangan langsung!

  • Log strategi menunjukkan operasi penempatan pesanan serentak:

img

3. Buat sambungan WebSocket dalam fungsi pelaksanaan thread serentak

Keperluan ini dibangkitkan oleh pengguna FMZ yang mahu contoh mudah menunjukkan bagaimana untuk menggunakanWebSocketsambungan dalam benang serentak dan bagaimana untuk lulus data kepadamain()fungsi dalam benang utama.

Sebenarnya, ia agak mudah dan serupa dengan membuat benang serentak dalam contoh sebelumnya.__threadPeekMessage()dan__threadPostMessage()mengambil panggilan WebSocket API untuk pertukaran Binance sebagai contoh, kita juga perlu mengendalikan operasi penutupan sambungan WebSocket. Contoh berikut menunjukkan bagaimana untuk memberitahu utas serentak untuk berhenti.

Contoh kod lengkap:

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

Semasa ujian perdagangan langsung, kita boleh melihat bahawamain()fungsi terus menerima data pasaran dari sambungan WebSocket yang dicipta oleh benang serentak.

Apabila menghentikan strategi perdagangan langsung, fungsi menyelesaikan akan mula berfungsi.


Berkaitan

Lebih lanjut