Dokumentation

Anwendungen

Zuletzt aktualisiert am 11. 1. 2023 von Mark Fric

Programmatische Auswahl von Bausteinen

Dies ist eine Erweiterung dieses Artikels: https://strategyquant.com/doc/programming-for-sq/changing-task-config-programmatically/
in dem gezeigt wurde, wie Sie die Aufgabenkonfiguration programmatisch ändern können.

Der Grundgedanke des ersten Beispiels ist, dass Sie die Aufgabenkonfiguration ändern können, indem Sie die XML-Konfiguration manipulieren und sie erneut auf die Aufgabe anwenden.
In diesem Beispiel demonstrieren wir, wie Sie auf diese Weise Bausteine aktivieren/deaktivieren können.

 

Wie Bausteine in der Aufgaben-XML gespeichert werden

Alle Bausteine werden als Kinder und Unterkinder im Element ->.

Jeder Baustein wird in einem eigenen -Element konfiguriert, das eindeutig durch seine Schlüssel - was der Name des Snippets ist.

 

Es gibt einige Standards bei den Schlüsselwerten:

  • wenn es sich Signalblock oder Vergleichenthält der Schlüssel nur den Namen des Snippets, zum Beispiel key="ADXChangesDown" oder key="IsGreater"
  • wenn es sich Anzeige (kein Signal), wird dem Schlüssel die Zeichenfolge "Indikator" vorangestellt, zum Beispiel key="Indicators.ADX"
  • wenn es sich Preiswird dem Schlüssel die Zeichenfolge "Preise" vorangestellt, zum Beispiel key="Preise.Hoch"
  • wenn es sich Stopp-/Grenzwert (für Stop- oder Limit-Aufträge), wird dem Schlüssel die Zeichenkette "Stop/Limit Price Levels" vorangestellt, zum Beispiel key="Stop/Limit Price Levels.TEMA"
  • wenn es sich Stopp-/Grenzbereich (für Stop- oder Limit-Aufträge), wird dem Schlüssel die Zeichenfolge "Stop/Limit Price Ranges" vorangestellt, z. B. key="Stop/Limit Price Ranges.BBWidthRatio"

 

Ein weiteres wichtiges Attribut des -Elements ist verwenden.. Wenn Sie möchten, dass der Block während der Erstellung verwendet wird, sollten Sie ihn auf "true" setzen, ansonsten auf "false".

Wenn Sie also einen bestimmten Block aktivieren oder deaktivieren möchten, brauchen Sie nur diesen Schritt zu tun:

  1. sein -Element finden
  2. setzen Sie das Attribut use auf true oder false wie folgt: ...

 

Es ist ein Beispiel für Builder Aufgabe XML in diesem Artikel beigefügt - Datei Build-Task1.xml

 

Beispiel

Als Beispiel für diese Funktionalität werden wir programmatisch zwischen den Signalblöcken Keltner Channel (KC) und Bollinger Bands (BB) umschalten, alle anderen Blöcke werden deaktiviert.

Wir werden ein benutzerdefiniertes Projekt mit zwei Aufgaben haben - die erste ist die Aufgabe "Benutzerdefinierte Analyse", die unser Snippet "Benutzerdefinierte Analyse" anwenden wird. Die zweite ist die Builder-Aufgabe - wir werden die Konfiguration dieser Builder-Aufgabe in unserem CA-Snipet ändern.

 

Wenn Sie also das benutzerdefinierte Projekt zum ersten Mal ausführen, werden nur die Blöcke für Bollinger Bandsignale aktiviert. Wenn Sie es zum zweiten Mal ausführen, werden nur die Blöcke des Keltner-Kanals aktiviert, und so weiter.

Alle Bollinger-Band-Signalblöcke haben Snippets mit BB-Präfix - BB*********, zum Beispiel key="BBBarClosesAboveDown", und alle Keltner-Kanal-Signalblöcke haben Snippets mit dem Namen KC*********, zum Beispiel key="KCBarClosesAboveLower".
Wir verwenden dieses BB- oder KC-Präfix, um zu erkennen, dass es sich entweder um einen Keltner-Kanal- oder Bollinger-Band-Signalblock handelt.

Das folgende Beispiel ist im Wesentlichen dasselbe wie im Artikel https://strategyquant.com/doc/programming-for-sq/changing-task-config-programmatically/ - nur hier machen wir etwas anderes mit dem XML.

Wir verwenden Standard JDOM Bibliotheksfunktionalität, um das XML zu durchsuchen und seine Attribute zu erhalten oder zu ändern.

Schritt 1 - Ermittlung aller Blockelemente

Element elBlocks = XMLUtil.getChildElem(elNewConfig, "Blocks");
if(elBlocks == null) {
    throw new Exception("Es existiert kein -Element, ist es eine Bauherrenaufgabe?");
}
Element buildingBlocks = XMLUtil.getChildElem(elBlocks, "BuildingBlocks");
// alternativ kann man die neue Aufgabenkonfiguration aus einer vorbereiteten Datei laden
//Element elNewConfig = XMLUtil.fileToXmlElement(new File("c:/BuildTask2009_2019.xml"));

