Documentação

Aplicações

Última atualização em 23. 11. 2023 por Mark Fric

Exemplo de plug-in - uma tarefa completa de projeto personalizado

Este artigo é uma descrição do desenvolvimento de um plug-in de tarefa personalizado complexo que pode ser usado em um projeto personalizado no StrategyQuant.

Observação 1 - tivemos que fazer algumas alterações na estrutura de classes para permitir a criação de plug-ins externos desse tipo e, por isso, esse plug-in funcionará somente a partir do SQX Build 138 e posterior.

Observação 2 - temos apenas documentação e exemplos limitados sobre a extensão do SQX com plug-ins, e este é um deles. Este exemplo é destinado a usuários que têm conhecimento e são capazes de entender o código existente.

 

O objetivo

Para desenvolver uma nova tarefa personalizada no StrategyQuant, incluindo configurações completas.

Implementaremos um novo plug-in de tarefa personalizado chamado Filtrar por correlação.

 

Não confunda isso com o exemplo de plug-in já existente com o mesmo nome no artigo aqui: https://strategyquant.com/doc/programming-for-sq/filter-by-correlation-plugin-example/

Esse exemplo mais antigo é um plug-in mais simples que implementa uma nova ação de banco de dados.

Nosso novo exemplo seria estender essa ideia e implementar um plug-in de tarefas completo.

 

O resultado

Como você pode ver abaixo - uma nova tarefa chamada Filter by correlation (Filtrar por correlação) nas tarefas de projetos personalizados para escolher:

 

E configurações dessa nova tarefa:

 

Essa tarefa faz um trabalho simples: compara estratégias de Fonte banco de dados com estratégias existentes em Existente banco de dados e copia aqueles que têm correlação inferior à permitida para Alvo banco de dados.

Essa (e todas as) tarefas personalizadas são, na verdade, compostas por dois plug-ins interdependentes:

TaskFilterByCorrelation

Plug-in que implementa a tarefa em si e a funcionalidade principal, além da interface do usuário para as configurações simples - é o que você vê na guia Progress para essa tarefa.

 

SettingsFilterByCorrelation

Plugin que implementa as configurações completas desse plugin, inclusive a interface do usuário - é a que você vê na guia Full settings (Configurações completas).

Todas as configurações dessa tarefa são carregadas usando esse plug-in de configurações.

 

Observe que esse tipo de plug-in combina Java - para implementação de back-end e funcionalidade - e JavaScript (AngularJS) para implementação de front-end.

 

Etapas gerais necessárias para implementar o novo plug-in de tarefas

  1. Criar plug-ins de tarefas e configurações - partes em Java e JS
  2. Criar task.xml padrão com as configurações dos bancos de dados que são criados automaticamente + configurações padrão no plug-in Task

 

Qualquer nova tarefa que você criar deve seguir os nomes dos pacotes:
pacote com.strategyquant.plugin.Task.impl.XXXXXX
pacote com.strategyquant.plugin.Settings.impl.XXXXX

Como XXXXX é seu nome, o SQX cria pastas para que os nomes dos pacotes correspondam:
TarefaXXXXXXXXXXXX
ConfiguraçõesXXXXXXXXXXX

Em nosso caso, as pastas são:
TaskFilterByCorrelation
SettingsFilterByCorrelation

 

A melhor abordagem ao criar seu próprio plug-in de tarefa seria:

  1. Faça uma cópia de nossos dois plug-ins de exemplo, altere os nomes das classes e as cadeias de caracteres no código de "FilterByCorrelation" para seu próprio nome
  2. Certifique-se de excluir/não copiar os respectivos arquivos .jar ao copiar os exemplos - os arquivos .jar serão criados quando você compilar seu próprio plug-in.
  3. Implementar o manuseio de configurações diferentes e a funcionalidade principal nos plug-ins Task e Settings (Java)
  4. Implementar uma interface de usuário diferente nos plug-ins Settings e Task - nos arquivos .HTML e .JS

 

Importação de plug-ins de exemplo para seu SQX

Os plug-ins de exemplo estão anexados a este artigo (na parte superior). Os dois plug-ins vêm em dois arquivos diferentes: .sxp e ZIP padrão.

