Documentação
Aplicações
Última atualização em 23. 11. 2023 por Mark Fric
Exemplo de plug-in - uma tarefa completa de projeto personalizado
Conteúdo da página
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
- Criar plug-ins de tarefas e configurações - partes em Java e JS
- 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:
- 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
- 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.
- Implementar o manuseio de configurações diferentes e a funcionalidade principal nos plug-ins Task e Settings (Java)
- 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
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.
Excelente trabalho! Estou muito ansioso por esse recurso, obrigado.
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