List blocks = buildingBlocks.getChildren("Block");

 

Schritt 2 - Initialisierung der activeBlock-Variable

verwenden wir diese Variable, um zu bestimmen, ob BB- oder KC-Blöcke verwendet werden sollen - denken Sie daran, dass wir zwischen BB- und KC-Blöcken umschalten, also müssen wir bestimmen, welcher von beiden ein- und ausgeschaltet werden soll.

// Mit dieser Variablen wird von BB auf KC umgeschaltet. Die Werte sind:
// 0 - nicht bekannt, wird vom ersten gefundenen Block gesetzt
// 1 - BB-Blöcke sollten aktiv sein
// 2 - KC-Blöcke sollten aktiv sein
int activeBlock = 0;

 

Schritt 3 - Durchlaufen aller Blöcke in einer Schleife

for(int i=0; i<blocks.size(); i++) {
    Element elBlock = blocks.get(i);

    String key = elBlock.getAttributeValue("key");

 

Schritt 4 - Wenn die Taste nicht mit BB oder KC beginnt, handelt es sich um einen anderen Block und sollte ausgeschaltet werden.

if(!key.startsWith("BB") && !key.startsWith("KC")) {
    // es ist weder Bollinger Bands noch Keltner Channel Block, schalten Sie es aus
    elBlock.setAttribute("use", "false");
    fortfahren;
}

 

Schritt 5 - Andernfalls handelt es sich um einen KC- oder BB-Block

Erkennen Sie nun den richtigen Wert der activeBlock-Variable:

// es ist entweder ein BB- oder ein KC-Block
String use = elBlock.getAttributeValue("use");

if(activeBlock == 0) {
    // wir bestimmen anhand des ersten gefundenen Blocks, ob BB- oder KC-Blöcke aktiv sein sollen
    if(key.startsWith("BB")) {
        if (use.equals("true")) {
            // BB war vorher aktiv, jetzt wird KC aktiv sein
            activeBlock = 2;
        }
    } else if(key.startsWith("KC")) {
        if(use.equals("true")) {
            // KC war vorher aktiv, jetzt wird BB aktiv sein
            activeBlock = 1;
        }
    }

    if(activeBlock == 0) {
        activeBlock = 1;
    }

    Log.info("----- Einschalten von "+(activeBlock == 1 ? "Bollinger Bands" : "Keltner Channel")+" Blöcken.");
}

 

Schritt 6 - die Hauptsache

schalten Sie entweder den BB- oder den KC-Block ein, je nach activeBlock indem Sie ihr Attribut use auf true oder false setzen:

// schalten Sie nun den Block entsprechend dem activeBlock-Wert ein oder aus
if(key.startsWith("BB")) {
    elBlock.setAttribute("use", (activeBlock == 1 ? "true" : "false"));
} else if(key.startsWith("KC")) {
    elBlock.setAttribute("use", (activeBlock == 2 ? "true" : "false"));
}

 

Schritt 7 - Anwenden der geänderten Konfiguration auf die Aufgabe

Wir sind damit fertig, alle Bausteine durchzugehen, jetzt müssen wir nur noch die geänderte Konfiguration auf die Aufgabe anwenden:

// Die geänderte Konfiguration auf die Aufgabe anwenden
buildTask.setConfig(elNewConfig, true);

// Dies benachrichtigt die Benutzeroberfläche, die geänderte Konfiguration zu laden und auf die Benutzeroberfläche anzuwenden.
// Ohne dies würde es immer noch funktionieren, aber Sie werden die Änderungen in der UI nicht sehen
JSONObject jsonData = new JSONObject().put("projectConfig", sqProject.toJSON());
DataToSend dataToSend = new DataToSend(WebSocketConst.UpdateProject, jsonData);
SQWebSocketManager.addToDataQueue(dataToSend, SQConst.CODE_TASKMANAGER);

 

Und das ist alles.

Wenn Sie nun das benutzerdefinierte Projekt starten, werden die Bausteine zwischen Bollinger Bands und Keltner Channel-Signalen umgeschaltet.

 

 

Vollständiger Code des CAChangeBlocksConfig-Snippets:

Paket SQ.CustomAnalysis;

import com.strategyquant.lib.XMLUtil;
import com.strategyquant.lib.constants.SQConst;
import com.strategyquant.tradinglib.CustomAnalysisMethod;
import com.strategyquant.tradinglib.ResultsGroup; import com.strategyquant.tradinglib.ResultsGroup;
import com.strategyquant.tradinglib.project.ProjectEngine;
import com.strategyquant.tradinglib.project.SQProject; import com.strategyquant.tradinglib.project.SQProject;
import com.strategyquant.tradinglib.project.websocket.DataToSend;
import com.strategyquant.tradinglib.project.websocket.SQWebSocketManager;
import com.strategyquant.tradinglib.project.websocket.WebSocketConst;
import com.strategyquant.tradinglib.taskImpl.ISQTask;
import org.jdom2.Element;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

public class CAChangeBlocksConfig extends CustomAnalysisMethod {

    //------------------------------------------------------------------------
    //------------------------------------------------------------------------
    //------------------------------------------------------------------------

    public CAChangeBlocksConfig() {
        super("CAChangeBlocksConfig", TYPE_PROCESS_DATABANK);
    }

    //------------------------------------------------------------------------

    @Override
    public ArrayList processDatabank(String project, String task, String databankName, ArrayList databankRG) throws Exception {

        // aktuelles Projekt holen
        SQProject sqProject = ProjectEngine.get(project);

        // Aufgabe nach Name abrufen
        ISQTask buildTask = sqProject.getTaskByName("Strategien erstellen");
        if(buildTask == null) {
            throw new Exception("Eine solche Aufgabe existiert nicht!");
        }
        // alternativ können Sie sqProject.getTasks() verwenden, um eine Liste aller Aufgaben zu erhalten
        // und sie durchgehen, um die gewünschte Aufgabe zu finden


        // So erhalten Sie das XML der Aufgabeneinstellungen auf die neue Art (SQ 136 up)
        // Es gibt ein JDOM XML-Element mit der vollständigen Aufgabenkonfiguration zurück
        Element elConfig = buildTask.getConfig();
        // Erstellen Sie eine neue Konfiguration, indem Sie sie klonen - es ist wichtig, einen Klon zu erstellen,
        // sonst wird die neue Konfiguration nicht übernommen
        Element elNewConfig = elConfig.clone();

        // Ändern Sie nun alles in der neuen Konfiguration
        Element elBlocks = XMLUtil.getChildElem(elNewConfig, "Blocks");
        if(elBlocks == null) {
            throw new Exception("Es existiert kein -Element, ist es eine Bauherrenaufgabe?");
        }
        Element buildingBlocks = XMLUtil.getChildElem(elBlocks, "BuildingBlocks");
        // alternativ kann man die neue Aufgabenkonfiguration aus einer vorbereiteten Datei laden
        //Element elNewConfig = XMLUtil.fileToXmlElement(new File("c:/BuildTask2009_2019.xml"));

        List blocks = buildingBlocks.getChildren("Block");

        // Wir verwenden diese Variable, um von BB zu KC zu wechseln. Die Werte sind:
        // 0 - nicht bekannt, wird vom ersten gefundenen Block gesetzt
        // 1 - BB-Blöcke sollten aktiv sein
        // 2 - KC-Blöcke sollten aktiv sein
        int activeBlock = 0;

        for(int i=0; i<blocks.size(); i++) {
            Element elBlock = blocks.get(i);

            String key = elBlock.getAttributeValue("key");

            if(!key.startsWith("BB") && !key.startsWith("KC")) {
                // es handelt sich weder um einen Bollinger-Band- noch um einen Keltner-Kanal-Block, schalten Sie ihn aus
                elBlock.setAttribute("use", "false");
                fortfahren;
            }

            // es ist entweder ein BB- oder KC-Block
            String use = elBlock.getAttributeValue("use");

            if(activeBlock == 0) {
                // wir bestimmen anhand des ersten gefundenen Blocks, ob BB- oder KC-Blöcke aktiv sein sollen
                if(key.startsWith("BB")) {
                    if (use.equals("true")) {
                        // BB war vorher aktiv, jetzt wird KC aktiv sein
                        activeBlock = 2;
                    }
                } else if(key.startsWith("KC")) {
                    if(use.equals("true")) {
                        // KC war vorher aktiv, jetzt wird BB aktiv sein
                        activeBlock = 1;
                    }
                }

                if(activeBlock == 0) {
                    activeBlock = 1;
                }

                Log.info("----- Einschalten von "+(activeBlock == 1 ? "Bollinger Bands" : "Keltner Channel")+" Blöcken.");
            }

            // schaltet nun den Block entsprechend dem activeBlock-Wert ein oder aus
            if(key.startsWith("BB")) {
                elBlock.setAttribute("use", (activeBlock == 1 ? "true" : "false"));
            } else if(key.startsWith("KC")) {
                elBlock.setAttribute("use", (activeBlock == 2 ? "true" : "false"));
            }
        }


        // Anwenden der geänderten Konfiguration auf die Aufgabe
        buildTask.setConfig(elNewConfig, true);

        // Dies benachrichtigt die Benutzeroberfläche, die geänderte Konfiguration zu laden und auf die Benutzeroberfläche anzuwenden.
        // Ohne dies würde es immer noch funktionieren, aber Sie werden die Änderungen in der UI nicht sehen
        JSONObject jsonData = new JSONObject().put("projectConfig", sqProject.toJSON());
        DataToSend dataToSend = new DataToSend(WebSocketConst.UpdateProject, jsonData);
        SQWebSocketManager.addToDataQueue(dataToSend, SQConst.CODE_TASKMANAGER);

        return databankRG;
    }
}

 

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

Abonnieren
Benachrichtigen Sie mich bei
1 Kommentar
Älteste
Neuestes Meistgewählt
Inline-Rückmeldungen
Alle Kommentare anzeigen
Emmanuel
15. 1. 2023 7:24 pm

Vielen Dank, Mark, für dieses hervorragende Beispiel
Es wird sehr nützlich sein

Verwandte Beiträge