Dokumentation

Anwendungen

Zuletzt aktualisiert am 23. 11. 2023 von Mark Fric

Beispiel-Plugin - eine vollständige benutzerdefinierte Projektaufgabe

Dieser Artikel beschreibt die Entwicklung eines komplexen benutzerdefinierten Aufgaben-Plugins, das innerhalb eines benutzerdefinierten Projekts in StrategyQuant verwendet werden kann.

Hinweis 1 - wir mussten einige Änderungen in der Klassenstruktur vornehmen, um die Erstellung von externen Plugins dieses Typs zu ermöglichen. Aus diesem Grund wird dieses Plugin erst ab SQX Build 138 und später funktionieren.

Anmerkung 2 - wir haben nur eine begrenzte Anzahl von Dokumentationen und Beispielen zur Erweiterung von SQX mit Plugins, dies ist eines davon. Dieses Beispiel ist für Benutzer gedacht, die das Wissen haben und in der Lage sind, bestehenden Code zu verstehen.

 

Das Ziel

So entwickeln Sie eine neue benutzerdefinierte Aufgabe in StrategyQuant mit allen Einstellungen.

Wir implementieren ein neues benutzerdefiniertes Aufgaben-Plugin namens Nach Korrelation filtern.

 

Bitte verwechseln Sie dies nicht mit dem bereits existierenden Beispiel-Plugin mit demselben Namen im Artikel hier: https://strategyquant.com/doc/programming-for-sq/filter-by-correlation-plugin-example/

Dieses ältere Beispiel ist ein einfacheres Plugin, das eine neue Datenbankaktion implementiert.

Unser neues Beispiel würde diese Idee erweitern und ein ganzes Aufgaben-Plugin implementieren.

 

Das Ergebnis

Wie Sie unten sehen können - eine neue Aufgabe mit dem Namen Filter by correlation in der Custom projects Aufgaben zu wählen:

 

Und die Einstellungen für diese neue Aufgabe:

 

Diese Aufgabe erfüllt eine einfache Aufgabe - sie vergleicht Strategien von Quelle Datenbank mit bestehenden Strategien in Bestehend Datenbank und kopiert diejenigen, die eine niedrigere als die zulässige Korrelation aufweisen, in Ziel datenbank.

Diese (und jede andere) benutzerdefinierte Aufgabe besteht eigentlich aus zwei voneinander abhängigen Plugins:

TaskFilterByCorrelation

Plugin, das die Aufgabe selbst und die Hauptfunktionalität implementiert, plus UI für die einfachen Einstellungen - es ist dasjenige, das Sie auf der Registerkarte Progress für diese Aufgabe sehen.

 

EinstellungenFilterByCorrelation

Plugin, das die vollständigen Einstellungen für dieses Plugin implementiert, einschließlich der Benutzeroberfläche - es ist diejenige, die Sie auf der Registerkarte Vollständige Einstellungen sehen.

Alle Einstellungen dieser Aufgabe werden über dieses Einstellungs-Plugin geladen.

 

Bitte beachten Sie, dass diese Art von Plugin Java - für die Implementierung des Backends und der Funktionen - und JavaScript (AngularJS) für die Implementierung des Frontends kombiniert.

 

Allgemeine Schritte zur Implementierung eines neuen Aufgaben-Plugins

  1. Erstellen von Aufgaben- und Einstellungs-Plugins - sowohl Java- als auch JS-Teile
  2. Erstellen Sie die Standard-Task.xml mit den Einstellungen der Datenbanken, die automatisch erstellt werden, und den Standardeinstellungen im Task-Plugin

 

Jede neue Aufgabe, die Sie erstellen, muss sich an die Paketnamen halten:
Paket com.strategyquant.plugin.Task.impl.XXXXXX
Paket com.strategyquant.plugin.Settings.impl.XXXXX

Wenn XXXXX Ihr Name ist, erstellt SQX dann Ordner, damit die Paketnamen übereinstimmen:
AufgabeXXXXXXXXXX
EinstellungenXXXXXXXXX

In unserem Fall sind das folgende Ordner:
TaskFilterByCorrelation
EinstellungenFilterByCorrelation

 

