ドキュメント

アプリケーション

最終更新日: 2023年11月1日(マーク・フリック)

プログラムで構成要素を選択する

これはこの記事の続きです: https://strategyquant.com/doc/programming-for-sq/changing-task-config-programmatically/
それは、プログラムによってタスクの設定を変更する方法を示していました。.

最初の例の一般的な考え方は、タスクのXML設定を操作しそれをタスクに再適用することで、タスクの設定を変更できるということです。.
この例では、この方法で構成要素を有効化/無効化する方法を示します。.

 

タスクXMLにおけるビルディングブロックの格納方法

すべてのビルディングブロックは、要素内に子および孫要素として格納されます。 ->.

各ビルディングブロックは、それぞれ独自の要素として構成され、その 鍵 – それがそのスニペット名です。.

 

キー値にはいくつかの標準があります:

  • もしそうなら 信号ブロック または 比較, 、キーにはスニペットの名前のみが含まれます。例: key=”ADXChangesDown” または key=”IsGreater”
  • もしそうなら インジケーター (信号ではなく)、そのキーには文字列「Indicator.」が接頭辞として付いています。例えば key=”Indicators.ADX”
  • もしそうなら 価格, 、そのキーには文字列「Prices.」がプレフィックスとして付加されます。例えば key=”Prices.High”
  • もしそうなら ストップ/リミットレベル (ストップ注文または指値注文の場合)、そのキーには「Stop/Limit Price Levels.」という文字列が前置されます。例: key=”ストップ/リミット価格水準.TEMA”
  • もしそうなら ストップ・リミット・レンジ (ストップまたは指値注文の場合)、そのキーには「Stop/Limit Price Ranges.」という文字列が前置されます。例: key=”ストップ・リミット価格範囲.BBWidthRatio”

 

要素のもう1つの重要な属性は 使用する. ビルド時にブロックを使用する場合は「true」に、そうでない場合は「false」に設定してください。.

したがって、特定のブロックを有効または無効にしたい場合は、次の手順を行うだけです:

  1. その要素を見つける
  2. 「use」属性を次のように「true」または「false」に設定します:…

 

この記事にはBuilderタスクのXMLの例が添付されています – ファイル名 Build-Task1.xml

 

例

この機能の例として、ケルトナーチャネル(KC)とボリンジャーバンド(BB)のシグナルブロックをプログラムで切り替えますが、他のすべてのブロックは無効化されます。.

カスタムプロジェクトには2つのタスクが含まれます。1つ目はカスタム分析スニペットを適用する「カスタム分析タスク」、2つ目は「ビルダータスク」で、このビルダータスクの設定をカスタム分析スニペット内で変更します。.

 

したがって、カスタムプロジェクトを初めて実行したときは、ボリンジャーバンドのシグナルブロックのみが有効になります。2回目に実行したときは、ケルトナーチャネルのブロックのみが有効になり、以降も同様となります。.

すべてのボリンジャーバンドのシグナルブロックには、BBで始まるスニペット(例:key=”BBBarClosesAboveDown”)があり、すべてのケルトナーチャネルのシグナルブロックには、KCで始まるスニペット(例:key=”KCBarClosesAboveLower”)があります。.
ケルトナーチャネルまたはボリンジャーバンドのシグナルブロックであると認識するために、BBまたはKCのプレフィックスを使用します。.

以下の例は、記事中のものと本質的に同じです。 https://strategyquant.com/doc/programming-for-sq/changing-task-config-programmatically/ – ここだけはXMLの処理が異なります。.

私たちは標準を使用します JDOM XMLを走査して属性を取得または変更するためのライブラリ機能.

ステップ 1 – すべてのブロック要素の取得

Element elBlocks = XMLUtil.getChildElem(elNewConfig, "Blocks");
if(elBlocks == null) {
    throw new Exception("要素が存在しません。Builderタスクでしょうか?");
}
Element buildingBlocks = XMLUtil.getChildElem(elBlocks, "BuildingBlocks");
// あるいは、あらかじめ用意されたファイルから新しいタスク設定を読み込むこともできます
//Element elNewConfig = XMLUtil.fileToXmlElement(new File("c:/BuildTask2009_2019.xml"));

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

 

ステップ 2 – activeBlock 変数の初期化

この変数を使用してBBまたはKCブロックを使用するかどうかを判断します。BBブロックとKCブロックを切り替えているため、どちらを有効にし、どちらを無効にするかを決定する必要があります。.

// BBからKCへの切り替えに使用する変数です。値の意味は以下の通りです:
// 0 - 未知、最初に発見されたブロックによって設定されます
// 1 - BBブロックがアクティブになるべき
// 2 - KCブロックがアクティブになるべき
int activeBlock = 0;

 

ステップ3 – すべてのブロックをループ処理する

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

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

 

ステップ4 – キーがBBまたはKCで始まらない場合、それは異なるブロックであり、オフにする必要があります

if(!key.startsWith("BB") && !key.startsWith("KC")) {
    // ボリンジャーバンドでもケルトナーチャネルブロックでもないので、オフにする
    elBlock.setAttribute("use", "false");
    continue;
}

 

ステップ5 – それ以外の場合はKCまたはBBブロック

activeBlock変数の正しい値を認識してください:

// it is either BB or KC block
String use = elBlock.getAttributeValue("use");

