Documentação
Aplicações
Última atualização em 11. 1. 2023 por Mark Fric
Seleção programática de blocos de construção
Conteúdo da página
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:
- encontrar seu elemento
- 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
Obrigado Mark por este excelente exemplo
Será muito útil