Die beste Vorgehensweise bei der Erstellung eines eigenen Aufgaben-Plugins wäre:

  1. Erstellen Sie eine Kopie unserer beiden Beispiel-Plugins, ändern Sie die Klassennamen und Strings im Code von "FilterByCorrelation" in Ihren eigenen Namen
  2. Achten Sie darauf, dass Sie die entsprechenden .jar-Dateien beim Kopieren der Beispiele löschen bzw. nicht kopieren - .jar-Dateien werden beim Kompilieren Ihres eigenen Plugins erstellt.
  3. Implementierung verschiedener Einstellungen und Hauptfunktionen in Task- und Settings-Plugins (Java)
  4. Implementierung verschiedener UI in Einstellungen und Aufgaben-Plugins - sowohl in .HTML- als auch in .JS-Dateien

 

Importieren von Beispiel-Plugins in Ihre SQX

Beispiel-Plugins sind an diesen Artikel angehängt (oben). Beide Plugins werden in zwei verschiedenen Archiven geliefert - .sxp und Standard-ZIP.

Die ZIP-Version ist nicht zum Importieren gedacht, sondern dient nur der Bequemlichkeit - falls jemand die Dateien ansehen möchte, ohne sie in SQX zu importieren.

 

Das Importieren von Plugins mit .sxp ist einfach - öffnen Sie Ihren CodeEditor, gehen Sie auf Importieren, wählen Sie beide .sxp-Dateien - für beide Plugins und klicken Sie auf OK.

 

Die Plugins werden importiert, und Sie sollten die neuen Plugin-Ordner im Datei-Explorer sehen:

Danach brauchen Sie nur Ihre SQX neu zu starten, um die neue Aufgabe unter Benutzerdefinierte Projekte zu sehen.

 

EinstellungenFilterByCorrelation-Plugin

Wir beschreiben zunächst das Einstellungs-Plugin. Dies ist ein Plugin, das die "vollen" Einstellungen implementiert, also diejenigen, die in der Vollständige Einstellungen Registerkarte. Sie kann eine andere und kompliziertere Benutzeroberfläche haben als die einfachen Einstellungen, die auf der Registerkarte Fortschritt tab.

 

Auch hier werden wir alle Dateien durchgehen:

 

FilterByCorrelationCtrl.js

Angular-Controller für dieses Plugin. Die Hauptfunktion des Controllers besteht darin, Variablen (ihre Werte) in den Geltungsbereich aufzunehmen und sie so in der HTML-Datei verfügbar zu machen.

 

In den Einstellungen des Plugins setzen wir die gesamte Konfiguration von FilterByCorrelationService:

$scope.config = FilterByCorrelationService.config;

 

Außerdem können wir einige zusätzliche Variablen festlegen, z. B. die Liste der in den Listenfeldern verwendeten Korrelationstypen/Perioden.

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

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

 

Neben dem Setzen der Variablen kümmert sich diese Steuerung auch um das Laden/Speichern von Einstellungen - wann sie gespeichert und wann sie gelesen werden sollen.

 

Es gibt eine Controller-Aktion settingsChanged() von HTML bei jeder Änderung der Eingabe aufgerufen, und diese Methode ruft dann FilterByCorrelationService.saveSettings() um die Einstellungen zu speichern.

 

Das Laden der Einstellungen wird durch ein Ereignis ausgelöst EINSTELLUNGEN_TAB_NEU LADEN die automatisch beim Start der Registerkarte oder beim Wechsel zu dieser Registerkarte von einer anderen aufgerufen wird.

Der Einstellungscontroller muss diesem Ereignis einen Listener hinzufügen, der beim Wechsel zu dieser Registerkarte dieses Ereignis auslöst, das die init() Methode, die ihrerseits die aktuellen Einstellungen durch den Aufruf von FilterByCorrelationService.loadSettings();

 

FilterByCorrelationService.js

Dienst für diesen Filter, der Dinge wie das Laden und Speichern von Daten vom/zum Backend, das Setzen von Standardwerten usw. regelt.

Alle Dienste sind Singleton-Instanzen, sie werden nur einmal beim Start der Anwendung erstellt.

Jeder Einstellungsdienst enthält ein Config-Objekt, das die Einstellungen für die aktuell ausgewählte Aufgabe und die Methoden loadSettings/saveSettings enthält.

 

Die aktuellen xml-Einstellungen für die ausgewählte Aufgabe werden durch Aufruf ermittelt:

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

 

Dann können wir den Wert aus xml lesen:

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

 

oder schreiben Sie Werte hinein:

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

 

Im Service ändern wir also direkt das XML.

 

Bitte beachten Sie, dass es nur eine Dienstinstanz gibt, die von den Plugins Einstellungen (vollständige Benutzeroberfläche) und Aufgaben (einfache Benutzeroberfläche) gemeinsam genutzt wird.

 