A versão ZIP não é para importação, é apenas para conveniência - se alguém quiser dar uma olhada nos arquivos sem importá-los para o SQX.

 

A importação de plug-ins usando .sxp é simples: abra o CodeEditor, vá para Importar, escolha os dois arquivos .sxp para ambos os plug-ins e clique em OK.

 

Os plugins serão importados e você deverá ver as novas pastas de plugins no explorador de arquivos:

Depois disso, basta reiniciar o SQX para ver a nova tarefa disponível nos projetos personalizados.

 

Plug-in SettingsFilterByCorrelation

Primeiro, descreveremos o plug-in de configurações. Esse é um plug-in que implementa as configurações "completas", ou seja, aquelas que aparecem na seção Configurações completas guia. Ela pode ter uma interface de usuário diferente e mais complicada do que as configurações simples exibidas na guia Progresso tab.

 

Novamente, examinaremos todos os arquivos:

 

FilterByCorrelationCtrl.js

Controlador do Angular para este plug-in. A principal função do controlador é adicionar variáveis (seus valores) ao escopo e, assim, torná-las disponíveis no arquivo HTML.

 

Nos plug-ins de configurações, definimos toda a configuração do FilterByCorrelationService:

$scope.config = FilterByCorrelationService.config;

 

Além disso, podemos definir algumas variáveis adicionais, por exemplo, a lista de tipos de correlação/períodos usados nas caixas de listagem.

    $scope.correlationTypes = [];
    $scope.correlationPeriods = [];

    loadToArray($scope.correlationTypes, SQConstants.getConstants().correlationTypes);
    loadToArray($scope.correlationPeriods, SQConstants.getConstants().correlationPeriods);

 

Além de definir as variáveis, esse controlador também lida com o carregamento/salvamento de configurações - quando elas devem ser salvas e quando lidas.

 

Há uma ação do controlador settingsChanged() chamado do HTML em cada mudança de entrada, e esse método chama FilterByCorrelationService.saveSettings() para salvar as configurações.

 

O carregamento das configurações é acionado por um evento SETTINGS_TAB_RELOAD que é chamado automaticamente na inicialização da guia ou quando você alterna de outra guia para esta.

O controlador de configurações precisa adicionar um ouvinte a esse evento e, ao alternar para essa guia de configurações, ele acionaria esse evento que chamará o init() que, por sua vez, carrega as configurações atuais chamando FilterByCorrelationService.loadSettings();

 

FilterByCorrelationService.js

Serviço para esse filtro, que trata de coisas como carregar e salvar dados de/para o backend, definir valores padrão etc.

Todos os serviços são instâncias de singleton, ou seja, são criados apenas uma vez quando o aplicativo é iniciado.

Cada serviço de configurações contém um objeto de configuração que contém as configurações da tarefa selecionada no momento e os métodos loadSettings/saveSettings.

 

As configurações xml atuais da tarefa selecionada são obtidas por chamada:

var filteringObj = AppService.getCurrentTaskTabSettings("FilterByCorrelation");

 

Em seguida, podemos ler o valor do xml:

instance.config.correlation.max = getNodeFloatValue(filteringObj, 'CorrMax', 0.3);

 

ou escrever valores nele:

addNode('CorrMax', instance.config.correlation.max, filteringObj, xmlDoc);

 

Portanto, no serviço, alteramos diretamente o XML.

 

Observe que a instância do serviço é apenas uma e é compartilhada entre o plug-in Settings (UI de configurações completas) e o plug-in Task (UI de configurações simples).

 

module.js

Registra o plug-in na interface da IU. Para exibir o painel de configurações completo, um plug-in do tipo SettingsTab deve ser registrado.

Os atributos obrigatórios do plug-in são:

  • task - nome da tarefa para a qual ela deve ser exibida, neste caso "FilterByCorrelation". Se quisermos exibir essa guia de configuração também para a tarefa Build e Retest, haverá 'FilterByCorrelation,Build,Retest'
  • configElemName - nome da configuração em xml
  • templateUrl - o html a ser exibido
  • controlador - qual controlador está vinculado ao html da definição de templateUrl
  • dataItem - ID da guia de configuração, deve ter um nome exclusivo entre as guias SettingsTab

 

outras configurações, como título, ajuda, helpUrl, são compreensíveis a partir do nome do atributo.

 

