Utilisez JavaScript pour mettre en œuvre l'exécution simultanée de la stratégie quantitative - encapsuler la fonction Go

Auteur:Je ne sais pas., Créé: 2023-01-31 09:57:00, Mis à jour: 2023-09-18 20:10:07

img

Utilisez JavaScript pour mettre en œuvre l'exécution simultanée de la stratégie quantitative - encapsuler la fonction Go

Lors de la mise en œuvre de la stratégie quantitative, l'exécution simultanée peut réduire la latence et améliorer l'efficacité dans de nombreux cas. Prenant le robot de couverture comme exemple, nous devons obtenir la profondeur de deux pièces. Le code exécuté en séquence est le suivant:

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

Il y a un retard dans la demande d'une API de repos. En supposant qu'il s'agisse de 100 ms, le temps pour obtenir la profondeur est en fait différent. Si plus d'accès est nécessaire, le problème de retard deviendra plus important et affectera la mise en œuvre de la stratégie.

JavaScript n'a pas de multithreading, donc la fonction Go est encapsulée en bas pour résoudre ce problème.

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

Dans la plupart des cas simples, il n'y a rien de mal à écrire la stratégie de cette façon. Cependant, il est à noter que ce processus doit être répété pour chaque boucle de stratégie. Les variables intermédiaires a et b ne sont que des aides temporaires. Si nous avons beaucoup de tâches simultanées, nous devons enregistrer la relation correspondante entre a et la profondeurA, et b et la profondeurB. Lorsque nos tâches simultanées sont incertaines, la situation devient plus complexe. Par conséquent, nous voulons implémenter une fonction: lors de l'écriture Go simultanément, lier une variable en même temps, et lorsque le résultat de l'opération simultanée revient, le résultat sera automatiquement affecté à la variable, éliminant la variable intermédiaire et rendant ainsi le programme plus concis. La mise en œuvre spécifique est la suivante:

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

Nous définissons une fonction G, où le paramètre t est la fonction Go à exécuter, ctx est le contexte du programme d'enregistrement, et f est la fonction d'affectation spécifique.

À ce stade, le cadre de programmation global peut être écrit comme similaire au modèle producteur-consommateur (avec quelques différences). Le producteur continue d'envoyer des tâches et le consommateur les exécute simultanément.

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

Il semble qu'une seule fonction simple ait été mise en œuvre après avoir fait le tour en cercle. En fait, la complexité du code a été grandement simplifiée. Nous n'avons qu'à nous soucier des tâches que le programme doit générer. Le programme worker() les exécutera automatiquement simultanément et renverra les résultats correspondants. La flexibilité s'est beaucoup améliorée.


Relationnée

Plus de