Documentação

Aplicações

Última atualização em 16. 11. 2021 por Mark Fric

Exemplo - por banco de dados análise personalizada

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.

Tarefa de análise 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.

wf banco de dados de patrimônio líquido

e o patrimônio líquido da carteira de todos os resultados da WF se parece com isto:

Patrimônio líquido da carteira WF

 

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

Assine
Notificação de
3 Comentários
Mais antigo
Novidades Mais Votados
Feedbacks em linha
Ver todos os comentários
Emmanuel
25. 11. 2021 8:52 pm

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.

Emmanuel
26. 11. 2021 11:53 am

O código completo comentado é realmente útil

Emmanuel
26. 11. 2021 11:59 am

Está funcionando bem !!!!!!! Obrigado

Postos relacionados