17. 5. 2022

5 4

Lectura de configuraciones de estrategia, variables, reglas y bloques de construcción en pocos pasos mediante Xml

Gracias a un ejemplo anterior : https://strategyquant.com/doc/programming-for-sq/viewing-and-changing-strategy-parameters-version-2/podemos leer una estrategia y sus variables.

Este ejemplo de código va un paso más allá leyendo el XML de una estrategia, sus variables y sus reglas.

 

1/ Visión general de una estrategia

  • Se puede leer una Estrategia Xml con el Función XMLUtil.elementToString(). 

Puede realizar un análisis personalizado XmlStrategyToFile o XmlStrategyToFileSym (para estrategias simétricas) para transformar cualquier estrategia de su Banco de Datos a su unidad a una ruta de salida como "C:Temp"

A continuación, puede abrir este archivo XML en cualquier lector de xml (como https://jsonformatter.org/xml-editor por ejemplo).

También puede leer una plantilla , si carga su plantilla en Databank.

(Véase el proyecto personalizado Project adjunto) StrategyToXmlFile y el Xml adjunto de una estrategia Estrategia 1.6.22(1)B)

 

  • A Las estrategias tienen reglas y Variables :

Si abre el Extensión SQ.utils.Bouillantencontrará una estructura similar para abrir una estrategia:

En "toBuildingBlocksName", podemos ver dos regiones del código , Variables y reglas también

 

2/ Estamos utilizando Clase XMLUtil y Elemento JDOM

https://strategyquant.com/sqxapi/com/strategyquant/lib/XMLUtil.html

 

3/ Cómo leer las variables de estrategia

Una vez que obtenemos el XML de una Estrategia, tenemos que obtener los valores de sus variables. Pueden ser Booleano, Enteroo Doble.

Para conseguirlos, tienes tres funciones :

  • getVariableValueToBoolean
  • getVariableValueToInt
  • getVariableValueToDouble

 

A partir de estas funciones, podemos obtener cualquier valor de las variables de una estrategia.

4/ Por ejemplo, podemos obtener un valor Stop loss o un valor Profit Target de los ajustes de la estrategia e insertar los resultados en un banco de datos :

Con esta extensión, puede encontrar un Análisis personalizado "CA_StrategySettings" o "CA_StrategySettingsSym"(para estrategias simétricas)

Estos análisis personalizados llamarán a SQ.utils.Bouillant y solicitar un valor Stop Loss o un valor Profit Target de una señal :

@Override
public boolean filterStrategy(String project, String task, String databankName, ResultsGroup rg) throws Exception
{
    Bouillant BouilltParaObj1 = new Bouillant();
    int IntTemp = BouilltParaObj1.getVariableValueToInt(rg, false, "LongProfitTarget");
 	rg.specialValues().set("CA_Long_ProfitTarget", IntTemp);
    IntTemp = BouilltParaObj1.getVariableValueToInt(rg, false, "ShortProfitTarget");
 	rg.specialValues().set("CA_Short_ProfitTarget", IntTemp);
    IntTemp = BouilltParaObj1.getVariableValueToInt(rg, false, "LongStopLoss");
 	rg.specialValues().set("CA_Long_StopLoss", IntTemp);
    IntTemp = BouilltParaObj1.getVariableValueToInt(rg, false, "ShortStopLoss");
 	rg.specialValues().set("CA_Short_StopLoss", IntTemp);
    IntTemp = BouilltParaObj1.getVariableValueToInt(rg, false, "LongTrailingStop");
 	rg.specialValues().set("CA_Long_TrailingStop", IntTemp);
    IntTemp = BouilltParaObj1.getVariableValueToInt(rg, false, "ShortTrailingStop");
 	rg.specialValues().set("CA_Short_TrailingStop", IntTemp);
    return true;
}

(Como se puede ver en el adjunto Custom Project : StrategySettings)

Una vez que ejecute "CA_StrategySettings" análisis personalizado o "CA_StrategySettingsSym" análisis personalizado , puede leer un valor de stop loss o un valor de objetivo de beneficio de cualquier configuración de estrategia y actualizar su banco de datos con los siguientes fragmentos :

