Documentação
Aplicações
Última atualização em 21. 7. 2022 por Mark Fric
Fusão de múltiplos resultados em carteira
Conteúdo da página
Neste artigo mostraremos como o StrategyQuant X lida com os resultados dos backtest, e como podemos fundi-los em portfólio.
Isso já pode ser feito no SQX, selecionando múltiplas estratégias e escolhendo Portfólio -> Fundir estratégiasmas mostraremos como isso é feito em segundo plano.
Esta pretende ser uma primeira parte de múltiplas séries, gostaríamos de usar esta funcionalidade para explorar se a comercialização poderia ser melhorada escolhendo um subconjunto específico de estratégias para comercializar - isto será examinado nos próximos artigos.
Note que, por fusão com a carteira, entendemos a fusão dos resultados finais de backtest em um resultado de carteira, não a fusão de estratégias comerciais individuais.
Esta característica é novamente feita na forma de snippet de Análise Personalizada, e o snippet completo é anexado a este artigo.
Trabalhando com resultados de backtest - Objeto ResultsGroup
Apenas um rápido lembrete de que no SQX todos os resultados backtest são armazenados no objeto Resultado, e eles são agrupados no objeto ResultadoGrupo.
RegultGroup é o que você vê no banco de dados - ele pode conter um ou mais resultados - retrocesso de estratégia no mercado principal, mercados adicionais, etc.
Há um artigo com introdução: Trabalhando com ResultsGroup
Quando queremos fundir vários resultados estratégicos em um único portfólio, temos que
- criar um novo objeto do ResultsGroup que irá manter o portfólio
- passar por ResultsGroup objeto de toda estratégia em banco de dados
- encontrar o resultado principal - o que contém o backtest sobre os dados principais - este é o resultado que estaremos fundindo
- criar um novo objeto de resultado para esta estratégia e adicioná-lo ao portfólio
- clonar e copiar pedidos de resultados originaisGrupo de resultados para carteira
- copiar símbolos do ResultsGroup original para o portfólio - isto é necessário para o cálculo do PL etc.
- no final, criar um novo resultado de Portfólio e calcular todas as estatísticas
Código fonte completo do snippet
O código é amplamente comentado, você pode seguir sua lógica.
Ele criará dois novos resultados de Portfólio - um criado por nós manualmente, e outro criado pelo método SQX para comparação.
pacote SQ.CustomAnalysis; import com.strategyquant.lib.SQUtils; importar com.strategyquant.lib.SettingsMap; importar com.strategyquant.lib.utils.IUniqueNameChecker; import com.strategyquant.tradinglib.*; importar com.strategyquant.tradinglib.project.projectEngine; import com.strategyquant.tradinglib.results.SpecialValues; import com.strategyquant.tradinglib.results.stats.comparator.OrderComparatorByOpenTime; import org.slf4j.logger; importar org.slf4j.LoggerFactory; importação java.util.ArrayList; classe pública CAMergeStrategiesToPortfolio estende o CustomAnalysisMethod { logger final estático público = LoggerFactory.getLogger("CAMergeStrategiesToPortfolio"); //------------------------------------------------------------------------ //------------------------------------------------------------------------ //------------------------------------------------------------------------ públicas CAMergeStrategiesToPortfolio() { super("Merge Strategies To Portfolio", TYPE_PROCESS_DATABANK); } //------------------------------------------------------------------------ @Override filtro booleano públicoEstratégia(projeto String, tarefa String, banco de dados StringName, ResultsGroup rg) lança Exceção { retornar falso; } //------------------------------------------------------------------------ @Override public ArrayList processDatabank(String project, String task, String databankName, ArrayList databankRG) lança Exceção { if(databankRG.size() <= 1) { // se não houver nenhuma ou apenas uma estratégia, não há nada para fundir banco de dados de retornoRG; } // obter o banco de dados alvo para salvar o resultado final Databank targetDatabank = ProjectEngine.get(project).getDatabanks().get("Portfolios"); if(targetDatabank == nulo) { lançar uma nova exceção ("Por favor, crie um novo banco de dados chamado 'Portfólios' !"); } // ------------------------------ // Criação manual de portfólio // fundir todas as estratégias em banco de dados em um único portfólio ResultadosGrupo caPortfolio = fundirEstratégiasToPortfolio(databankRG); // criar resultado final de Portfólio para somar todos os sub-resultados createPortfolioResultado(caPortfolio); // adicionar novo portfólio ao nosso banco de dados alvo targetDatabank.add(caPortfolio, falso); // ------------------------------ // Criando portfólio de maneira padrão chamando o método SQ - para controle ResultsGroup standardPortfolio = ResultsGroup.merge(databankRG, new String[] { ResultsGroup.AdditionalMarket }, null); standardPortfolio.createPortfolioResultado(PortfolioInitialBalanceTypes.SINGLE, nulo); targetDatabank.add(standardPortfolio, false); banco de dados de retornoRG; } //------------------------------------------------------------------------ resultados privadosGrupo fundeEstratégiasParaPortfolio(ArrayList banco de dadosRG) lança Exceção { ResultsGroup caPortfolio = novos resultadosGroup("PortfolioMadeByCA"); // adicionar estratégias individuais ao portfólio for(ResultadosGrupo rg : banco de dadosRG) { addResultado(caPortfolio, rg); } addSymbolsMap(caPortfolio, databankRG); retornar caPortfolio; } //------------------------------------------------------------------------ nulo privado addSymbolsMap(ResultsGroup rgCSPortfolio, ArrayList databankRG) { for(ResultadosGrupo rg : banco de dadosRG) { // adicionar todos os símbolos dos RGs fundidos ao mapa de símbolos do portfólio rgCSPortfolio.symbols().add(rg.symbols()); } } //------------------------------------------------------------------------ vazio privado adicionarResultado(ResultsGroup caPortfolio, ResultsGroup rg) joga Exceção { // primeiro criar um novo resultado para a RG em nosso novo portfólio // newResultKey será devolvido como resultado chave utilizada em nossa carteira String newResultKey = mergeResult(caPortfolio, rg); // próximo clone e pedidos de cópia para este resultado da RG para a carteira copyOrdersToPortfolio(caPortfolio, rg, newResultKey); // adicionar todos os dados de símbolo do RG fundido ao mapa de símbolos do portfólio - isto é necessário para o cálculo do PL etc. caPortfolio.symbols().add(rg.symbols()); } //------------------------------------------------------------------------ private String mergeResultado(ResultsGroup caPortfolio, ResultsGroup rg) lança Exceção { // obter o principal resultado da estratégia atual - esta é a que estaremos fundindo Resultado rgMainResult = rg.mainResult(); String mainResultKey = rgMainResult.getResultKey(); // determinar nova chave de resultado - ela deve ser única, então temos que verificar // se não houver resultado com esta chave já em nossa carteira String newResultKey = rg.getName(); if(caPortfolio.hasResultado(newResultKey)) { // a mesma chave já existe, temos que encontrar uma nova chave newResultKey = SQUtils.generateUniqueName(mainResultKey, new IUniqueNameChecker() { cheque booleano públicoNameExist(String name) lança Exceção { retornar caPortfolio.hasResultado(nome); } }); } // criar resultado fundido SettingsMap copiedSettingsMap = rgMainResult.getSettings().clone(); // criar novo anúncio de resultado fundido adicioná-lo ao nosso portfólio Resultado fundidoResultado = novo Resultado(newResultKey, caPortfolio, copySettingsMap); caPortfolio.addSubresult(newResultKey, copySettingsMap, mergedResult); // definir o símbolo e o prazo da estratégia de fusão 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))); copySettingsMap.set(SettingsKeys.PortfolioDataStart, Math.min(rgDateFrom, caDateFrom)); copySettingsMap.set(SettingsKeys.PortfolioDataStart, Math.min(rgDateFrom, caDateFrom)); copiedSettingsMap.set(SettingsKeys.PortfolioDataEnd, Math.max(rgDateTo, caDateTo)); copiedSettingsMap.set(SettingsKeys.PortfolioDataEnd, Math.max(rgDateTo, caDateTo)); retornar newResultKey; } //------------------------------------------------------------------------ private void copyOrdersToPortfolio(ResultsGroup caPortfolio, ResultsGroup rg, String newResultKey) lança Exceção { // obter a lista de pedidos de nosso portfólio atual OrderList mergedOrdersList = caPortfolio.orders(); // obter todos os pedidos a partir do resultado da estratégia de fusão - note que eles devem ser clonados! String mainResultKey = rg.mainResult().getResultKey(); OrderList filteredOL = rg.orders().filterWithClone(mainResultKey, Directions.Both, SampleTypes.FullSample); // não passar por esses pedidos e adicioná-los à lista de pedidos de carteira for(int i=0; i<filteredOL.size(); i++) { Pedido = filteredOL.get(i); // pedido. SetupName é usado como identificador para que saibamos a que resultado o pedido pertence // por isso temos que definir para a novaResultKey order.SetupName = newResultKey; mergedOrdersList.add(order); } } //------------------------------------------------------------------------ vazio privado criarPortfolioResultado(ResultsGroup caPortfolio) lança Exceção { ConfiguraçõesConfiguraçõesMapa = caPortfolio.mainResultado().getSettings(); Resultado carteiraResultado = novo resultado(ResultsGroup.Portfolio, caPortfolio, settings); caPortfolio.removeSubresult(ResultsGroup.Portfolio, true); caPortfolio.addSubresult(ResultsGroup.Portfolio, settings, portfolioResultado); caPortfolio.specialValues().setString(SpecialValues.Symbol, ResultsGroup.Portfolio); // para ordens de classificação de portfólio por seu tempo aberto OrderList ordersList = caPortfolio.orders(); orderList.sort(novo OrderComparatorByOpenTime()); portfolioResultados.computeAllStats(caPortfolio.specialValues(), caPortfolio.getOOS()); caPortfolio.updated = true; } }
Este artigo foi útil? O artigo foi útil O artigo não foi útil
Excelente exemplo!! Exatamente o que eu precisava!! Obrigado Mark