Documentação

Aplicações

Última atualização em 11. 1. 2023 por Mark Fric

Seleção programática de blocos de construção

Esta é uma extensão deste artigo: https://strategyquant.com/doc/programming-for-sq/changing-task-config-programmatically/
que demonstrou como você pode mudar programticamente a configuração das tarefas.

A idéia geral do exemplo inicial é que você pode mudar a configuração da tarefa manipulando sua configuração XML e reaplicando-a à tarefa.
Neste exemplo, vamos demonstrar como você pode habilitar/desabilitar blocos de construção desta forma.

 

Como os blocos de construção são armazenados na tarefa XML

Todos os blocos de construção são armazenados como crianças e subcrianças no elemento ->>BuildingBlocks>.

Cada bloco de construção é configurado em seu próprio elemento , identificado de forma única por seu chave - que é o nome de seu snippet.

 

Existem alguns padrões em valores-chave:

  • se for bloco de sinal ou comparaçãoa chave contém apenas o nome do trecho, por exemplo key="ADXChangesDown ou key="IsGreater"
  • se for indicador (não sinal), sua chave é prefixada por uma corda "Indicador", por exemplo key="Indicadores.ADX".
  • se for preçosua chave é prefixada por um fio "Preços", por exemplo key="Prices.High" (preços.altos)
  • se for nível de parada/limite (para ordens Stop ou Limit), sua chave é prefixada por uma string "Stop/Limit Price Levels", por exemplo key="Stop/Limit Price Levels.TEMA" (Parar/Limitar Níveis de Preços.TEMA)
  • se for intervalo de parada/limite (para ordens Stop ou Limit), sua chave é prefixada por uma string "Stop/Limit Price Ranges", por exemplo key="Stop/Limit Price Ranges.BBWidthRatio"

 

Outro importante atributo do elemento é uso. Se você quiser que o bloco seja usado durante a construção, você deve defini-lo como "verdadeiro", caso contrário, como "falso".

Portanto, se você quiser ativar ou desativar um determinado bloco, você só precisa fazê-lo:

  1. encontrar seu elemento
  2. definir atributo de uso para verdadeiro ou falso como este: ...

 

Há um exemplo de tarefa Builder XML anexado neste artigo - arquivo Build-Task1.xml

 

Exemplo

Como exemplo desta funcionalidade estaremos alternando programmaticamente entre os blocos de sinais Keltner Channel (KC) e Bollinger Bands (BB), todos os outros blocos serão desativados.

Teremos um projeto personalizado com duas tarefas - a primeira será uma tarefa de Análise Personalizada que aplicará nosso snippet de Análise Personalizada. A segunda é a tarefa Builder - estaremos modificando a configuração desta tarefa Builder em nosso trecho CA.

 

Portanto, quando você executar o projeto personalizado pela primeira vez, somente os blocos de sinais Bollinger Bands serão ativados. Ao executá-lo pela segunda vez, somente os blocos do Canal Keltner serão ativados, e assim por diante.

Todos os blocos de sinal das Bandas de Bollinger têm snippets nomeados com prefixo BB - BB*********, por exemplo key="BBBarClosesAboveDown", e todos os blocos de sinal do Canal Keltner têm snippets nomeados KC*********, por exemplo key="KCBarClosesAboveLower".
Usaremos este prefixo BB ou KC para reconhecer que se trata do canal Keltner Channel ou do bloco de sinais Bollinger Bands.

O exemplo abaixo é essencialmente o mesmo que no artigo https://strategyquant.com/doc/programming-for-sq/changing-task-config-programmatically/ - só que aqui fazemos coisas diferentes com o XML.

Usamos o padrão JDOM biblioteca para percorrer o XML e obter ou modificar seus atributos.

Passo 1 - Obtendo todos os elementos do bloco