Aquí están los Profit Valor objetivo y Stop Loss Valor de la configuración de la estrategia

 

 

5/ Cómo leer la estrategia XML paso a paso

(de nuestra función toBuildingBlocksName en SQ.Utils.Bouillant)

 

A/ Nuestro ejemplo utiliza getStrategyBase para obtener el raíz Elemento de una estrategia :

 

StrategyBase strategyBase = getStrategyBase(strategyRG, symmetricVariables);

Elemento Strategie1 = strategyBase.getStrategyXml();

 

B/ Del Estrategia1 Elementose está poniendo un niño concreto Elemento

 

Element elParams = Strategie1.getChild("Estrategia").getChild("Variables");

o

elParams = Strategie1.getChild("Strategy").getChild("Rules").getChild("Events"); // ir a la sección Rules del Xml de la Estrategia

 

C/ Del elParams Elementoestá recibiendo el elementos infantiles a un Lista de elementos paramElems

 

List paramElems = elParams.getChildren();

 

D/ De Lista de elementos paramElems, puedes consiga cada Elemento y leer el ValorNodo utilizando getNodeValue :

 

for (i = 0; i < paramElems.size(); i++)
{
    Elemento elParam = paramElems.get(i);

    String nombre = XMLUtil.getNodeValue(elParam, "nombre");
    String id = XMLUtil.getNodeValue(elParam, "id");

    if (name.equals(TradingSignalName)) // Buscamos el Id de TradingSignalName, necesario para encontrar la regla correspondiente
    {
        SignalID = id;
    }
}
E/ De Lista de elementos paramElems, puede obtener cada AtributoValor de un Elemento :

 

String elParamKey = elParam.getAttributeValue("key");

 

F/ De un elemento a una cadena 

Como para una estrategia, si quieres leer un Elemento y ver su estructurapuede utilizar la función XMLUtil.elementToString y enviarlo a un archivo.

String String1 = XMLUtil.elementToString(elParam);

 

6/ Aplicación : Cómo llamar a esta función, cómo utilizarla .

Con este ejemplo, tenemos fragmentos de columnas de DataBank para aplicar esta función :

Bouillant BouilltParaObj1 = new Bouillant();
String StringTotal = BouilltParaObj1.toBuildingBlocksName(results,false, "LongEntrySignal",100);

 

Esta función pide a los Building Blocks con a Grupo de resultados y a TradingSignal Nombre. (SeñalEntradaLarga, SeñalEntradaCorta, SeñalSalidaLarga, SeñalSalidaCorta,...)

Es realmente práctico porque puede seleccionar una señal de Entrada Larga, o de Entrada Corta, o de Salida Larga o Corta, o todas juntas

Incluso puede seleccionar cualquier nombre de señal de su plantilla.

Aquí está el código :

paquete SQ.Columns.Databanks;

import SQ.Utils.Bouillant;
import com.strategyquant.lib.L;
import com.strategyquant.tradinglib.*;
import com.strategyquant.tradinglib.optimization.WalkForwardMatrixResult;
import com.strategyquant.lib.ValuesMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

// Creado en Francia por Emmanuel Bouillant-Evrard para la Comunidad StrategyQuantX :)
public class BloquesDeEstrategia extends BancoDeDatosColumna
{
    public static final Logger Log = LoggerFactory.getLogger(StrategyBuildingBlocks.class);

    public StrategyBuildingBlocks() {
        super(L.tsq("Strategy Building Blocks"), DatabankColumn.Text, ValueTypes.Maximize, 0, 0, 1);

        setWidth(1000);
    }
    
    //------------------------------------------------------------------------

    @Override
    public double getNumericValue(ResultsGroup results, String resultKey, byte direction, byte plType, byte sampleType) throws Exception {
        return 0;
    }

    //------------------------------------------------------------------------
    