settings.html, styles.css

Arquivo HTML que contém a definição da interface do usuário das configurações e a definição do CSS dos estilos usados.

 

SettingsFilterByCorrelation.jar

Esse é um plug-in já compilado. Você não o verá em seu próprio plug-in até que o compile - consulte as instruções sobre como fazer isso mais tarde.

 

SettingsFilterByCorrelation.java

Classe Java que lida com o backend desse plug-in. Ela implementa ISettingTabPlugin

Interface e o método mais importante é readSettings() - que lê as configurações do XML fornecido pela interface do usuário (parâmetro elSettings), analisa-o e salva-o em um objeto de dados com as chaves exclusivas desse plug-in:

public void readSettings(String projectName, ISQTask task, Element elSettings, TaskSettingsData data) {
        Element elFiltering = null;

        try {
            elFiltering = XMLUtil.getChildElem(elSettings, getSettingName());
        } catch(Exception e){
            data.addError(getSettingName(), null, e.getMessage());
            return;
        }
       
        try {
            Banco de dados dbSource = ProjectConfigHelper.getDatabankByType(projectName, "Source", elSettings);
            Banco de dados dbTarget = ProjectConfigHelper.getDatabankByType(projectName, "Target", elSettings);
            Banco de dados dbExisting = ProjectConfigHelper.getDatabankByType(projectName, "Existing", elSettings);

            data.addParam(SettingsKeys.DatabankSource, dbSource);
            data.addParam(SettingsKeys.DatabankTarget, dbTarget);
            data.addParam("DatabankExisting", dbExisting);

            CorrelationSettings corr = new CorrelationSettings();
            corr.loadFromXml(elFiltering);

            data.addParam(SettingsKeys.Correlation, corr);

        } catch(Exception e){
            data.addError(getSettingName(), null, L.t("Não é possível carregar as configurações de FilterByCorrelation. ") + e.getMessage());
        }
    }

 

Plug-in TaskFilterByCorrelation

Como dito acima, esse é o plug-in "principal" que implementa a funcionalidade. Esse plug-in também é responsável por exibir as configurações "simples" visíveis na guia Progress.

 

Você pode ver que o plug-in consiste em vários arquivos, incluindo a estrutura de subpastas. Vamos examiná-los um a um.

 

module.js

Registra o plug-in na interface da interface do usuário. Para exibir as configurações simples, é necessário registrar um plug-in do tipo "SimpleTaskSettings".

Os argumentos obrigatórios do plug-in são:

  • taskType - nome da tarefa à qual está se referindo
  • templateUrl - URL do arquivo HTML que contém a interface do usuário - é um dos outros arquivos descritos abaixo
  • controlador - qual controlador será conectado ao modelo HTML - novamente, esse controlador é definido em um dos próximos arquivos

Seu código JavaScript:

angular.module('app.settings').config(function(sqPluginProvider, SQEventsProvider) {
    sqPluginProvider.plugin("SimpleTaskSettings", 1, {
        taskType: 'FilterByCorrelation',
        templateUrl: '../../../plugins/TaskFilterByCorrelation/simpleSettings/simpleSettings.html',
        controlador: 'SimpleFilterByCorrelationCtrl',
        getInfoPanels: function(xmlConfig, injector){
            var L = injector.get("L");
            var settingsPlugins = sqPluginProvider.getPlugins('SettingsTab');
            var groups = [
                {
                    title: L.tsq('Filtering options'),
                    settings: [
                        { name : L.tsq("Filtering"), value : getTaskInfoPanelSettings(xmlConfig, getItem(settingsPlugins, 'configElemName', "FilterByCorrelation")) }
                    ]
                }
            ];
           
            return groups;
        }
    });
});

 

pasta simpleSettings

Contém a interface do usuário para as configurações simples desse plug-in - são as miniconfigurações exibidas na guia Progress.

 

SimpleFilterByCorrelationCtrl.js e simpleSettings.html

Código HTML para as configurações e o controlador Angular que as manipula. O controlador de configurações simples funciona da mesma forma que o controlador de configurações completo descrito acima, com uma diferença: ele não precisa implementar quando carregar as configurações, pois isso já é feito no controlador de configurações completo.

 

styles.css

