En la carga de los recursos... Cargando...

Utilice JavaScript para implementar la ejecución simultánea de la estrategia cuantitativa - encapsular la función Go

El autor:FMZ~Lydia, Creado: 2023-01-31 09:57:00, Actualizado: 2023-09-18 20:10:07

img

Utilice JavaScript para implementar la ejecución simultánea de la estrategia cuantitativa - encapsular la función Go

Cuando se implementa la estrategia cuantitativa, la ejecución simultánea puede reducir la latencia y mejorar la eficiencia en muchos casos. Tomando el robot de cobertura como ejemplo, necesitamos obtener la profundidad de dos monedas.

var depthA = exchanges[0].GetDepth()
var depthB = exchanges[1].GetDepth()

Hay un retraso en la solicitud de una API de descanso. Suponiendo que sea de 100 ms, el tiempo para obtener la profundidad es realmente diferente. Si se requiere más acceso, el problema de retraso se volverá más prominente y afectará a la implementación de la estrategia.

JavaScript no tiene multithreading, por lo que la función Go se encapsula en la parte inferior para resolver este problema. Sin embargo, debido al mecanismo de diseño, la implementación es relativamente engorrosa.

var a = exchanges[0].Go("GetDepth")
var b = exchanges[1].Go("GetDepth")
var depthA = a.wait() // Call the wait method to wait for the return of the depth result asynchronously 
var depthB = b.wait()

En la mayoría de los casos simples, no hay nada de malo en escribir la estrategia de esta manera. Sin embargo, se observa que este proceso debe repetirse para cada bucle de estrategia. Las variables intermedias a y b son solo ayudas temporales. Si tenemos muchas tareas concurrentes, necesitamos registrar la relación correspondiente entre a y profundidadA, y b y profundidadB. Cuando nuestras tareas concurrentes son inciertas, la situación se vuelve más compleja. Por lo tanto, queremos implementar una función: al escribir Go simultáneamente, vincular una variable al mismo tiempo, y cuando el resultado de la operación concurrente devuelve, el resultado se asignará automáticamente a la variable, eliminando la variable intermedia y, por lo tanto, haciendo que el programa sea más conciso. La implementación específica es la siguiente:

function G(t, ctx, f) {
    return {run:function(){
        f(t.wait(1000), ctx)
    }}
}

Definimos una función G, donde el parámetro t es la función Go a ejecutar, ctx es el contexto del programa de grabación, y f es la función de asignación específica.

En este momento, el marco general del programa se puede escribir como similar al modelo producer-consumer (con algunas diferencias). El productor sigue enviando tareas, y el consumidor las ejecuta simultáneamente.

var Info = [{depth:null, account:null}, {depth:null, account:null}] // If we need to obtain the depth and account of the two exchanges, more information can also be put in, such as order ID, status, etc.
var tasks = [ ] // Global list of tasks

function produce(){ // Issue various concurrent tasks
  // The logic of task generation is omitted here, for demonstration purposes only.
  tasks.push({exchange:0, ret:'depth', param:['GetDepth']})
  tasks.push({exchange:1, ret:'depth', param:['GetDepth']})
  tasks.push({exchange:0, ret:'sellID', param:['Buy', Info[0].depth.Asks[0].Price, 10]})
  tasks.push({exchange:1, ret:'buyID', param:['Sell', Info[1].depth.Bids[0].Price, 10]})
}
function worker(){
    var jobs = []
    for(var i=0;i<tasks.length;i++){
        var task = tasks[i]
        tasks.splice(i,1) // Delete executed tasks
        jobs.push(G(exchanges[task.exchange].Go.apply(this, task.param), task, function(v, task) {
                    Info[task.exchange][task.ret] = v // The v here is the return value of the concurrent Go function wait(), which can be experienced carefully.
                }))
    }
    _.each(jobs, function(t){
            t.run() // Execute all tasks concurrently here
        })
}
function main() {
    while(true){
        produce()         // Send trade orders
        worker()        // Concurrent execution
        Sleep(1000)
    }
}

Parece que solo se ha implementado una función simple después de ir en círculos. De hecho, la complejidad del código se ha simplificado mucho. Solo tenemos que preocuparnos por qué tareas debe generar el programa. El programa worker() las ejecutará automáticamente simultáneamente y devolverá los resultados correspondientes. La flexibilidad ha mejorado mucho.


Relacionados

Más.