    @Override
    public String getValue(ResultsGroup results, String resultKey, byte direction, byte plType, byte sampleType) throws Exception
    {
        try
        {
            String StringTotal = "";
            Bouillant BouilltParaObj1 = new Bouillant();
            String String1 = BouilltParaObj1.toBuildingBlocksName(results,false, "LongEntrySignal",100); // 100 para tener el nombre de los Building blocks
            BouilltParaObj1 = new Bouillant();
            String String2 = BouilltParaObj1.toBuildingBlocksName(results,false, "ShortEntrySignal",100);
 
            if (String1 == null | String2 == null) { return "";}

            int maxLength = (String1.length() < 100)?String1.length():100;
            String1 = String1.substring(0, maxLength);

            maxLength = (String2.length() < 100)?String2.length():100;
            String2 = String2.substring(0, maxLength);

            if (!String1.equals("") && !String2.equals(""))
            {
                StringTotal += String1 + "," + String2;
            }
            else if (!String1.equals(""))
            {
                StringTotal += String1;
            }
            else if (!String2.equals(""))
            {
                StringTotal += String2;
            }
            return StringTotal;

        } catch(Exception e)
        {
            Log.error("Error StrategyBuildingBlocks", e);
            return ""; // "Error: " + e.getMessage();
        }
    }
}

 

7/ Los bloques de construcción Nombre de cada estrategia en el banco de datos

 

8/ El código de la función toBuildingBlocksName 

 