Element elBlocks = XMLUtil.getChildElem(elNewConfig, "Blocos");
if(elBlocks == nulo) {
    lançar nova Exceção ("Não  elemento existe, é tarefa de Construtor?");
}
Element buildingBlocks = XMLUtil.getChildElem(elBlocks, "BuildingBlocks");
// alternativamente, você pode carregar a nova configuração de tarefa a partir do arquivo preparado
//Element elNewConfig = XMLUtil.fileToXmlElement(new File("c:/BuildTask2009_2019.xml"));

Lista blocos = buildingBlocks.getChildren("Bloco");

 

Passo 2 - Inicializar a variável ActiveBlock

usaremos esta variável para determinar se os blocos BB ou KC devem ser usados - lembre-se, estamos trocando entre os blocos BB e KC, portanto devemos determinar qual desses dois blocos deve ser ligado e desligado.

// usaremos esta variável para mudar de BB para KC. Os valores são:
// 0 - não conhecido, será definido pelo primeiro bloco encontrado
// 1 - Os blocos BB devem estar ativos
// 2 - Os blocos KC devem estar ativos
int activeBlock = 0;

 

Passo 3 - Passar por todos os blocos em um loop

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

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

 

Passo 4 - Se a chave não começa com BB ou KC, é um bloco diferente e deve ser desligada

if(!key.startsWith("BB") && !key.startsWith("KC")) {
    // não é o Bollinger Bands nem o bloco Keltner Channel, desligue-o
    elBlock.setAttribute("uso", "falso");
    continuar;
}

 

Passo 5 - Caso contrário, é bloco KC ou BB

Agora reconheça o valor adequado da variável ActiveBlock:

// é um bloco BB ou KC
String use = elBlock.getAttributeValue("uso");

if(activeBlock == 0) {
    // vamos determinar se os blocos BB ou KC devem estar ativos pelo primeiro bloco encontrado
    if(key.startsWith("BB")) {
        se (usar.igual("verdadeiro")) {
            // BB estava ativa antes, agora a KC estará ativa
            ActiveBlock = 2;
        }
    } else if(key.startsWith("KC")) {
        if(use.equals("true")) {
            // KC estava ativa antes, agora BB estará ativa
            ActiveBlock = 1;
        }
    }

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

    Log.info("----- Ligando "+(activeBlock == 1 ? "Bollinger Bands" : "Keltner Channel")+" blocos");
}

 

Passo 6 - o principal

ligar os blocos BB ou KC de acordo com o ActiveBlock definindo seu atributo de uso como verdadeiro ou falso:

// agora ligue ou desligue o bloco de acordo com o valor do Bloco ativo
if(key.startsWith("BB")) {
    elBlock.setAttribute("use", (activeBlock == 1 ? "true" : "false"));
} else if(key.startsWith("KC")) {
    elBlock.setAttribute("use", (activeBlock == 2 ? "true" : "false"));
}

 

Passo 7 - aplicar a configuração modificada à tarefa

Já acabamos de passar por todos os blocos de construção, agora basta aplicar a configuração modificada à tarefa:

// Aplicar a configuração modificada à tarefa
buildTask.setConfig(elNewConfig, true);

// isto notifica a IU para carregar che mudou de configuração e aplicá-la à IU.
// Sem isto ainda funcionaria, mas você não verá as mudanças na IU
JSONObject jsonData = novo JSONObject().put("projectConfig", sqProject.toJSON());
DataToSend dataToSend = novo DataToSend(WebSocketConst.UpdateProject, jsonData);
SQWebSocketManager.addToDataQueue(dataToSend, SQConst.CODE_TASKMANAGER);

 

E isso é tudo.

Agora, sempre que você iniciar o projeto personalizado, ele trocará os blocos de construção entre as Bandas Bollinger e os sinais do Canal Keltner.

 

 

Código completo do snippet da CAChangeBlocksConfig:

pacote SQ.CustomAnalysis;

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

importação java.util.ArrayList;
importação java.util.List;

