Documentazione

Applicazioni

Ultimo aggiornamento il 23. 11. 2023 da Mark Fric

Esempio di plugin: un progetto completo e personalizzato

Questo articolo descrive lo sviluppo di un complesso plugin di attività personalizzato che può essere utilizzato all'interno di un progetto personalizzato in StrategyQuant.

Nota 1 - abbiamo dovuto apportare alcune modifiche alla struttura delle classi per consentire la creazione di plugin esterni di questo tipo; per questo motivo il plugin funzionerà solo a partire dalla build 138 di SQX.

Nota 2 - La documentazione e gli esempi sull'estensione di SQX con i plugin sono limitati e questo è uno di quelli. Questo esempio è destinato agli utenti che hanno le conoscenze e sono in grado di comprendere il codice esistente.

 

L'obiettivo

Per sviluppare un nuovo compito personalizzato in StrategyQuant, comprese le impostazioni complete.

Implementeremo un nuovo plugin di task personalizzato, chiamato Filtrare per correlazione.

 

Non confondetelo con il plugin di esempio già esistente con lo stesso nome nell'articolo qui: https://strategyquant.com/doc/programming-for-sq/filter-by-correlation-plugin-example/

Questo vecchio esempio è un plugin più semplice che implementa una nuova azione della banca dati.

Il nostro nuovo esempio consiste nell'estendere questa idea e nell'implementare un intero plugin di attività.

 

Il risultato

Come si può vedere qui sotto, nelle attività dei progetti personalizzati è presente una nuova attività denominata Filtro per correlazione:

 

E le impostazioni di questo nuovo compito:

 

Questo task svolge un lavoro semplice: confronta le strategie di Fonte con le strategie esistenti in Esistente e copia quelli che hanno una correlazione inferiore a quella consentita in Obiettivo banca dati.

Questo (e ogni) task personalizzato è in realtà composto da due plugin interdipendenti:

TaskFilterByCorrelation

Plugin che implementa l'attività stessa e le funzionalità principali, oltre all'interfaccia utente per le impostazioni semplici: è quello che si vede nella scheda Progress per questa attività.

 

ImpostazioniFiltroPerCorrelazione

Plugin che implementa le impostazioni complete di questo plugin, compresa l'interfaccia utente, quella che si vede nella scheda Impostazioni complete.

Tutte le impostazioni di questo task vengono caricate tramite il plugin Impostazioni.

 

Si noti che questo tipo di plugin combina Java - per l'implementazione del backend e delle funzionalità - e JavaScript (AngularJS) per l'implementazione del frontend.

 

Passi generali necessari per l'implementazione di un nuovo plugin per le attività

  1. Creare plugin di attività e impostazioni, sia in java che in JS.
  2. Creare task.xml predefinito con le impostazioni delle banche dati che vengono create automaticamente + le impostazioni predefinite nel plugin Task.

 

Ogni nuovo task creato deve rispettare i nomi dei pacchetti:
pacchetto com.strategyquant.plugin.Task.impl.XXXXXX
pacchetto com.strategyquant.plugin.Settings.impl.XXXXX

Dove XXXXX è il nome dell'utente, SQX crea le cartelle in modo che i nomi dei pacchetti corrispondano:
CompitoXXXXXXXXXX
ImpostazioniXXXXXXXXX

Nel nostro caso le cartelle sono:
TaskFilterByCorrelation
ImpostazioniFiltroPerCorrelazione

 

L'approccio migliore per creare il proprio plugin per le attività è quello di:

  1. Fate una copia dei nostri due plugin di esempio, cambiate i nomi delle classi e le stringhe nel codice da "FilterByCorrelation" a un nome vostro.
  2. Assicurarsi di cancellare/non copiare i rispettivi file .jar durante la copia degli esempi: i file .jar saranno creati quando si compilerà il proprio plugin.
  3. Implementare la gestione di diverse impostazioni e le principali funzionalità nei plugin Task e Settings (Java)
  4. Implementare un'interfaccia utente diversa nei plugin Impostazioni e Attività - sia in file .HTML che .JS

 