/**
     * Esta función lee el nombre de las variables, las reglas y devuelve una cadena con el nombre de los Building Blocks.
     * @param strategyRG
     * @param symmetricVariables
     * @param TradingSignal
     * @devuelve
     */
    public String toBuildingBlocksName(ResultsGroup strategyRG, boolean symmetricVariables, String TradingSignalName, int breakdownLevelMax) throws Exception
    {
        try
        {
            int i;
            String SignalID = "";
            String strName = strategyRG.getName();
            if(strName.startsWith("Cartera filtrada") || strName.startsWith("Cartera"))
            {
                return "";
            }
            StrategyBase strategyBase = getStrategyBase(strategyRG, symmetricVariables);
            
            Elemento Strategie1 = strategyBase.getStrategyXml();

            if (DebugMode){
            OutputPath = "C:³\Temp\"+strNombre+".txt";
            FileWriter myWriter = new FileWriter(OutputPath , true); }

            if (Strategie1 != null)
            {
                //#region ********************************************************* Variables **************************************************************************************
                String test4 = "" ;
                Element elParams = Strategie1.getChild("Estrategia").getChild("Variables");
                if (elParams != null)
                {
                    List paramElems = elParams.getChildren();
                    
                    VariableValues = new HashMap();
                    VariableID = new HashMap();
                    VariableType = new HashMap();

                    for (i = 0; i < paramElems.size(); i++)
                    {
                        Elemento elParam = paramElems.get(i);
                        if (elParam != null)
                        {
                            String name = XMLUtil.getNodeValue(elParam, "name");
                            String id = XMLUtil.getNodeValue(elParam, "id");
                            String value = XMLUtil.getNodeValue(elParam, "value");
                            String Tipo = XMLUtil.getNodeValue(elParám, "tipo");
                            VariableID.put(nombre, id);
                            VariableValues.put(nombre, valor);
                            VariableType.put(nombre, Tipo);

                            if (DebugMode){
                            test4 = XMLUtil.getNodeValue(elParam, "name") + " " + XMLUtil.getNodeValue(elParam, "id");
                            myWriter.write("nombre + id : "+ test4 + "\r\n");
                            myWriter.write("VariableID : "+ VariableID.get(name) + "\r\n");

                            test4 = XMLUtil.getNodeValue(elParam, "nombre") + " " + XMLUtil.getNodeValue(elParam, "valor");
                            myWriter.write("nombre + valor : "+ test4 + "\r\n");
                            myWriter.write("VariableValues : "+ VariableValues.get(name) + "\r\n");
                            
                            test4 = XMLUtil.getNodeValue(elParam, "nombre") + " " + XMLUtil.getNodeValue(elParam, "tipo");
                            myWriter.write("nombre + tipo : "+ prueba4 + "\r\n");
                            myWriter.write("TipoVariable : "+ VariableType.get(name) + "\r\n");}

                            if (name.equals(TradingSignalName)) // Buscamos el Id de la TradingSignalName, necesario para encontrar la regla correspondiente
                            {
                                SignalID = id;
                            }
                        }
                    }
                    if (DebugMode){
                    myWriter.close();}
                }
                //#endregion

                //#region ********************************************************* Rules ******************************************************************************************
                elParams = Strategie1.getChild("Strategy").getChild("Rules").getChild("Events"); // ir a la sección Rules del Xml de la Estrategia
                if (elParams != null)
                {
                    List paramElems = elParams.getChildren();
                    for (i = 0; i < paramElems.size(); i++)
                    {
                        Elemento elParam2 = paramElems.get(i);

                        if (elParam2 != null) {
                        String elParamKey2 = elParam2.getAttributeValue("clave");
                        if (elParamKey2.equals("OnBarUpdate")) // Busca la regla OnBarUpdate
                        {
                            List paramElems3 = elParam2.getChildren();
                            for (int i2 = 0; i2 < paramElems3.size(); i2++)
                            {
                                Elemento elParam3 = paramElems3.get(i2);
                                if (elParam3 != null) {
                                String elParamKey3 = elParam3.getAttributeValue("name");
                                if (elParamKey3.equals("Señales de negociación")) // Buscar la regla Señales de negociación
                                {
                                    Elemento elParams4 = elParam3.getChild("signals");
                                    List paramElems4 = elParams4.getChildren();
                                    for (int i3 = 0; i3 < paramElems4.size(); i3++)
                                    {
                                        Elemento elParam4 = paramElems4.get(i3);
                                        if (elParam4 != null) {
                                        String elParamKey4 = elParam4.getAttributeValue("variable");
                                        if (elParamKey4.equals(SignalID)) // Buscar el TradingSignalName solicitado a partir de su ID : SignalID
                                        {
                                            if (DebugMode){
                                            myWriter = new FileWriter(OutputPath , true);
                                            String String1 = XMLUtil.elementToString(elParam4);
                                            myWriter.write(String1);
                                            myWriter.close();}

                                            Elemento elParams5 = elParam4.getChild("Item");
                                            
                                            if (DebugMode){
                                            myWriter = new FileWriter(OutputPath , true);
                                            String String1 = XMLUtil.elementToString(elParams5);
                                            myWriter.write(String1);
                                            myWriter.close();}

                                            if (elParams5 != null) {
                                            String key = elParams5.getAttributeValue("key"); // el nombre
                                            if (!key.equals("Boolean"))
                                            {
                                                Element elParam5Temp = elParams5;
                                                Elemento elParam6Temp = elParams5;
                                                strName = strategyRG.getName();
                                                ArrayListElemsAll = new ArrayList();
                                                UpdateNodesValues(strategyRG, symmetricVariables, elParams5, breakdownLevelMax, 0);
                                                AddToList(strategyRG, symmetricVariables, elParams5, breakdownLevelMax, 0);
                                                if (!StrategyName2.equals(strName) && OutPutBlockMode)
                                                {
                                                    StrategyName2 = strName;
                                                    strategyBase = getStrategyBase(strategyRG, symmetricVariables);
                                                    Strategie1 = strategyBase.getStrategyXml();

                                                    OutputPath = "C:³\Temp\"+strNombre+"B.txt";
                                                    FileWriter myWriter = new FileWriter(OutputPath , false);
                                                    String String1 = XMLUtil.elementToString(Strategie1);
                                                    myWriter.write(String1+"\r\n");
                                                    myWriter.close();
                                                }

                                                StringBuilder sb = new StringBuilder(); // crear la cadena con el nombre de los Building Blocks
                                                if (ArrayListElemsAll.size()>=1)
                                                {
                                                    if (DebugMode){
                                                    myWriter = new FileWriter(OutputPath , true);
                                                    myWriter.write("ArrayListElemsAll.size() : "+ String.valueOf(ArrayListElemsAll.size()) + "\r\n");
                                                    String String1 = XMLUtil.elementToString(elParam5Temp);
                                                    myWriter.write(String1);
                                                    myWriter.close();}
                                                    for (int i5 = 0; i5 < ArrayListElemsAll.size(); i5++)
                                                    {
                                                        elParam6Temp = ArrayListElemsAll.get(i5);

                                                        if (elParam6Temp != null) {
                                                            String elParamKey8Temp = elParam6Temp.getAttributeValue("nombre"); // elParam6Temp.getAttributeValue("clave");
                                                            sb.append(elParamKey8Temp);
                                                            sb.append(ParamDelimiter);
                                                        }
                                                    }
                                                }
                                                return sb.toString();
                                            }}
                                        }}
                                    }
                                }}
                            }
                        }}
                    }
                }
                //#endregion
            }

            return "";
        } catch (Exception e) {
            if (DebugMode2){
            String strName = strategyRG.getName();
            OutputPath = "C:³\Temp\toBuildingBlocksName "+strName+".txt";
            FileWriter myWriter = new FileWriter(OutputPath , true);
            myWriter.write("Error : "+ strName +" "+ "\r\n");
            myWriter.write("Error : "+ e +"\r\n");
            StrategyBase strategyBase = getStrategyBase(strategyRG, symmetricVariables);
            Elemento Strategie1 = strategyBase.getStrategyXml();
            String String1 = XMLUtil.elementToString(Strategie1);
            myWriter.write(String1 + "\r\n");
            myWriter.close();}
            Log.error("Error toBuildingBlocksName", e);
            return "";
        }
    }

 