classe pública CAChangeBlocksConfig estende o método CustomAnalysisMethod {

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

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

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

    @Override
    public ArrayList processDatabank(String project, String task, String databankName, ArrayList databankRG) lança Exceção {

        // obter projeto atual
        SQProject sqProject = ProjectEngine.get(projeto);

        // obter tarefa pelo nome
        ISQTask buildTask = sqProject.getTaskByName("Construir estratégias");
        if(buildTask == nulo) {
            lançar nova Exceção ("Não existe tal tarefa!");
        }
        // alternativamente, você pode usar sqProject.getTasks() para obter uma lista de todas as tarefas
        // e passe por eles para conseguir aquele que você quer


        // é assim que você obtém as configurações de tarefas XML da nova maneira (SQ 136 acima)
        // Devolve o JDOM XML Element com configuração de tarefa completa
        Element elConfig = buildTask.getConfig();
        // criar uma nova configuração através da clonagem - é importante fazer um clone,
        // caso contrário, sua nova configuração não será aplicada
        Element elNewConfig = elConfig.clone();

        // agora mudar qualquer coisa na nova configuração
        Element elBlocks = XMLUtil.getChildElem(elNewConfig, "Blocos");
        if(elBlocks == nulo) {
            lançar nova Exceção("Não  elemento existe, é tarefa de Construtor?");
        }
        Element buildingBlocks = XMLUtil.getChildElem(elBlocks, "BuildingBlocks");
        // alternativamente, você pode carregar a nova configuração de tarefa a partir do arquivo preparado
        //Element elNewConfig = XMLUtil.fileToXmlElement(new File("c:/BuildTask2009_2019.xml"));

        Lista blocos = buildingBlocks.getChildren("Bloco");

        // usaremos esta variável para mudar de BB para KC. Os valores são:
        // 0 - não conhecido, será definido pelo primeiro bloco encontrado
        // 1 - Os blocos BB devem estar ativos
        // 2 - Os blocos KC devem estar ativos
        int activeBlock = 0;

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

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

            if(!key.startsWith("BB") && !key.startsWith("KC")) {
                // não é o Bollinger Bands nem o bloco Keltner Channel, desligue-o
                elBlock.setAttribute("uso", "falso");
                continuar;
            }

            // é um bloco BB ou KC
            String use = elBlock.getAttributeValue("uso");

            if(activeBlock == 0) {
                // vamos determinar se os blocos BB ou KC devem estar ativos pelo primeiro bloco encontrado
                if(key.startsWith("BB")) {
                    se (usar.igual("verdadeiro")) {
                        // BB estava ativa antes, agora a KC estará ativa
                        ActiveBlock = 2;
                    }
                } else if(key.startsWith("KC")) {
                    if(use.equals("true")) {
                        // KC estava ativa antes, agora BB estará ativa
                        ActiveBlock = 1;
                    }
                }

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

                Log.info("----- Ligando "+(activeBlock == 1 ? "Bollinger Bands" : "Keltner Channel")+" blocos");
            }

            // agora ligue ou desligue o bloco de acordo com o valor do Bloco ativo
            if(key.startsWith("BB")) {
                elBlock.setAttribute("use", (activeBlock == 1 ? "true" : "false"));
            } else if(key.startsWith("KC")) {
                elBlock.setAttribute("use", (activeBlock == 2 ? "true" : "false"));
            }
        }


        // Aplicar a configuração modificada à tarefa
        buildTask.setConfig(elNewConfig, true);

        // isto notifica a IU para carregar che mudou de configuração e aplicá-la à IU.
        // Sem isto ainda funcionaria, mas você não verá as mudanças na IU
        JSONObject jsonData = novo JSONObject().put("projectConfig", sqProject.toJSON());
        DataToSend dataToSend = novo DataToSend(WebSocketConst.UpdateProject, jsonData);
        SQWebSocketManager.addToDataQueue(dataToSend, SQConst.CODE_TASKMANAGER);

        banco de dados de retornoRG;
    }
}

 

Este artigo foi útil? O artigo foi útil O artigo não foi útil

Assine
Notificação de
1 Comentário
Mais antigo
Novidades Mais Votados
Feedbacks em linha
Ver todos os comentários
Emmanuel
15. 1. 2023 7:24 pm

Obrigado Mark por este excelente exemplo
Será muito útil

Postos relacionados