Importazione di plugin di esempio in SQX

I plugin di esempio sono allegati a questo articolo (in alto). Entrambi i plugin sono disponibili in due archivi diversi: .sxp e ZIP standard.

La versione ZIP non serve per l'importazione, ma solo per comodità, se qualcuno vuole dare un'occhiata ai file senza importarli in SQX.

 

L'importazione dei plugin tramite .sxp è semplice: aprite CodeEditor, andate su Importa, scegliete entrambi i file .sxp - per entrambi i plugin e cliccate su OK.

 

I plugin saranno importati e si dovrebbero vedere le nuove cartelle dei plugin nell'esploratore dei file:

Dopo di che è sufficiente riavviare SQX per vedere il nuovo task disponibile nei progetti personalizzati.

 

Plugin ImpostazioniFiltroPerCorrelazione

Descriviamo innanzitutto il plugin delle impostazioni. Si tratta di un plugin che implementa le impostazioni "complete", quindi quelle che appaiono nel file Impostazioni complete scheda. Può avere un'interfaccia utente diversa e più complicata rispetto alle semplici impostazioni visualizzate nella scheda Progressi scheda.

 

Anche in questo caso esamineremo tutti i file:

 

FilterByCorrelationCtrl.js

Controller Angular per questo plugin. La funzione principale del controllore è quella di aggiungere le variabili (i loro valori) nello scope e quindi renderle disponibili nel file HTML.

 

Nei plugin delle impostazioni impostiamo l'intera configurazione di FilterByCorrelationService:

$scope.config = FilterByCorrelationService.config;

 

Inoltre, è possibile impostare alcune variabili aggiuntive, ad esempio l'elenco dei tipi di correlazione/periodi utilizzati nelle caselle di riepilogo.

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

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

 

Oltre a impostare le variabili, questo controllore gestisce anche il caricamento/salvataggio delle impostazioni: quando devono essere salvate e quando lette.

 

Esiste un'azione del controllore settingsChanged() richiamato dall'HTML ad ogni cambio di input, e questo metodo richiama poi il metodo FilterByCorrelationService.saveSettings() per salvare le impostazioni.

 

Il caricamento delle impostazioni viene attivato da un evento RICARICA_TAB_IMPOSTAZIONI che viene richiamato automaticamente all'avvio della scheda o quando si passa a questa scheda da un'altra.

Il controllore delle impostazioni deve aggiungere un ascoltatore a questo evento e quando si passa alla scheda delle impostazioni si attiva questo evento che richiama il metodo init() che a sua volta carica le impostazioni correnti chiamando FilterByCorrelationService.loadSettings();

 

FilterByCorrelationService.js

Servizio per questo filtro, che gestisce cose come il caricamento e il salvataggio dei dati da/verso il backend, l'impostazione di valori predefiniti, ecc.

Tutti i servizi sono istanze singleton e vengono creati una sola volta all'avvio dell'applicazione.

Ogni servizio di impostazioni contiene un oggetto config che contiene le impostazioni per l'attività attualmente selezionata e i metodi loadSettings/saveSettings.

 

Le impostazioni xml correnti per l'attività selezionata si ottengono con una chiamata:

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

 

Poi possiamo leggere il valore da xml:

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

 

o scrivere valori in esso:

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

 

Quindi nel servizio cambiamo direttamente l'XML.

 

Attenzione: l'istanza del servizio è una sola, condivisa tra il plugin Impostazioni (interfaccia utente completa) e il plugin Attività (interfaccia utente semplice).

 

modulo.js

Registra il plugin nell'interfaccia dell'interfaccia utente. Per visualizzare l'intero pannello delle impostazioni, è necessario registrare un plugin del tipo SettingsTab.

Gli attributi obbligatori del plugin sono:

  • task - nome del task per il quale deve essere visualizzata, in questo caso "FilterByCorrelation". Se si desidera visualizzare questa scheda di impostazione anche per i task Build e Retest, ci sarà 'FilterByCorrelation,Build,Retest'.
  • configElemName - nome dell'impostazione in xml
  • templateUrl - quale html visualizzare
  • controllore - quale controllore è legato all'html dalla definizione del templateUrl
  • dataItem - ID scheda di impostazione, deve avere un nome univoco tra le schede di SettingsTab

 