Arquivo que pode conter estilos usados na interface do usuário

 

task.xml

Configurações padrão dessa tarefa. Você pode ver que, nesse plug-in, basicamente salvamos:

  • 3 bancos de dados - Fonte, Alvo, Existente
  • Configurações de filtragem de correlação

Conforme descrito em FilterByCorrelationService Na descrição, o serviço manipula o XML diretamente - ele carrega o XML do backend e envia o XML para o backend para salvar as alterações.

A estrutura padrão das configurações XML do nosso plug-in é definida aqui e na classe de serviço.

 

TaskFilterByCorrelation.jar

Esse é um plug-in já compilado. Você não o verá em seu próprio plug-in até que o compile - consulte as instruções sobre como fazer isso mais tarde.

 

TaskFilterByCorrelation.java

Classe Java que lida com o backend desse plug-in. Por ser um plug-in de tarefa, ele é estendido de AbstractTask:

public class TaskFilterByCorrelation extends AbstractTask {

 

O método mais importante é start() - Esse é o método que é chamado quando você clica no botão Start (Iniciar) no projeto personalizado, e é nele que a funcionalidade principal é implementada:

    public void start() throws Exception {
        loadSettings();

 

No início, ele carrega as configurações - isso carrega as configurações que foram preparadas em nosso segundo plug-in SettingsFilterByCorrelation

Em seguida, ele atualiza o mecanismo de progresso:

        progressEngine.setLogPrefix(taskLogPrefix);
        progressEngine.printToLog(L.t("Iniciando a filtragem de estratégias..."));
        progressEngine.start();

 

E o restante é a funcionalidade principal: percorrer as estratégias no banco de dados de origem uma a uma, calcular a correlação e copiá-las para o banco de dados de destino:

        ResultsGroup strategyCloned;
        ArrayList results = databankSource.getRecords();

        this.totalCopied = 0;
        this.totalResults = results.size();

        for(int i=0; i<results.size(); i++) {
            ResultsGroup strategy = results.get(i);
            String strategyName = strategy.getName();
           
            try {
                String dismissalMessage = checkCorrelation(strategy);
                se (dismissalMessage != null) {
                    progressEngine.printToLogDebug(L.t("%s pulado, %s", strategyName, dismissalMessage));
                    increaseGlobalStats(false);
                   
                    continue;
                }
                //copiar da origem para o destino
                strategyCloned = strategy.clone();
                databankTarget.add(strategyCloned, true);
               
                progressEngine.printToLogDebug(L.t("%s copied, %s", strategyName, String.format("correlation < %.2f", correlation.maxCorrelation)));
               
                this.totalCopied++;
               
                increaseGlobalStats(true);
               
                progressEngine.checkPaused();
               
                se (progressEngine.isStopped()) {
                    break;
                }
            }
            catch (OutOfMemoryError e) {
                project.onMemoryError(e);
                break;
            }
        }
      
        databankTarget.updateBestResults();
       
        progressEngine.finish();

 

 

Compilação dos plug-ins

Ambos os plug-ins precisam ser compilados para que o SQX os carregue. Isso pode ser feito simplesmente em CodeEditorPara obter mais informações, basta clicar com o botão direito do mouse na pasta do plug-in e escolher Compilar o plug-in no menu:

Se não houver erros, o plug-in será compilado e um novo arquivo com o nome do plug-in e .jar aparecerá na pasta.

 

Observe que você precisa compilar os dois plug-ins. Em seguida, reinicie o SQX e você verá o novo plug-in nas tarefas do projeto personalizado.

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
tníquel
26. 11. 2023 10:18 am

Perdi esse recurso há muito tempo. Agora estou feliz. Recebi esse recurso e uma descrição detalhada de como implementar as próprias tarefas. Estou feliz.

Jordânia
30. 11. 2023 12:55 pm

Excelente trabalho! Estou muito ansioso por esse recurso, obrigado.

JOSE ANTONIO HERNANDEZ ROSALES
JOSE ANTONIO HERNANDEZ ROSALES
6. 2. 2024 1:12 pm

It’s great. A filter could be made that would choose the best ones in a specific bank. For example, before optimizing, choose the ten best for their stability and the best ten for their total profit…. Thanks

Postos relacionados