Documentación
Aplicaciones
Última actualización el 21. 7. 2022 by Mark Fric
Fusionar varios resultados en una cartera
Contenido de la página
En este artículo mostraremos cómo StrategyQuant X maneja los resultados de backtest, y cómo podemos fusionarlos en la cartera.
Esto ya se puede hacer en SQX seleccionando varias estrategias y eligiendo Cartera -> Fusionar estrategiaspero mostraremos cómo se hace en el fondo.
Esto pretende ser una primera parte de una serie múltiple, nos gustaría utilizar esta funcionalidad para explorar si el comercio podría mejorarse mediante la selección de subconjunto particular de las estrategias para el comercio - esto será examinado en los próximos artículos.
Tenga en cuenta que por fusión en cartera nos referimos a la fusión de los resultados finales de las pruebas retrospectivas en un resultado de cartera, no a la fusión de estrategias de negociación individuales.
Esta función se presenta de nuevo en forma de fragmento de análisis personalizado, y el fragmento completo se adjunta a este artículo.
Trabajar con resultados de backtest - Objeto ResultsGroup
Sólo un recordatorio rápido de que en SQX todos los resultados de backtest se almacenan en el objeto Result, y se agrupan en el objeto ResultsGroup.
RegultGroup es lo que se ve en el banco de datos - puede contener uno o más resultados - backtests de la estrategia en el mercado principal, mercados adicionales, etc.
Hay un artículo con introducción: Trabajar con ResultsGroup
Cuando queremos fusionar los resultados de varias estrategias en una cartera tenemos que
- crear un nuevo objeto ResultsGroup que contendrá la cartera
- recorrer el objeto ResultsGroup de cada estrategia en el banco de datos
- encontrar el resultado principal - el que contiene backtest en los datos principales - este es el que vamos a fusionar
- crear un nuevo objeto Resultado para esta estrategia y añadirlo a la cartera
- clonar y copiar órdenes del Grupo de Resultados original a la cartera
- copiar símbolos del ResultsGroup original a la cartera - esto es necesario para el cálculo de PL, etc.
- al final crear un nuevo resultado de Cartera y calcular todas las estadísticas
Código fuente completo del fragmento
El código está ampliamente comentado, puedes seguir su lógica.
Creará dos nuevos resultados de Cartera - uno creado por nosotros manualmente, y otro creado por el método SQX para comparación.
paquete SQ.CustomAnalysis; import com.strategyquant.lib.SQUtils; import com.strategyquant.lib.SettingsMap; import com.strategyquant.lib.utils.IUniqueNameChecker; import com.strategyquant.tradinglib.*; import com.strategyquant.tradinglib.project.ProjectEngine; import com.strategyquant.tradinglib.results.SpecialValues; import com.strategyquant.tradinglib.results.stats.comparator.OrderComparatorByOpenTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; public class CAMergStrategiesToPortfolio extends CustomAnalysisMethod { public static final Logger Log = LoggerFactory.getLogger("CAMergeStrategiesToPortfolio"); //------------------------------------------------------------------------ //------------------------------------------------------------------------ //------------------------------------------------------------------------ public CAMergirEstrategiasEnCartera() { super("Combinar estrategias en cartera", TYPE_PROCESS_DATABANK); } //------------------------------------------------------------------------ @Override public boolean filterStrategy(String project, String task, String databankName, ResultsGroup rg) throws Exception { return false; } //------------------------------------------------------------------------ @Override public ArrayList processDatabank(String project, String task, String databankName, ArrayList databankRG) throws Exception { if(databankRG.size() <= 1) { // si no hay o sólo hay una estrategia no hay nada que fusionar return databankRG; } // obtener el banco de datos de destino para guardar el resultado final Databank targetDatabank = ProjectEngine.get(project).getDatabanks().get("Carteras"); if(targetDatabank == null) { throw new Exception("¡Por favor, cree un nuevo banco de datos llamado 'Carteras'!"); } // ------------------------------ // Crear cartera manualmente // fusionar todas las estrategias del banco de datos en una cartera Grupo de resultados caPortfolio = mergeStrategiesToPortfolio(databankRG); // crear el resultado final de la cartera para sumar todos los subresultados createPortfolioResult(caPortfolio); // añadir la nueva cartera al banco de datos de destino targetDatabank.add(caPortfolio, false); // ------------------------------ // Crear cartera de forma estándar llamando al método SQ - para control ResultsGroup standardPortfolio = ResultsGroup.merge(databankRG, new String[] { ResultsGroup.AdditionalMarket }, null); standardPortfolio.createPortfolioResult(PortfolioInitialBalanceTypes.SINGLE, null); targetDatabank.add(standardPortfolio, false); return databankRG; } //------------------------------------------------------------------------ private ResultsGroup mergeStrategiesToPortfolio(ArrayList databankRG) throws Exception { ResultsGroup caPortfolio = new ResultsGroup("CarteraHechaPorCA"); // añadir estrategias individuales a la cartera for(GrupoResultados rg : databankRG) { addResult(caCartera, rg); } addSymbolsMap(caCartera, databankRG); return caCartera; } //------------------------------------------------------------------------ private void addSymbolsMap(ResultsGroup rgCSPortfolio, ArrayList databankRG) { for(ResultsGroup rg : databankRG) { // añade todos los símbolos de los RG fusionados al mapa de símbolos de la cartera rgCSPortfolio.symbols().add(rg.symbols()); } } //------------------------------------------------------------------------ private void addResult(ResultsGroup caPortfolio, ResultsGroup rg) throws Exception { // primero crear un nuevo resultado para RG en nuestra nueva cartera // newResultKey será devuelto como su clave de resultado utilizado en nuestra cartera String newResultKey = mergeResult(caPortfolio, rg); // a continuación clonamos y copiamos las órdenes de este resultado de RG a la cartera copyOrdersToPortfolio(caPortfolio, rg, newResultKey); // añadir todos los datos de símbolos del RG fusionado al mapa de símbolos de la cartera - esto es necesario para el cálculo de PL, etc. caPortfolio.symbols().add(rg.symbols()); } //------------------------------------------------------------------------ private String mergeResult(ResultsGroup caPortfolio, ResultsGroup rg) throws Exception { // obtener el resultado principal de la estrategia actual - este es el que vamos a fusionar Resultado rgMainResult = rg.mainResult(); String mainResultKey = rgMainResult.getResultKey(); // determinar nueva clave de resultado - debe ser única por lo que tenemos que comprobar // si ya existe algún resultado con esta clave en nuestra cartera String newResultKey = rg.getName(); if(caPortfolio.hasResult(newResultKey)) { // la misma clave ya existe, tenemos que encontrar una nueva clave newResultKey = SQUtils.generateUniqueName(mainResultKey, new IUniqueNameChecker() { public boolean checkNameExist(String name) throws Exception { return caPortfolio.hasResult(nombre); } }); } // crear resultado fusionado SettingsMap copiedSettingsMap = rgMainResult.getSettings().clone(); // crear nuevo resultado fusionado y añadirlo a nuestra cartera Result mergedResult = new Result(newResultKey, caPortfolio, copiedSettingsMap); caPortfolio.addSubresult(newResultKey, copiedSettingsMap, mergedResult); // establecer el símbolo y el marco temporal de la estrategia combinada mergedResult.setString(SpecialValues.Symbol, rg.mainResult().getString(SpecialValues.Symbol)); mergedResult.setString(SpecialValues.Timeframe, rg.mainResult().getString(SpecialValues.Timeframe)); long rgDateFrom = rg.specialValues().getLong(SpecialValues.HistoryFrom, Long.MAX_VALUE); long rgDateTo = rg.specialValues().getLong(SpecialValues.HistoryTo, Long.MIN_VALUE); long caDateFrom = caPortfolio.specialValues().getLong(SpecialValues.PortfolioHistoryFrom, Long.MAX_VALUE); long caDateTo = caPortfolio.specialValues().getLong(SpecialValues.PortfolioHistoryTo, Long.MIN_VALUE); caPortfolio.specialValues().set(SpecialValues.HistoryFrom, Math.min(rgDateFrom, caDateFrom)); caPortfolio.specialValues().set(SpecialValues.HistoryTo, Math.max(rgDateTo, caDateTo)); copiedSettingsMap.set(SettingsKeys.PortfolioDataStart, Math.min(rgDateFrom, caDateFrom)); copiedSettingsMap.set(SettingsKeys.PortfolioDataEnd, Math.max(rgDateTo, caDateTo)); return newResultKey; } //------------------------------------------------------------------------ private void copyOrdersToPortfolio(ResultsGroup caPortfolio, ResultsGroup rg, String newResultKey) throws Exception { // obtener la lista de pedidos de nuestra cartera actual OrdersList mergedOrdersList = caPortfolio.orders(); // obtener todos los pedidos del resultado de la estrategia de fusión - ¡tenga en cuenta que deben ser clonados! String mainResultKey = rg.mainResult().getResultKey(); OrdersList filteredOL = rg.orders().filterWithClone(mainResultKey, Directions.Both, SampleTypes.FullSample); // no recorrer estos pedidos y añadirlos a la lista de pedidos de la cartera for(int i=0; i<filteredOL.size(); i++) { Orden = filteredOL.get(i); // order.SetupName se usa como identificador para que sepamos a que resultado pertenece la orden // por lo que tenemos que establecerlo como newResultKey order.SetupName = newResultKey; mergedOrdersList.add(orden); } } //------------------------------------------------------------------------ private void createPortfolioResult(ResultsGroup caPortfolio) throws Exception { SettingsMap settings = caPortfolio.mainResult().getSettings(); ResultadoCarteraResultado = new Resultado(GrupoResultados.Cartera, caCartera, configuración); caPortfolio.removeSubresult(ResultsGroup.Portfolio, true); caPortfolio.addSubresult(ResultsGroup.Portfolio, settings, portfolioResult); caPortfolio.specialValues().setString(SpecialValues.Symbol, ResultsGroup.Portfolio); // para la cartera ordenar las órdenes por su hora de apertura OrdersList ordersList = caPortfolio.orders(); ordersList.sort(new OrderComparatorByOpenTime()); portfolioResult.computeAllStats(caPortfolio.specialValues(), caPortfolio.getOOS()); caPortfolio.updated = true; } }
¿Le ha resultado útil este artículo? El artículo era útil El artículo no era útil
¡¡Excelente ejemplo !! ¡Exactamente lo que necesitaba! Gracias Mark