altre impostazioni, come titolo, aiuto, helpUrl, sono comprensibili dal nome dell'attributo.

 

settings.html, styles.css

File HTML contenente la definizione UI delle impostazioni e la definizione CSS degli stili utilizzati.

 

SettingsFilterByCorrelation.jar

Questo è un plugin già compilato. Non lo si vedrà nel proprio plugin fino a quando non lo si compilerà - si vedano le istruzioni su come farlo più avanti.

 

SettingsFilterByCorrelation.java

Classe Java che gestisce il backend di questo plugin. Implementa ISettingTabPlugin

L'interfaccia e il metodo più importante è readSettings() - che legge le impostazioni dall'XML fornito dall'interfaccia utente (parametro elSettings), le analizza e le salva in un oggetto dati con le chiavi uniche di questo plugin:

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 {
            Databank dbSource = ProjectConfigHelper.getDatabankByType(projectName, "Source", elSettings);
            Databank dbTarget = ProjectConfigHelper.getDatabankByType(projectName, "Target", elSettings);
            Databank 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("Impossibile caricare le impostazioni di FilterByCorrelation. ") + e.getMessage());
        }
    }

 

Plugin TaskFilterByCorrelation

Come detto sopra, questo è il plugin "principale" che implementa la funzionalità. Questo plugin è anche responsabile della visualizzazione delle impostazioni "semplici" visibili nella scheda Progress.

 

Si può notare che il plugin è composto da diversi file, compresa la struttura delle sottocartelle. Li esamineremo uno per uno.

 

modulo.js

Registra il plugin nell'interfaccia dell'interfaccia utente. Per visualizzare le impostazioni semplici, è necessario registrare un plugin di tipo "SimpleTaskSettings".

Gli argomenti obbligatori del plugin sono:

  • taskType - nome del task a cui fa riferimento
  • templateUrl - URL del file HTML che contiene l'interfaccia utente, uno degli altri file descritti di seguito.
  • controllore - quale controllore sarà collegato al template HTML - anche in questo caso questo controllore è definito in uno dei file successivi

Il suo codice JavaScript:

angular.module('app.settings').config(function(sqPluginProvider, SQEventsProvider) {
    sqPluginProvider.plugin("SimpleTaskSettings", 1, {
        taskType: 'FilterByCorrelation',
        templateUrl: '../../../plugins/TaskFilterByCorrelation/simpleSettings/simpleSettings.html',
        controllore: 'SimpleFilterByCorrelationCtrl',
        getInfoPanels: function(xmlConfig, injector){
            var L = injector.get("L");
            var settingsPlugins = sqPluginProvider.getPlugins('SettingsTab');
            var groups = [
                {
                    titolo: L.tsq('Opzioni di filtraggio'),
                    impostazioni: [
                        { name : L.tsq("Filtraggio"), value : getTaskInfoPanelSettings(xmlConfig, getItem(settingsPlugins, 'configElemName', "FilterByCorrelation")) }
                    ]
                }
            ];
           
            restituire i gruppi;
        }
    });
});

 

cartella simpleSettings

Contiene l'interfaccia utente per le impostazioni semplici di questo plugin: si tratta delle mini-impostazioni visualizzate nella scheda Progress.

 

SimpleFilterByCorrelationCtrl.js e simpleSettings.html

Codice HTML per le impostazioni e controller Angular che lo gestisce. Il controllore delle impostazioni semplice funziona come il controllore delle impostazioni completo descritto sopra, con una differenza: non deve implementare quando caricare le impostazioni, perché questo è già fatto nel controllore delle impostazioni completo.

 

stili.css

File che può contenere gli stili utilizzati nell'interfaccia utente.

 

task.xml