9/ Para leer cada Building Blocks, este ejemplo utiliza dos funciones recursivas : UpdateNodesValues y AddToList.

Estas funciones buscan cada Building Blocks sea cual sea la estructura XML de la estrategia.

Aquí está el Código :

   /**
    * Recursive function that read the Building Blocks Name from the Xml to update Nodes Values
    * @param strategyRG
    * @param symmetricVariables
    * @param Element
    * @param breakdownLevelMax
	 * @param breakdownLevel
    * @return
    */
   public void UpdateNodesValues(ResultsGroup strategyRG,  boolean symmetricVariables, Element element, int breakdownLevelMax, int breakdownLevel) throws Exception 
   {
       int i;
       if (element != null)
       {
           breakdownLevel = breakdownLevel + 1 ;
           List<Element> element1 = element.getChildren();
           if (element1.size() >= 1)
           {
               for (i = 0; i < element1.size(); i++) 
               {
                   Element element11 = element1.get(i);
                   if (element11 != null)
                   {
                       UpdateNodesValues(strategyRG, symmetricVariables, element11, breakdownLevelMax, breakdownLevel);  
                   }
               }
           }
       }

       if (element != null)
       {
           List<Element> listParams = element.getChildren("Param");
           if (listParams.size() >= 1)
           {
               boolean VariableFounded = false;
               for (i = 0; i < listParams.size(); i++) 
               {
                   Element courant = listParams.get(i);
                   if (courant != null) 
                   {
                       String elParamKey5 = courant.getAttributeValue("key");					    			// the name
                       String elParamVariable3 = courant.getAttributeValue("variable");					    // the variable
                       if (elParamKey5.startsWith("#") && elParamVariable3=="true")
                       {
                           String Temp1 =  VariableValues.get(courant.getText());
                           String Temp2 =  courant.getText();
                           if (Temp1 != null)
                           {
                               courant.setText(Temp1);
                           }
                           VariableFounded = true;
                       }
                   }
               }
           }
       }
   }

   /**
    * Recursive function that read the Building Blocks Name from the Xml to the ArrayList : ArrayListElemsAll
    * @param strategyRG
    * @param symmetricVariables
    * @param Element
    * @param breakdownLevelMax
	 * @param breakdownLevel
    * @return
    */
   public void AddToList(ResultsGroup strategyRG,  boolean symmetricVariables, Element element, int breakdownLevelMax, int breakdownLevel) throws Exception 
   {
       int i;
       boolean Condition1 = false;
       if (element != null)
       {
           breakdownLevel = breakdownLevel + 1 ;

           String elParamKey = element.getAttributeValue("key");
           String categoryType = element.getAttributeValue("categoryType");
           if (categoryType == null){categoryType = "";}
           if (breakdownLevelMax < 100)  { Condition1 = (elParamKey.equals("IsRising") || elParamKey.equals("IsFalling") || elParamKey.equals("IsLowerCount") || elParamKey.equals("IsGreaterCount") || elParamKey.equals("IsLower") || elParamKey.equals("IsLowerOrEqual") || elParamKey.equals("IsGreater") || elParamKey.equals("IsGreaterOrEqual") || elParamKey.equals("CrossesAbove") || elParamKey.equals("CrossesBelow") || elParamKey.startsWith("CBlock")); }
           if (!Condition1)                                              
           {
               List<Element> element1 = element.getChildren();
               if (element1.size() >= 1)
               {
                   for (i = 0; i < element1.size(); i++) 
                   {
                       Element element11 = element1.get(i);
                       if (element11 != null)
                       {
                           AddToList(strategyRG, symmetricVariables, element11, breakdownLevelMax, breakdownLevel); 
                       }
                   }
               }
           }

           List<Element> listParams = element.getChildren("Param");
           if (listParams.size() >= 1 || Condition1)    
           {
               Element elementCopy = (Element)element.clone();
               elParamKey = elementCopy.getAttributeValue("key");
                   listParams = elementCopy.getChildren("Param");
                   List<Element> listParamsBlock = element.getChildren("Block");

                   if (listParamsBlock.size() == 0 || Condition1)   
                   {
                           if ((listParams.size() == 1 && !elParamKey.equals("Number")) || !elParamKey.equals("Number"))
                           {
                               if (breakdownLevel <= breakdownLevelMax)
                               {
                                   ArrayListElemsAll.add(elementCopy); 
                               }
                           }
                   }

                   if (breakdownLevel <= breakdownLevelMax && OutPutBlockMode)
                   {
                       String strName = strategyRG.getName();
                       OutputPath = "C:\\Temp\\"+strName+".txt";
                       FileWriter myWriter = new FileWriter(OutputPath , true); 
                       String String1 = XMLUtil.elementToString(elementCopy);
                       myWriter.write(String1+"\r\n");
                       myWriter.write("________________________________________________________________________________________________________________________________________________________________________________________________________________"+"\r\n");
                       myWriter.close();
                   }

           }
       }
   }

