Documentación

Aplicaciones

Última actualización el 29. 9. 2022 by Mark Fric

Uso de la configuración de backtest en las métricas de la estrategia

En este ejemplo veremos cómo podemos obtener y utilizar la configuración actual del backtest - como por ejemplo el tamaño del spread - en el cálculo de las métricas del backtest (columnas del banco de datos).

 

Esto fue solicitado por un usuario - la pregunta exacta era cómo él puede conseguir el ajuste de la extensión usado en el backtest de la estrategia para computar una nueva métrica especial para la estrategia.

 

Vía 1 - en el método getValue() de DatabankColumn

En este ejemplo se puede ver cómo puede funcionar en principio. Podemos utilizar el método getLastSettings() de Grupo de resultados que devolverá una cadena, que puede transformarse en un elemento XML que contenga la estructura de la configuración del backtest.

 

            String lastSettingsXml = results.getLastSettings();
            if(lastSettingsXml != null) {
                Elemento elSettings = XMLUtil.stringToElement(lastSettingsXml);

 

La estructura XML de elSettings está más allá de este artículo, puede revisar el XML en el archivo .cfx de configuración de su proyecto o en el archivo de estrategia (.sqx).

Ambos ficheros son archivos ZIP que se pueden abrir con WinZip o WinRar y en los que se puede consultar la configuración del proyecto.

La parte que nos interesa está aquí:


Queremos recuperar el diferencial, y podemos hacerlo así:

Elemento elData = elSettings.getChild("Datos");
Elemento elSetups = elData.getChild("Setups");
Elemento elSetup = elSetups.getChild("Configuración");
Elemento elChart = elSetup.getChild("Chart");

double spread = Double.parseDouble(elChart.getAttributeValue("spread"));

Ahora que tenemos el spread, podemos simplemente mostrarlo convirtiéndolo a String y devolviéndolo como resultado de nuestro comando getValue() véase el código completo del fragmento a continuación.

Tenga en cuenta que también utilizamos resultados.valoresespeciales().getDouble() y .set() para "almacenar en caché" el valor de dispersión recuperado - es para que no tengamos que analizar el XML cada vez que se calcula esta métrica. De esta forma, sólo se analizará una vez por estrategia.

 

El inconveniente

El problema es que estamos utilizando un método especial DatabankColumn.getValue() y no el estándar DatabankColumn.compute().

La diferencia es que el método getValue() en la columna del banco de datos es llamado cuando el valor es mostrado en SQ UI, DESPUÉS de que la estrategia fue insertada en el banco de datos, y devuelve texto, no un número.

Este tipo de columna de la base de datos no se puede utilizar en el filtrado ni en el cálculo de otras columnas de la base de datos.

 

Lo hacemos de esta manera porque en las versiones de StrategyQuantX anteriores a la Build 136 Dev 5 (que se publicó el 3 de noviembre de 2022) los últimos ajustes se guardaban en la estrategia en el momento en que ésta se añadía al banco de datos, después de que se calcularan todas sus métricas.

Código completo del fragmento:

paquete SQ.Columns.Databanks;

import com.strategyquant.lib.*;
import com.strategyquant.datalib.*;
import com.strategyquant.tradinglib.*;

import org.jdom2.Element;

public class Spread1 extends DatabankColumn {
    
    private static final String SpreadKey = "BacktestSpread";
    
    public Spread1() {
        super("Spread1", DatabankColumn.Text, ValueTypes.Minimize, 0, 0, 10000);

        setTooltip("Spread en el que se hizo la prueba (como texto)");
        setWidth(150);
        printsSpecialValue(true);
    }
    
  //------------------------------------------------------------------------

    @Override
    public String getValue(ResultsGroup results, String resultKey, byte direction, byte plType, byte sampleType) throws Exception {
        try {
            if(results.specialValues().containsKey(SpreadKey)) {
                return results.specialValues().getDouble(SpreadKey)+"";
            }
            
            String lastSettingsXml = results.getLastSettings();
            if(lastSettingsXml != null) {
                Elemento elSettings = XMLUtil.stringToElement(lastSettingsXml);
                Elemento elData = elSettings.getChild("Data");
                Elemento elSetups = elData.getChild("Setups");
                Element elSetup = elSetups.getChild("Configuración");
                Elemento elChart = elSetup.getChild("Chart");

                double spread = Double.parseDouble(elChart.getAttributeValue("spread"));
                results.specialValues().set(SpreadKey, spread);

                return Double.toString(spread);
            }

        } catch(Exception e) {
            Log.error("Exc.", e);
        }
        
        return NOT_AVAILABLE;
    }
}

 

Forma 2 - en el método DatabankColumn compute()

Nota: este método sólo funcionará en SQX Build 136 Dev 5 (publicado el 3 de noviembre de 2022) y posteriores.

El principio fundamental es el mismo, sólo utilizamos calcular() para la columna del banco de datos, que se llama cuando se calculan las métricas de la estrategia. Esto significa que podrá utilizar este valor en el filtrado y puede obtener su valor en otras columnas del banco de datos - sólo tiene que configurar la dependencia adecuada utilizando el método setDependencies().

De este modo, el valor del diferencial se recupera de la última configuración de backtest y se almacena en las métricas.

 

Código completo del fragmento:

paquete SQ.Columns.Databanks;

import com.strategyquant.lib.*;
import com.strategyquant.datalib.*;
import com.strategyquant.tradinglib.*;

import org.jdom2.Element;

public class Spread2 extends DatabankColumn {
    
  private static final String SpreadKey = "BacktestSpread";

    public Spread2() {
        super("Spread2",
          DatabankColumn.Decimal2, // formato de visualización del valor
          ValueTypes.Minimize, // si el valor debe maximizarse / minimizarse / aproximarse a un valor
          0, // valor objetivo si se ha elegido la aproximación
          0, // mínimo medio de este valor
          5); // máximo medio de este valor
        
    setWidth(80); // ancho de columna por defecto en píxeles
    
        setTooltip("Spread en el que se hizo la prueba (como número)");
    }
  
  //------------------------------------------------------------------------

    @Override
    //public double compute(SQStats stats, StatsTypeCombination combination, OrdersList ordersList, SettingsMap settings, SQStats statsLong, SQStats statsShort) throws Exception {
    public double compute(SQStats stats, StatsTypeCombination combination, OrdersList ordersList, SettingsMap settings, SQStats statsLong, SQStats statsShort, Result result) throws Exception {
    	
        try {
      		if(resultado == null) {
        	    return -1;
      		}

      		ResultsGroup results = result.getResultsGroup();
      		if(resultados == null) {
        	    return -2;
      		}

            if(results.specialValues().containsKey(SpreadKey)) {
            return results.specialValues().getDouble(SpreadKey);
            }
            
            String lastSettingsXml = results.getLastSettings();
            if(lastSettingsXml == null) {
        	        return -3;
           	    }

            Element elSettings = XMLUtil.stringToElement(lastSettingsXml);
            Elemento elData = elSettings.getChild("Data");
            Element elSetups = elData.getChild("Setups");
            Element elSetup = elSetups.getChild("Configuración");
            Elemento elChart = elSetup.getChild("Chart");
        
            double spread = Double.parseDouble(elChart.getAttributeValue("spread"));
            results.specialValues().set(SpreadKey, spread);
            
            return spread;

        } catch(Exception e) {
        Log.error("Exc.", e);
        }
        
        return -4;
    }
}

 

 

 

¿Le ha resultado útil este artículo? El artículo era útil El artículo no era útil

Suscríbase a
Notificar a
0 Comentarios
Feedbacks de Inline
Ver todos los comentarios