Documentation

Applications

Dernière mise à jour le 24. 5. 2022 par Mark Fric

Backtesting de la stratégie par programme, y compris les tests de robustesse

Cet article est la suite de l'article précédent Exécution programmée de backtests de stratégie.

 

Il montrera comment exécuter un backtest de manière programmatique, en incluant cette fois des contrôles croisés sélectionnés (tests de robustesse). Le principe du backtest programmatique est le même, nous ne l'expliquerons pas à nouveau ici.

Nous n'expliquerons que les nouveautés.

 

Utilisation de processDatabank() pour exécuter le backtest d'une stratégie

Comme dans l'exemple précédent, nous utiliserons l'extrait CustomAnalysis et sa méthode processDatabank(). Ici, nous choisirons la première stratégie de la banque de données et nous effectuerons un backtest + des tests de robustesse sur cette stratégie.

Le code de la méthode processDatabank() est le suivant :

//------------------------------------------------------------------------

@Override
public ArrayList processDatabank(String project, String task, String databankName, ArrayList databankRG) throws Exception {
    if(databankRG.size() == 0) {
        return databankRG ;
    }

    // récupérer la première stratégie de la banque de données pour effectuer un nouveau test sur celle-ci
    ResultsGroup strategyToRetest = databankRG.get(0) ;

    //------------------------------------
    // CONFIGURATION PRINCIPALE DU BACKTEST
    ResultsGroup backtestResultRG = runMainBacktest(strategyToRetest) ;

    //------------------------------------
    // VÉRIFICATIONS CROISÉES
    runAndSaveCrossChecks(backtestResultRG, strategyToRetest.getName()) ;

    // Obtenir les détails du résultat du backtest
    int trades = backtestResultRG.portfolio().stats(Directions.Both, PlTypes.Money, SampleTypes.FullSample).getInt(StatsKey.NUMBER_OF_TRADES) ;
    double profit = backtestResultRG.portfolio().stats(Directions.Both, PlTypes.Percent, SampleTypes.FullSample).getDouble(StatsKey.NET_PROFIT) ;

    // faire quelque chose avec les nouveaux résultats du backtest
    // Le ResultsGroup contient maintenant le backtest principal + toutes les vérifications croisées configurées.
    // voir : https://strategyquant.com/doc/programming-for-sq/working-with-resultsgroup/
    // sur la manière d'obtenir les résultats individuels


    // ici nous allons juste sauvegarder la stratégie nouvellement backtestée dans la banque de données cible
    Databank targetDatabank = ProjectEngine.get(project).getDatabanks().get("Results") ;

    targetDatabank.add(backtestResultRG, true) ;

    return databankRG ;
}

 

Vous pouvez voir que nous avons deux sous-méthodes ici :

  • runMainBacktest() exécute le backtest principal de la stratégie et produit Groupe de résultats avec le résultat du backtest. Cette méthode est la même que dans l'exemple original et ne sera pas expliquée ici.
  • runAndSaveCrosschecks() effectue les contrôles croisés spécifiés et les place tous dans le même dossier. Groupe de résultats en tant que résultats distincts

Il enregistre ensuite ce nouveau résultat dans une banque de données cible.

 

 

Configuration des contrôles croisés

Les contrôles croisés dans SQX sont implémentés comme des plugins, et chaque contrôle croisé a une méthode runTest() qui effectuera un contrôle croisé de la stratégie.

Ainsi, lorsque les contrôles croisés sont configurés, il suffit d'appeler cette méthode pour chaque contrôle croisé à effectuer.

La création / configuration de la vérification croisée est le défi ici, elle est faite dans une sous-méthode. configureCrosschecks() - cette méthode renvoie un tableau de contrôles croisés, qui sont ensuite exécutés un par un.

 

Il existe d'autres façons de créer des configurations de contrôle croisé, mais la plus simple, tant pour la programmation que pour une utilisation normale, est de les laisser simplement se créer à partir du format XML dans lequel SQX les stocke. C'est la méthode que nous utilisons ici.

 

Le code de configureCrosschecks() et quelques sous-méthodes :

   //------------------------------------------------------------------------

   private ArrayList configureCrosschecks() throws Exception {
       ArrayList crossChecks = new ArrayList() ;

       crossChecks.add( createFromXml("c:\NRetestWithHigherPrecision.xml") ) ;
       crossChecks.add( createFromXml("c:\NMonteCarloManipulation.xml") ) ;
       crossChecks.add( createFromXml("c:\NMonteCarloRetest.xml") ) ;

       return crossChecks ;
   }

   //------------------------------------------------------------------------

   private ICrossCheck createFromXml(String xmlFile) throws Exception {
       Element elXml = XMLUtil.fileToXmlElement(new File(xmlFile)) ;

       String ccName = elXml.getName() ;

       ICrossCheck crossCheck = getCrossCheckPlugin(ccName) ;
       if(crossCheck != null) {
           crossCheck.readSettings(elXml, null) ;
       }
       else {
           throw new Exception ("Cannot find cross check plugin '" + ccName + "'") ;
       }

       return crossCheck ;
   }

   //------------------------------------------------------------------------

   private ICrossCheck getCrossCheckPlugin(String name) {
       ArrayList plugins = SQPluginManager.getPlugins(ICrossCheck.class) ;

       for(int i=0 ; i<plugins.size() ; i++) {
           if(plugins.get(i).getSettingName().equals(name)) {
               return plugins.get(i).clone(null) ;
           }
       }

       return null ;
   }

 