10/ Conclusión

En Resumen, es sencillo, solemos empezar leyendo la estructura del fichero XML desde el archivo XMLUtil.elementToString entonces estamos utilizando las funciones anteriores (A,B,C,D,E)

Podemos encontrar más funciones si es necesario en :

https://strategyquant.com/sqxapi/com/strategyquant/lib/XMLUtil.html

 

Fuente de información :

https://strategyquant.com/doc/programming-for-sq/viewing-and-changing-strategy-parameters-version-2/

https://www.w3schools.com/xml/default.asp

https://strategyquant.com/sqxapi/com/strategyquant/lib/XMLUtil.html

https://www.tutorialspoint.com/java_xml/java_jdom_parse_document.htm

 

Un útil lector de Xml :

https://jsonformatter.org/xml-editor

 

Me llamo Emmanuel Bouillant-Evrard, Ingeniero especializado en Finanzas. He trabajado en Investigación y Desarrollo en Finanzas en EE.UU., Canadá y Francia durante 24 años.

 

Suscríbase a
Notificar a
4 Comentarios
Más antiguo
Más reciente Más votados
Feedbacks de Inline
Ver todos los comentarios
clonex / Ivan Hudec
7. 6. 2022 17:21

excelente

innggo
8. 7. 2023 12:31 pm

Gracias, Emmanuel.

Jordan
13. 11. 2023 7:24 am

Gran trabajo realizado