modul.js

Registriert das Plugin in der UI-Schnittstelle. Um das vollständige Einstellungsfeld anzuzeigen, sollte ein Plugin vom Typ SettingsTab registriert werden.

Obligatorische Plugin-Attribute sind:

  • Aufgabe - Name der Aufgabe, für die sie angezeigt werden soll, in diesem Fall "FilterByCorrelation". Wenn wir diese Einstellungsregisterkarte auch für die Aufgaben "Erstellen" und "Erneuern" anzeigen möchten, steht dort "FilterByCorrelation,Erstellen,Erneuern".
  • configElemName - Name der Einstellung in xml
  • templateUrl - welche html-Datei angezeigt werden soll
  • Controller - welcher Controller an die HTML aus der TemplateUrl-Definition gebunden ist
  • dataItem - ID der Einstellungsregisterkarte, muss einen eindeutigen Namen unter den SettingsTab-Registerkarten haben

 

andere Einstellungen wie title, help, helpUrl, sind aus dem Attributnamen verständlich.

 

einstellungen.html, styles.css

HTML-Datei mit UI-Definition der Einstellungen und CSS-Definition der verwendeten Stile.

 

EinstellungenFilterByCorrelation.jar

Dies ist ein bereits kompiliertes Plugin. Sie werden es in Ihrem eigenen Plugin nicht sehen, bis Sie es kompiliert haben - siehe Anweisungen, wie Sie dies später tun.

 

EinstellungenFilterBisKorrelation.java

Java-Klasse, die das Backend für dieses Plugin verwaltet. Sie implementiert ISettingTabPlugin

Schnittstelle und die wichtigste Methode ist readSettings() - das die Einstellungen aus dem von der Benutzeroberfläche bereitgestellten XML (Parameter elSettings) liest, analysiert und in einem Datenobjekt unter den für dieses Plugin eindeutigen Schlüsseln speichert:

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());
            zurückgeben;
        }
       
        try {
            Datenbank dbSource = ProjectConfigHelper.getDatabankByType(Projektname, "Quelle", elSettings);
            Databank dbTarget = ProjectConfigHelper.getDatabankByType(Projektname, "Ziel", elSettings);
            Datenbank dbExisting = ProjectConfigHelper.getDatabankByType(Projektname, "Vorhanden", elSettings);

            data.addParam(SettingsKeys.DatabankSource, dbSource);
            data.addParam(SettingsKeys.DatabankTarget, dbTarget);
            data.addParam("DatabankBestehend", dbBestehend);

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

            data.addParam(SettingsKeys.Correlation, corr);

        } catch(Exception e){
            data.addError(getSettingName(), null, L.t("Cannot load FilterByCorrelation settings. ") + e.getMessage());
        }
    }

 

TaskFilterByCorrelation-Plugin

Wie oben erwähnt, ist dies das "Haupt"-Plugin, das die Funktionalität implementiert. Dieses Plugin ist auch für die Anzeige der "einfachen" Einstellungen verantwortlich, die auf der Registerkarte Progress sichtbar sind.

 

Wie Sie sehen können, besteht das Plugin aus mehreren Dateien, einschließlich der Unterordnerstruktur. Wir gehen sie eine nach der anderen durch.

 

modul.js

Registriert das Plugin in der UI-Schnittstelle. Um die einfachen Einstellungen anzuzeigen, muss es ein Plugin vom Typ "SimpleTaskSettings" registrieren.

Die obligatorischen Argumente des Plugins sind:

  • taskType - Name der Aufgabe, auf die er sich bezieht
  • templateUrl - URL zur HTML-Datei, die die Benutzeroberfläche enthält - es handelt sich um eine der anderen unten beschriebenen Dateien
  • Controller - welcher Controller mit dem HTML-Template verbunden werden soll - auch dieser Controller wird in einer der folgenden Dateien definiert

Sein JavaScript-Code:

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

 

Ordner "simpleSettings

Enthält die Benutzeroberfläche für die einfachen Einstellungen dieses Plugins - es handelt sich um die Mini-Einstellungen, die auf der Registerkarte Progress angezeigt werden.

 

SimpleFilterByCorrelationCtrl.js und simpleSettings.html

HTML-Code für die Einstellungen und Angular-Controller, der sie verarbeitet. Der einfache Einstellungscontroller funktioniert genauso wie der oben beschriebene vollständige Einstellungscontroller, mit einem Unterschied: Er muss nicht implementieren, wann die Einstellungen geladen werden sollen, da dies bereits im vollständigen Einstellungscontroller erfolgt.

 