if(activeBlock == 0) {
    // we'll determine if BB or KC blocks should be active by first block found
    if(key.startsWith("BB")) {
        if (use.equals("true")) {
            // BB was active before, now KC will be active
            activeBlock = 2;
        }
    } else if(key.startsWith("KC")) {
        if(use.equals("true")) {
            // KC was active before, now BB will be active
            activeBlock = 1;
        }
    }

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

    Log.info("----- Turning on "+(activeBlock == 1 ? "Bollinger Bands" : "Keltner Channel")+" blocks.");
}

 

ステップ6 – 最も重要なこと

BBまたはKCブロックのいずれかを次に応じてONにする アクティブブロック use属性をtrueまたはfalseに設定することで、変数を:

// now turn the block on or off according to activeBlock value
if(key.startsWith("BB")) {
    elBlock.setAttribute("use", (activeBlock == 1 ? "true" : "false"));
} else if(key.startsWith("KC")) {
    elBlock.setAttribute("use", (activeBlock == 2 ? "true" : "false"));
}

 

ステップ 7 – 変更した設定をタスクに適用する

すべてのビルディングブロックの確認が終わりましたので、修正した設定をタスクに適用してください:

// Apply the modified config to the task
buildTask.setConfig(elNewConfig, true);

// this notifies UI to load che changed config and apply it to the UI.
// Without this it would still work but you'll not see the changes in the UI
JSONObject jsonData = new JSONObject().put("projectConfig",  sqProject.toJSON());
DataToSend dataToSend = new DataToSend(WebSocketConst.UpdateProject, jsonData);
SQWebSocketManager.addToDataQueue(dataToSend, SQConst.CODE_TASKMANAGER);

 

これだけです。.

これで、カスタムプロジェクトを開始するたびに、ビルディングブロックがボリンジャーバンドとケルトチャネルのシグナル間で切り替わります。.

 

 

CAChangeBlocksConfigスニペットの完全なコード:

package 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.project.ProjectEngine;
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<ResultsGroup> processDatabank(String project, String task, String databankName, ArrayList<ResultsGroup> databankRG) throws Exception {

        // get current project
        SQProject sqProject = ProjectEngine.get(project);

        // get task by name
        ISQTask buildTask = sqProject.getTaskByName("Build strategies");
        if(buildTask == null) {
            throw new Exception("No such task exists!");
        }
        // alternatively you can use sqProject.getTasks() to get a list of all tasks
        // and go through them to get the one you want


        // this is how you get task settings XML in the new way (SQ 136 up)
        // It returns JDOM XML Element with full task configuration
        Element elConfig = buildTask.getConfig();
        // create a new config by cloning it - it is important to make a clone,
        // otherwise your new config will be not applied
        Element elNewConfig = elConfig.clone();

        // now change anything in the new config
        Element elBlocks = XMLUtil.getChildElem(elNewConfig, "Blocks");
        if(elBlocks == null) {
            throw new Exception("No <Blocks> element exists, is it Builder task?");
        }
        Element buildingBlocks = XMLUtil.getChildElem(elBlocks, "BuildingBlocks");
        // alternatively you can load the new task config from prepared file
        //Element elNewConfig = XMLUtil.fileToXmlElement(new File("c:/BuildTask2009_2019.xml"));

        List<Element> blocks = buildingBlocks.getChildren("Block");

        // we'll use this variable to switch from BB to KC. The values are:
        // 0 - not known, will be set by first found block
        // 1 - BB blocks should be active
        // 2 - KC blocks should be active
        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")) {
                // it is not Bollinger Bands nor Keltner Channel block, turn it off
                elBlock.setAttribute("use", "false");
                continue;
            }

            // it is either BB or KC block
            String use = elBlock.getAttributeValue("use");

            if(activeBlock == 0) {
                // we'll determine if BB or KC blocks should be active by first block found
                if(key.startsWith("BB")) {
                    if (use.equals("true")) {
                        // BB was active before, now KC will be active
                        activeBlock = 2;
                    }
                } else if(key.startsWith("KC")) {
                    if(use.equals("true")) {
                        // KC was active before, now BB will be active
                        activeBlock = 1;
                    }
                }

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

                Log.info("----- Turning on "+(activeBlock == 1 ? "Bollinger Bands" : "Keltner Channel")+" blocks.");
            }

            // now turn the block on or off according to activeBlock value
            if(key.startsWith("BB")) {
                elBlock.setAttribute("use", (activeBlock == 1 ? "true" : "false"));
            } else if(key.startsWith("KC")) {
                elBlock.setAttribute("use", (activeBlock == 2 ? "true" : "false"));
            }
        }


        // Apply the modified config to the task
        buildTask.setConfig(elNewConfig, true);

        // this notifies UI to load che changed config and apply it to the UI.
        // Without this it would still work but you'll not see the changes in the UI
        JSONObject jsonData = new JSONObject().put("projectConfig",  sqProject.toJSON());
        DataToSend dataToSend = new DataToSend(WebSocketConst.UpdateProject, jsonData);
        SQWebSocketManager.addToDataQueue(dataToSend, SQConst.CODE_TASKMANAGER);

        return databankRG;
    }
}

 

この記事は参考になりましたか? この記事は役に立った この記事は役に立たなかった

1 コメント
最古の
最新 最も投票された
エマニュエル
2023年1月15日 午後7:24

マーク、素晴らしい例をありがとうございます
それはとても役に立ちます

関連記事