Impostazioni predefinite di questo task. Si può notare che in questo plugin salviamo fondamentalmente:

  • 3 banche dati - Fonte, Target, Esistente
  • Impostazioni del filtro di correlazione

Come descritto in Servizio FiltroPerCorrelazione descrizione, il servizio manipola direttamente l'XML: carica l'XML dal backend e invia l'XML al backend per salvare le modifiche.

La struttura predefinita delle impostazioni XML per il nostro plugin è definita qui e nella classe del servizio.

 

TaskFilterByCorrelation.jar

Questo è un plugin già compilato. Non lo si vedrà nel proprio plugin fino a quando non lo si compilerà - si vedano le istruzioni su come farlo più avanti.

 

TaskFilterByCorrelation.java

Classe Java che gestisce il backend di questo plugin. Poiché si tratta di un plugin per i task, è esteso da Compito astratto:

public class TaskFilterByCorrelation extends AbstractTask {

 

Il metodo più importante è start() - è il metodo che viene richiamato quando si fa clic sul pulsante Avvia nel progetto personalizzato ed è qui che viene implementata la funzionalità principale:

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

 

all'inizio carica le impostazioni - questo carica le impostazioni che sono state preparate nel nostro secondo plugin ImpostazioniFiltroPerCorrelazione

Quindi aggiorna il motore di avanzamento:

        progressEngine.setLogPrefix(taskLogPrefix);
        progressEngine.printToLog(L.t("Avvio filtraggio strategie..."));
        progressEngine.start();

 

Il resto è la funzionalità principale: esaminare una per una le strategie della banca dati di origine, calcolarne la correlazione e copiarle nella banca dati di destinazione:

        Gruppo di risultati strategiaCloned;
        ArrayList results = databankSource.getRecords();

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

        for(int i=0; i<risultati.size(); i++) {
            ResultsGroup strategy = results.get(i);
            String strategyName = strategy.getName();
           
            try {
                String dismissalMessage = checkCorrelation(strategy);
                if(dismissalMessage != null) {
                    progressEngine.printToLogDebug(L.t("%s saltato, %s", strategyName, dismissalMessage));
                    increaseGlobalStats(false);
                   
                    continua;
                }
                //copiare dall'origine alla destinazione
                strategyCloned = strategy.clone();
                databankTarget.add(strategyCloned, true);
               
                progressEngine.printToLogDebug(L.t("%s copiato, %s", strategyName, String.format("correlazione < %.2f", correlation.maxCorrelation));
               
                this.totalCopied++;
               
                increaseGlobalStats(true);
               
                progressEngine.checkPaused();
               
                se(progressEngine.isStopped()) {
                    break;
                }
            }
            catch (OutOfMemoryError e) {
                project.onMemoryError(e);
                break;
            }
        }
      
        databankTarget.updateBestResults();
       
        progressEngine.finish();

 

 

Compilazione dei plugin

Entrambi i plugin devono essere compilati affinché SQX possa caricarli. Questo può essere fatto semplicemente in Editor di codiceè sufficiente fare clic con il tasto destro del mouse sulla cartella dei plugin e scegliere Compilazione del plugin dal menu:

Se non ci sono errori, il plugin verrà compilato e verrà creato un nuovo file con il nome del plugin e la dicitura .jar nella cartella apparirà l'estensione.

 

Si noti che è necessario compilare entrambi i plugin. Quindi riavviate SQX e dovreste vedere il vostro nuovo plugin nelle attività del progetto personalizzato.

Questo articolo è stato utile? L'articolo è stato utile L'articolo non è stato utile

Abbonarsi
Notificami
3 Commenti
Il più vecchio
Più recente I più votati
Feedback in linea
Visualizza tutti i commenti
tnickel
26. 11. 2023 10:18

Ho sbagliato questa funzione per molto tempo. Ora sono felice. Ho ottenuto questa funzione e una descrizione di alto livello su come implementare le proprie attività. Sono felice.

Giordania
30. 11. 2023 12:55 pm

Ottimo lavoro! Non vedo l'ora di poter usufruire di questa funzione. Grazie.

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

Messaggi correlati