Aplicación de la función _thread en el diseño de la política de JavaScript

El autor:Un sueño pequeño., Creado: 2023-07-04 16:35:42, Actualizado: 2023-09-18 19:32:51

img

Aplicación de la función _thread en el diseño de la política de JavaScript

En el diseño original de la política FMZ, sólo se podía usar una operación asíncrona si se necesitaba.exchange.Go()Las funciones para implementar la concurrencia de la interfaz de envase FMZ no pueden ejecutar simultáneamente algunas operaciones personalizadas (funciones). Aunque este diseño mejora mucho la eficiencia de la ejecución de los programas estratégicos, los estudiantes con experiencia en diseño simultáneo en los lenguajes nativos no están acostumbrados a la sensación general.

Incluso los nuevos estudiantes que usan FMZ para introducir transacciones cuantitativas no lo entienden.exchange.Go()Uso de funciones, usoexchange.Go()En este artículo, vamos a explorar las nuevas funciones de los hilos de concurrencia de la plataforma FMZ:__Thread()El uso de la serie de funciones, etc., es asíncrono con el diseño del procedimiento de la política.

1o, diseño simple paralelo

Si queremos que el hilo principal de la política se ejecute al mismo tiempo que se ejecuta un subdirectorio para ejecutar la función personalizada que hemos escrito, podemos usar un diseño similar al siguiente código.GetTickerAsync()Esta función ejecuta un ciclo muerto, en el que el valor de la función es el valor de la función.whileLa interfaz API de FMZ que llama continuamente en el circuito:GetTicker()En la actualidad, la mayoría de los usuarios de Twitter están en línea con sus redes sociales.

Y luego usarlo.__threadSetData(0, "ticker", t)Esta frase escribe un dato en el hilo principal, llamado nombre de datos.tickerEl valor de los datos estEs decir,GetTicker()El valor de retorno de los números de las partidas es:

__threadSetData(0, "ticker", t)

Y después de diseñar las funciones personalizadas que se ejecutan a la vez, podemos escribirmain()La función está en el código.main()La función comienza con:

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

Creamos un hilo paralelo que comienza a ejecutarse.GetTickerAsync()Función. Luegomain()Las funciones comienzan a ejecutarse.whileCirculan, reciben en el cicloGetTickerAsync()La función actualiza los datos y luego imprime:

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

Un ejemplo de código completo:

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

La prueba en disco real:

img

Este es el diseño de aplicaciones más sencillo, ahora vamos a ver otros diseños de necesidades.

2, diseño simultáneo

Se puede diseñar una función para crear 10 hilos simultáneamente, cada uno de los cuales ejecuta una función operativa de orden inferior.main()Diseñar una funciónwhileEn la página web del sitio web, el usuario puede encontrar instrucciones de interacción de la política de detección.placeMultipleOrdersAsí que esto es lo que llamamos.testPlaceMultipleOrders()

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

Añadir diseño interactivo de la política en la página de edición de la política, establecer un botón con el comando: placeMultipleOrders

img

Un ejemplo de código completo:

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)
    }
}
  • Prueba de la manera de usar el menú colgado, incrementado desde el 80% hasta el 90% del precio actual, prueba del entorno del disco analógico, clicando en el botón interactivo para activar el menú de prueba:

    img

  • Después de hacer clic en el botón "placeMultipleOrders", se muestra el siguiente mensaje:

    img

  • En el registro de estrategias se muestra la siguiente operación simultánea:

    img

3. Creación de conexiones WebSocket en ejecuciones de hilos simultáneas

Este requisito fue presentado por un usuario de FMZ, con la esperanza de tener un ejemplo simple que demuestre cómo usarlo en hilos paralelos.WebSocket y el sistema operativoLa conexión y diseño de cómo transmitir los datos a los hilos principalesmain()La función.

En realidad, es muy sencillo, y es casi lo mismo que crear hilos simultáneos en el ejemplo anterior; pero se utiliza para la comunicación entre hilos.__threadPeekMessage()Función y__threadPostMessage()Función. Tomando como ejemplo la llamada a la API de WebSocket de Bitcoin Exchange, en el diseño también necesitamos prestar atención a la operación de cierre de la conexión WebSocket, y el siguiente ejemplo también muestra cómo notificar a un hilo simultáneo para que se detenga.

Un ejemplo de código completo:

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

La prueba en disco real:

img

Se puede vermain()La función recibe continuamente datos de mercado de las conexiones WebSocket creadas en la misma cadena.

Cuando se detiene la política en vivo, la función de barrido comienza a funcionar:

img


Relacionados

Más.

Esparta jugando a la cantidadUn último ejemplo, si hay muchos hilos ws y se suscribe a varios temas, ¿cuál es el mejor rendimiento para la comunicación entre hilos, usar el método get / set o el método peek / post?

Esparta jugando a la cantidadLa implementación básica de variables compartidas entre hilos es que no soporta variables de referencia, y tiene que ser reestablecida cada vez que se actualiza, lo cual es muy bajo en eficiencia.

Un sueño pequeño.Las dos formas no son muy diferentes, pueden ser.