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