styles.css

Datei, die in der Benutzeroberfläche verwendete Stile enthalten kann

 

aufgabe.xml

Standardeinstellungen für diese Aufgabe. Sie können sehen, dass in diesem Plugin wir grundsätzlich speichern:

  • 3 Datenbanken - Quelle, Ziel, Bestehendes
  • Einstellungen für die Korrelationsfilterung

Wie beschrieben in FilterByCorrelationService Beschreibung manipuliert der Dienst das XML direkt - er lädt XML aus dem Backend und sendet XML an das Backend, um die Änderungen zu speichern.

Die Standardstruktur der XML-Einstellungen für unser Plugin ist hier und in der Dienstklasse definiert.

 

TaskFilterByCorrelation.jar

Dies ist ein bereits kompiliertes Plugin. Sie werden es in Ihrem eigenen Plugin nicht sehen, bis Sie es kompiliert haben - siehe Anweisungen, wie Sie dies später tun.

 

TaskFilterByCorrelation.java

Java-Klasse, die das Backend für dieses Plugin verwaltet. Da es sich um ein Task-Plugin handelt, wird es erweitert von AbstrakteAufgabe:

public class TaskFilterByCorrelation extends AbstractTask {

 

Die wichtigste Methode ist start() - Dies ist die Methode, die aufgerufen wird, wenn Sie im benutzerdefinierten Projekt auf die Schaltfläche "Start" klicken, und hier wird die Hauptfunktionalität implementiert:

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

 

am Anfang werden Einstellungen geladen - diese Einstellungen wurden in unserem zweiten Plugin vorbereitet EinstellungenFilterByCorrelation

Dann wird die Fortschrittsmaschine aktualisiert:

        progressEngine.setLogPrefix(taskLogPrefix);
        progressEngine.printToLog(L.t("Starting strategies filtering..."));
        progressEngine.start();

 

Der Rest ist die Hauptfunktionalität - die Strategien in der Quelldatenbank eine nach der anderen durchzugehen, ihre Korrelation zu berechnen und sie in die Zieldatenbank zu kopieren:

        ErgebnisGruppe 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);
                if(dismissalMessage != null) {
                    progressEngine.printToLogDebug(L.t("%s übersprungen, %s", strategyName, dismissalMessage));
                    increaseGlobalStats(false);
                   
                    weiter;
                }
                //Kopieren von der Quelle zum Ziel
                strategyCloned = strategy.clone();
                databankTarget.add(strategyCloned, true);
               
                progressEngine.printToLogDebug(L.t("%s kopiert, %s", strategyName, String.format("Korrelation < %.2f", correlation.maxCorrelation)));
               
                this.totalCopied++;
               
                increaseGlobalStats(true);
               
                progressEngine.checkPaused();
               
                if(progressEngine.isStopped()) {
                    break;
                }
            }
            catch (OutOfMemoryError e) {
                project.onMemoryError(e);
                break;
            }
        }
      
        databankTarget.updateBestResults();
       
        progressEngine.finish();

 

 

Kompilieren der Plugins

Beide Plugins müssen kompiliert werden, damit SQX sie laden kann. Dies kann einfach in CodeEditorklicken Sie einfach mit der rechten Maustaste auf den Plugin-Ordner und wählen Sie Plugin kompilieren aus dem Menü:

Wenn es keine Fehler gibt, wird das Plugin kompiliert und eine neue Datei mit dem Namen des Plugins und .jar wird in dem Ordner angezeigt.

 

Bitte beachten Sie, dass Sie beide Plugins kompilieren müssen. Dann müssen Sie SQX neu starten und Sie sollten Ihr neues Plugin in den Custom project tasks sehen.

War dieser Artikel hilfreich? Der Artikel war nützlich Der Artikel war nicht nützlich

Abonnieren
Benachrichtigen Sie mich bei
3 Kommentare
Älteste
Neuestes Meistgewählt
Inline-Rückmeldungen
Alle Kommentare anzeigen
tnickel
26. 11. 2023 10:18 Uhr

Ich habe diese Funktion so lange Zeit vermisst. Jetzt bin ich glücklich. Ich habe diese Funktion und eine Top-Beschreibung, wie man eigene Aufgaben implementiert. Ich bin glücklich.

Jordanien
30. 11. 2023 12:55 Uhr

Großartige Arbeit! Ich freue mich sehr auf diese Funktion, danke.

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

Verwandte Beiträge