Documentação
Aplicações
Última atualização em 16. 11. 2021 por Mark Fric
Exemplo - por banco de dados análise personalizada
Conteúdo da página
Este exemplo é sobre a análise personalizada por banco de dados. Ao contrário da análise personalizada por estratégia que processa uma estratégia, este trecho da CA percorre todo o banco de dados, e pode acessar cada resultado de estratégia em um banco de dados.
A análise personalizada por banco de dados só pode ser executada a partir de uma tarefa personalizada no projeto personalizado.
Neste exemplo, faremos um exemplo bastante complexo de snippet de análise personalizada que construirá um portfólio a partir dos resultados da Walk-Forward das estratégias em banco de dados.
Esta foi uma solicitação de nossa primeira sessão de codificação.
Passo 1 - Criar novo snippet de análise personalizada
Abra CodeEditor, clique em Criar novo e escolha a opção Análise personalizada (CA) na parte inferior. Dê-lhe um nome WFPortfolio.
Isto criará um novo snippet WFPortfolio.java em pasta Usuário/Snippets/SQ/CustomAnalysis
Desta vez, vamos defini-lo como TYPE_PROCESS_DATABANK na construtora da classe:
carteira pública do PAM() { super("WFPortfolio", TYPE_PROCESS_DATABANK); }
Etapa 2 - Implementar o método ProcessDatabank()
Este método de chamadas CA processDatabank() que tem 4 parâmetros:
- Projeto String - nome do projeto onde a tarefa CA é colocada
- Tarefa de cordas - nome da tarefa CA
- Banco de dados de cordasNome - nome do banco de dados em que o snippet CA trabalha
- ArrayList banco de dadosRG - lista de todas as estratégias (ResultsGroups) a partir deste banco de dados.
Ele também retorna uma lista ArrayList, que deve conter apenas as estratégias da lista de entrada que devem ser preservadas no banco de dados.
Desta forma, ele pode ser usado como um filtro - você pode percorrer as estratégias na lista do banco de dadosRG e criar uma nova lista onde você colocará apenas estas que correspondem a alguns de seus critérios. As estratégias que não estiverem na lista de saída serão excluídas do banco de dados.
Em nosso caso, não queremos excluir algo do banco de dados, mas acrescentar uma nova estratégia (nosso portfólio recém-criado). Veremos como isso é feito.
Para resumir, o código faz isso:
- Cria novo Grupo de Resultados para carteira - estará vazio no início
- Analisar cada estratégia no banco de dados, verificando se ela tem resultado WF. F sim, ele copiará este resultado para um novo portfólio, incluindo todos os pedidos da WF.
- Portfólio de cálculo resulta de subresultados - por padrão não é computado a partir dos resultados da WF, então devemos fazer isso por nós mesmos no código
- Adicionar ao banco de dados o grupo ResultsGroup do portfólio final
O código é longo e complexo, não vamos explicar tudo aqui. Ele é mostrado no final deste artigo totalmente comentado.
Passo 3 - Executando nosso snippet CA personalizado
Para executar um trecho de CA "por banco de dados", precisamos criar um projeto personalizado e uma tarefa personalizada do tipo CustomAnalysis.
Selecione o WFPortfolio na tarefa personalizada.
Em seguida, adicione algumas estratégias com resultados do Walk-Forward ao banco de dados de resultados e execute a tarefa.
Ela deve criar uma nova estratégia chamada carteira de Ações da WF que conterá as ações da WF de todas as estratégias em Resultados.
e o patrimônio líquido da carteira de todos os resultados da WF se parece com isto:
Código comentado completo do snippet
package SQ.CustomAnalysis; import com.strategyquant.lib.*; import java.util.ArrayList; import com.strategyquant.tradinglib.*; import com.strategyquant.tradinglib.project.ProjectEngine; import com.strategyquant.tradinglib.results.SpecialValues; import com.strategyquant.tradinglib.results.stats.comparator.OrderComparatorByOpenTime; public class WFPortfolio extends CustomAnalysisMethod { //------------------------------------------------------------------------ //------------------------------------------------------------------------ //------------------------------------------------------------------------ public WFPortfolio() { super("WFPortfolio", TYPE_PROCESS_DATABANK); } //------------------------------------------------------------------------ @Override public boolean filterStrategy(String project, String task, String databankName, ResultsGroup rg) throws Exception { return true; } //------------------------------------------------------------------------ @Override public ArrayList<ResultsGroup> processDatabank(String project, String task, String databankName, ArrayList<ResultsGroup> databankRG) throws Exception { // create new ResultsGroup for our new portfolio ResultsGroup portfolioRG = new ResultsGroup("WF Equity portfolio"); // get OrderList from new portfolio (empty so far), // we will insert WF orders there OrdersList portfolioOrdersList = portfolioRG.orders(); // go through all strategy results in databank for(ResultsGroup strategyRG : databankRG) { // skip strategies whose name starts with "WF Equity portfolio" // this will ensure that we'll ignore our portfolios created // in previous runs String strName = strategyRG.getName(); if(strName.startsWith("WF Equity portfolio")) { continue; } // get best Walk-Forward result from a strategy // If it doesn't exist it will return null Result wfResult = getWFResult(strategyRG); if(wfResult == null) { continue; } // --------------------- // wfResult is the best Walk-Forward result from existing strategy // clone it to a new result with all its settings String wfResultKey = wfResult.getResultKey(); // we'll name the new subresult as "StrategyName "+ "existing WF result name" String newSubResultKey = String.format("%s-%s", strategyRG.getName(), wfResultKey); // clone settings to use them in the new result SettingsMap settingsMapCopy = wfResult.getSettings().clone(); // create new result that will be added to the portfolio Result wfResultCopied = new Result(newSubResultKey, portfolioRG, settingsMapCopy); portfolioRG.addSubresult(newSubResultKey, settingsMapCopy, wfResultCopied); // --------------------- // copy WF orders from original strategy to new results group OrdersList filteredOL = strategyRG.orders().filterWithClone(wfResultKey, Directions.Both, SampleTypes.FullSample); for(int i=0; i<filteredOL.size(); i++) { Order order = filteredOL.get(i); // change setup name to match the new result name in the new portfolio order.SetupName = newSubResultKey; order.IsInPortfolio = 1; // add the order to the portfolio OrdersList portfolioOrdersList.add(order); } // copy also symbol definitions from old strategy // this is needed for proper cancullation of PL and metrics portfolioRG.symbols().add(strategyRG.symbols()); } // --------------------- // compute portfolio result // normally we'd call portfolioRG.createPortfolioResult() but the default version // ignores WF results, so we have to implement it by ourselves createPortfolioResult(portfolioRG); // portfolio ResultsGroup is complete, now add it to the databank Databank databank = ProjectEngine.get(project).getDatabanks().get(databankName); databank.add(portfolioRG, true); return databankRG; } //------------------------------------------------------------------------ /** * returns best Walk-Forward result - if it exists */ private Result getWFResult(ResultsGroup rg) throws Exception { String wfKey = rg.getBestWFResultKey(); if(wfKey == null) { return null; } return rg.subResult(wfKey); } //------------------------------------------------------------------------ /** * creates a Portfolio result from all the existing sub-results in the ResultsGroup * This is function from standard SQ library, with only exception that this works * also on WF results - standard ResultsGroup.createPortfolioResult() * ignores WF results when creating portfolio. * * @param portfolioRG * @throws Exception */ public void createPortfolioResult(ResultsGroup portfolioRG) throws Exception { Result firstResult = null; String tf = null; int resultsInPortfolio = 0; // go through all existing sub-results and get their initial capital and from-to dates for(String existingResultKey : portfolioRG.getResultKeys()) { Result result = portfolioRG.subResult(existingResultKey); resultsInPortfolio++; if(firstResult == null) { firstResult = result; } } if(resultsInPortfolio <= 1) { throw new Exception("ResultGroup doesn't contain more Results, cannot create a portfolio!"); } if(firstResult == null) { throw new Exception("No Result in ResultGroup to create portfolio!"); } SettingsMap settings = firstResult.getSettings(); Result portfolioResult = new Result(ResultsGroup.Portfolio, portfolioRG, settings); portfolioRG.removeSubresult(ResultsGroup.Portfolio, true); portfolioRG.addSubresult(ResultsGroup.Portfolio, settings, portfolioResult); portfolioRG.specialValues().setString(SpecialValues.Symbol, ResultsGroup.Portfolio); portfolioRG.specialValues().setString(SpecialValues.Timeframe, "N/A"); // for portfolio sort orders by their open time OrdersList ordersList = portfolioRG.orders(); ordersList.sort(new OrderComparatorByOpenTime()); // compute all metrics on the portfolio portfolioResult.computeAllStats(portfolioRG.specialValues(), portfolioRG.getOOS()); } }
Este artigo foi útil? O artigo foi útil O artigo não foi útil
Mark, muito obrigado por este trabalho impressionante !!!!!! É exatamente o que eu preciso !!!!
O SQX é realmente único.
Com o exemplo, serei capaz de construir uma nova idéia.
O código completo comentado é realmente útil
Está funcionando bem !!!!!!! Obrigado