Documentation
Applications
Dernière mise à jour le 11. 1. 2023 par Mark Fric
Sélection programmatique de blocs de construction
Contenu des pages
Il s'agit d'une extension de cet article : https://strategyquant.com/doc/programming-for-sq/changing-task-config-programmatically/
qui a démontré comment vous pouvez modifier la configuration des tâches de manière programmatique.
L'idée générale de l'exemple initial est que vous pouvez modifier la configuration d'une tâche en manipulant sa configuration XML et en la réappliquant à la tâche.
Dans cet exemple, nous allons montrer comment vous pouvez activer/désactiver les blocs de construction de cette manière.
Comment les blocs de construction sont stockés dans le XML de la tâche
Tous les blocs de construction sont stockés en tant qu'enfants et sous-enfants dans l'élément ->.
Chaque bloc de construction est configuré dans son propre élément , identifié de manière unique par son élément clé - qui est le nom de son extrait.
Il existe quelques normes en matière de valeurs clés :
- s'il est bloc de signaux ou comparaisonla clé ne contient que le nom de l'extrait, par exemple key="ADXChangesDown" ou key="IsGreater"
- s'il est indicateur (pas de signal), sa clé est précédée de la chaîne "Indicateur", par exemple key="Indicators.ADX"
- s'il est prixsa clé est préfixée par la chaîne "Prix", par exemple key="Prix.Haut"
- s'il est niveau d'arrêt/limite (pour les ordres Stop ou Limite), sa clé est préfixée par la chaîne "Niveaux de prix Stop/Limite", par exemple key="Niveaux de prix stop/limite.TEMA"
- s'il est plage d'arrêt/limite (pour les ordres Stop ou Limite), sa clé est préfixée par la chaîne "Plages de prix Stop/Limite", par exemple key="Fourchette de prix Stop/Limite.BBWidthRatio"
Un autre attribut important de l'élément est utiliser. Si vous voulez que le bloc soit utilisé pendant la construction, vous devez le mettre à "true", sinon à "false".
Ainsi, si vous souhaitez activer ou désactiver un bloc particulier, il vous suffit de le faire :
- trouver l'élément de ce dernier
- définir l'attribut use à true ou false comme ceci : ...
Un exemple de XML de tâche de construction est joint à cet article - fichier Build-Task1.xml
Exemple
Pour illustrer cette fonctionnalité, nous allons basculer de manière programmatique entre les blocs de signaux Keltner Channel (KC) et Bollinger Bands (BB), tous les autres blocs étant désactivés.
Nous aurons un projet personnalisé avec deux tâches - la première sera la tâche d'analyse personnalisée qui appliquera notre snippet d'analyse personnalisée. La seconde est la tâche Builder - nous allons modifier la configuration de cette tâche Builder dans notre snipet CA.
Ainsi, lorsque vous exécutez le projet personnalisé pour la première fois, seuls les blocs de signaux de bandes de Bollinger sont activés. Lors de la deuxième exécution, seuls les blocs du canal de Keltner sont activés, et ainsi de suite.
Tous les blocs de signaux des bandes de Bollinger ont des extraits nommés avec le préfixe BB - BB*********, par exemple clé="BBBarClosesAboveDown", et tous les blocs de signaux du canal de Keltner ont des extraits nommés KC*********, par exemple clé="KCBarClosesAboveLower".
Nous utiliserons le préfixe BB ou KC pour reconnaître qu'il s'agit d'un bloc de signaux du canal de Keltner ou des bandes de Bollinger.
L'exemple ci-dessous est essentiellement le même que celui de l'article https://strategyquant.com/doc/programming-for-sq/changing-task-config-programmatically/ - Seulement ici, nous faisons des choses différentes avec le XML.
Nous utilisons la norme JDOM pour parcourir le XML et obtenir ou modifier ses attributs.
Étape 1 - Obtenir tous les éléments du bloc
Element elBlocks = XMLUtil.getChildElem(elNewConfig, "Blocks") ; if(elBlocks == null) { throw new Exception("No element exists, is it Builder task ?") ; } Element buildingBlocks = XMLUtil.getChildElem(elBlocks, "BuildingBlocks") ; // vous pouvez également charger la configuration de la nouvelle tâche à partir d'un fichier préparé //Elément elNewConfig = XMLUtil.fileToXmlElement(new File("c:/BuildTask2009_2019.xml")) ; List blocks = buildingBlocks.getChildren("Block") ;
Étape 2 - Initialisation de la variable activeBlock
nous utiliserons cette variable pour déterminer si les blocs BB ou KC doivent être utilisés - n'oubliez pas que nous passons d'un bloc BB à un bloc KC, et que nous devons donc déterminer lequel de ces deux blocs doit être activé ou désactivé.
// nous utiliserons cette variable pour passer de BB à KC. Les valeurs sont les suivantes // 0 - inconnu, sera défini par le premier bloc trouvé // 1 - Les blocs BB doivent être actifs // 2 - Les blocs KC doivent être actifs int activeBlock = 0 ;
Étape 3 - Passer en revue tous les blocs en boucle
for(int i=0 ; i<blocks.size() ; i++) { Element elBlock = blocks.get(i) ; String key = elBlock.getAttributeValue("key") ;
Étape 4 - Si la clé ne commence pas par BB ou KC, il s'agit d'un bloc différent qui doit être désactivé.
if(!key.startsWith("BB") && !key.startsWith("KC")) { // il ne s'agit pas d'un bloc de bandes de Bollinger ou de canal de Keltner, désactivez-le elBlock.setAttribute("use", "false") ; continuer ; }
Étape 5 - Sinon, il s'agit d'un bloc KC ou BB
Reconnaissez maintenant la valeur correcte de la variable activeBlock :
// il s'agit d'un bloc BB ou KC String use = elBlock.getAttributeValue("use") ; if(activeBlock == 0) { // nous déterminerons si les blocs BB ou KC doivent être actifs en fonction du premier bloc trouvé if(key.startsWith("BB")) { if (use.equals("true")) { // le bloc BB était actif avant, maintenant c'est le bloc KC qui sera actif activeBlock = 2 ; } } else if(key.startsWith("KC")) { if(use.equals("true")) { // KC était actif avant, maintenant BB sera actif activeBlock = 1 ; } } if(activeBlock == 0) { activeBlock = 1 ; } Log.info("----- Tournant sur "+(activeBlock == 1 ? "Bollinger Bands" : "Keltner Channel")+" blocs.") ; }
Étape 6 - l'essentiel
tourner les blocs BB ou KC sur ON en fonction de l'état d'avancement du projet. bloc actif en fixant leur attribut use à true ou false :
// maintenant, activer ou désactiver le bloc en fonction de la valeur de activeBlock if(key.startsWith("BB"))) { elBlock.setAttribute("use", (activeBlock == 1 ? "true" : "false")) ; } else if(key.startsWith("KC")) { elBlock.setAttribute("use", (activeBlock == 2 ? "true" : "false")) ; }
Étape 7 - Appliquer la configuration modifiée à la tâche
Nous avons fini de passer en revue tous les blocs de construction, il ne reste plus qu'à appliquer la configuration modifiée à la tâche :
// Appliquer la configuration modifiée à la tâche buildTask.setConfig(elNewConfig, true) ; // ceci notifie l'interface utilisateur de charger la configuration modifiée et de l'appliquer à l'interface utilisateur. // Sans cela, cela fonctionnerait toujours mais vous ne verriez pas les changements dans l'interface utilisateur. JSONObject jsonData = new JSONObject().put("projectConfig", sqProject.toJSON()) ; DataToSend dataToSend = new DataToSend(WebSocketConst.UpdateProject, jsonData) ; SQWebSocketManager.addToDataQueue(dataToSend, SQConst.CODE_TASKMANAGER) ;
Et c'est tout.
Désormais, chaque fois que vous démarrerez le projet personnalisé, les blocs de construction alterneront entre les signaux des bandes de Bollinger et ceux du canal de Keltner.
Code complet de l'extrait CAChangeBlocksConfig :
package SQ.CustomAnalysis ; import com.strategyquant.lib.XMLUtil ; import com.strategyquant.lib.constants.SQConst ; import com.strategyquant.tradinglib.CustomAnalysisMethod ; import com.strategyquant.tradinglib.ResultsGroup ; import com.strategyquant.tradinglib.project.ProjectEngine ; import com.strategyquant.tradinglib.project.SQProject ; import com.strategyquant.tradinglib.project.websocket.DataToSend ; import com.strategyquant.tradinglib.project.websocket.SQWebSocketManager ; import com.strategyquant.tradinglib.project.websocket.WebSocketConst ; import com.strategyquant.tradinglib.taskImpl.ISQTask ; import org.jdom2.Element ; import org.json.JSONObject ; import java.util.ArrayList ; import java.util.List ; public class CAChangeBlocksConfig extends CustomAnalysisMethod { //------------------------------------------------------------------------ //------------------------------------------------------------------------ //------------------------------------------------------------------------ public CAChangeBlocksConfig() { super("CAChangeBlocksConfig", TYPE_PROCESS_DATABANK) ; } //------------------------------------------------------------------------ @Override public ArrayList processDatabank(String project, String task, String databankName, ArrayList databankRG) throws Exception { // récupération du projet en cours SQProject sqProject = ProjectEngine.get(project) ; // Obtention d'une tâche par son nom ISQTask buildTask = sqProject.getTaskByName("Build strategies") ; if(buildTask == null) { throw new Exception("No such task exists !") ; } // vous pouvez également utiliser sqProject.getTasks() pour obtenir une liste de toutes les tâches // et les parcourir pour obtenir celle que vous voulez // voici comment obtenir les paramètres XML des tâches de la nouvelle manière (SQ 136 up) // Il renvoie un élément XML JDOM avec la configuration complète de la tâche Element elConfig = buildTask.getConfig() ; // créer une nouvelle configuration en la clonant - il est important de faire un clone, // sinon votre nouvelle configuration ne sera pas appliquée Elément elNewConfig = elConfig.clone() ; // modifiez maintenant tout ce qui se trouve dans la nouvelle configuration Element elBlocks = XMLUtil.getChildElem(elNewConfig, "Blocks") ; if(elBlocks == null) { throw new Exception("No element exists, is it Builder task ?") ; } Element buildingBlocks = XMLUtil.getChildElem(elBlocks, "BuildingBlocks") ; // alternativement, vous pouvez charger la configuration de la nouvelle tâche à partir d'un fichier préparé //Elément elNewConfig = XMLUtil.fileToXmlElement(new File("c:/BuildTask2009_2019.xml")) ; List blocks = buildingBlocks.getChildren("Block") ; // nous utiliserons cette variable pour passer de BB à KC. Les valeurs sont les suivantes // 0 - inconnue, sera définie par le premier bloc trouvé // 1 - Les blocs BB doivent être actifs // 2 - Les blocs KC doivent être actifs int activeBlock = 0 ; for(int i=0 ; i<blocks.size() ; i++) { Element elBlock = blocks.get(i) ; String key = elBlock.getAttributeValue("key") ; if(!key.startsWith("BB") && !key.startsWith("KC")) { // il ne s'agit pas d'un bloc de bandes de Bollinger ou de canal de Keltner, désactivez-le elBlock.setAttribute("use", "false") ; continuer ; } // il s'agit d'un bloc BB ou KC String use = elBlock.getAttributeValue("use") ; if(activeBlock == 0) { // nous déterminerons si les blocs BB ou KC doivent être actifs en fonction du premier bloc trouvé if(key.startsWith("BB")) { if (use.equals("true")) { // le bloc BB était actif avant, maintenant c'est le bloc KC qui sera actif activeBlock = 2 ; } } else if(key.startsWith("KC")) { if(use.equals("true")) { // KC était actif avant, maintenant BB sera actif activeBlock = 1 ; } } if(activeBlock == 0) { activeBlock = 1 ; } Log.info("----- Tourner sur "+(activeBlock == 1 ? "Bollinger Bands" : "Keltner Channel")+" blocs.") ; } // active ou désactive maintenant le bloc en fonction de la valeur de activeBlock if(key.startsWith("BB"))) { elBlock.setAttribute("use", (activeBlock == 1 ? "true" : "false")) ; } else if(key.startsWith("KC")) { elBlock.setAttribute("use", (activeBlock == 2 ? "true" : "false")) ; } } // Appliquer la configuration modifiée à la tâche buildTask.setConfig(elNewConfig, true) ; // ceci notifie l'interface utilisateur de charger la configuration modifiée et de l'appliquer à l'interface utilisateur. // Sans cela, cela fonctionnerait toujours mais vous ne verriez pas les changements dans l'interface utilisateur. JSONObject jsonData = new JSONObject().put("projectConfig", sqProject.toJSON()) ; DataToSend dataToSend = new DataToSend(WebSocketConst.UpdateProject, jsonData) ; SQWebSocketManager.addToDataQueue(dataToSend, SQConst.CODE_TASKMANAGER) ; return databankRG ; } }
Cet article a-t-il été utile ? L'article était utile L'article n'était pas utile
Merci Mark pour cet excellent exemple
Il sera très utile