Vous pouvez voir que la configuration du contrôle croisé est créée par la méthode createFromXml() qui reçoit un fichier XML en paramètre. Ce fichier XML est la définition de la vérification croisée donnée.

La méthode commence par obtenir un clone du plugin pour le contrôle croisé concerné en appelant la fonction getCrossCheckPlugin(pluginName)et appelle ensuite simplement readSettings(xml) sur l'objet pour l'initialiser avec les paramètres du XML.

Ensuite, l'objet de configuration du contrôle croisé est prêt à être exécuté.

 

Dans notre exemple, nous créons trois contrôles croisés :

  • Retest avec un horizon temporel plus élevé
  • Manipulation de Monte Carlo avec quelques méthodes sélectionnées
  • Retest de Monte Carlo avec des méthodes sélectionnées

Nous disposons d'un fichier XML distinct contenant la configuration de chacun d'entre eux.

 

Comment préparer le fichier de configuration XML du contrôle croisé ?

L'approche la plus simple consiste à utiliser l'interface utilisateur SQX pour configurer les paramètres exacts de la vérification croisée que vous souhaitez utiliser dans le projet Builder ou Retester.

Sauvegardez ensuite l'ensemble du projet Builder/Retester dans un fichier .cfx. Ce fichier porte l'extension .cfx, mais il s'agit d'un fichier ZIP standard que vous pouvez ouvrir avec WinZip ou WinRar.

À l'intérieur du fichier, vous trouverez config.xml - il s'agit du document XML qui contient les paramètres de l'ensemble du projet.

Voici la section <CrossChecks> et de là, copier et coller le XML du contrôle croisé que vous souhaitez dans un fichier séparé que vous chargerez plus tard dans notre extrait d'analyse personnalisé.

 

Exemple de fichier RetestWithHigherPrecision.xml :

2
    3
  
  
    
      
        
          
        
        =" />
        
          
        
      
      
        
          
        
        =" />
        
          
        
      
      
        
          
        
        <Comparateur value="

 

Exemple de fichier MonteCarloManipulation.xml :

resampling
        
      
      
        
          10
        
      
    
    10
    false

 

Exemple de fichier MonteCarloRetest.xml :

20
          10 10
          20 10
          10 10
          true
        
      
      
        
          40
        
      
      
        
          0.0> Param
          10.0
        
      
      
        
          0.0> Param
          5.0
        
      
      
        
          1.0
          5.0
        
      
      
        
          100
        
      
      
        
          10> Param
          20 Synergique
          true
        
      
      
        
          10
          20 20
          true
          true true
          false
          true true
          true true
          true true
          true true
          true true
          false
          false
          true
        
      
    
    10
    false
    -1

 

 

 

Vérifications croisées

Lorsque les objets de configuration des contrôles croisés sont prêts, nous lançons les contrôles croisés en appelant simplement leur fonction runTest() méthode.

Code :

private void runAndSaveCrossChecks(ResultsGroup mainResult, String strategyName) throws Exception {
    ArrayList crossChecks = configureCrosschecks() ;

    StopPauseEngine stopPauseEngine = new StopPauseEngine() ;

    for(int i=0 ; i<crossChecks.size() ; i++) {

        ICrossCheck crossCheck = crossChecks.get(i) ;
        crossCheck.setStopPauseEngine(stopPauseEngine) ;

        try {
            Log.info(String.format("Running cross check %s for %s...", crossCheck.getName(), strategyName)) ;

            boolean ccResult = crossCheck.runTest(mainResult, i, globalATR, null, true, null, strategyName) ;

            if(!ccResult) {
                // décommentez si vous voulez arrêter l'exécution des autres contrôles croisés si l'un d'entre eux ne passe pas
                // sinon toutes les vérifications croisées sont exécutées sur la stratégie
                //return ;
            }

        } catch(Exception e) {
            Log.error("Exception de contrôle croisé : "+e.getMessage(), e) ;
        }
    }
}

 

Exécution de cet extrait d'analyse personnalisée

Lorsque vous compilez et exécutez ce snippet, le résultat est le suivant. Il prend la première stratégie de la banque de données, effectue un backtest et les 3 contrôles croisés que nous avons configurés sur elle et l'enregistre comme un nouveau résultat dans la banque de données.

Vous pouvez constater que le nouveau résultat contient également des résultats de Monte Carlo

 

 

Cet article a-t-il été utile ? L'article était utile L'article n'était pas utile

S'abonner
Notification pour
1 Commentaire
Le plus ancien
Le plus récent Le plus populaire
Commentaires en ligne
Afficher tous les commentaires
Emmanuel
25. 5. 2022 12:37 pm

Excellent ! !!! cela sera très utile
Merci de votre attention.

Postes connexes