Documentazione
Applicazioni
Ultimo aggiornamento il 11. 1. 2023 da Mark Fric
Selezione programmatica dei blocchi di costruzione
Contenuto della pagina
Si tratta di un'estensione di questo articolo: https://strategyquant.com/doc/programming-for-sq/changing-task-config-programmatically/
che ha dimostrato come sia possibile modificare la configurazione dei task in modo programmatico.
L'idea generale dell'esempio iniziale è che si può cambiare la configurazione del task manipolando la sua configurazione XML e riapplicandola al task.
In questo esempio dimostreremo come sia possibile attivare/disattivare i blocchi di costruzione in questo modo.
Come vengono memorizzati i blocchi di costruzione nell'XML dell'attività
Tutti i blocchi di costruzione sono memorizzati come figli e sottofigli nell'elemento ->.
Ogni blocco di costruzione è configurato in un proprio elemento , identificato in modo univoco dal suo elemento chiave - che è il nome dello snippet.
Esistono alcuni standard nei valori chiave:
- se è blocco del segnale o confronto, la chiave contiene solo il nome dello snippet, per esempio chiave="ADXChangesDown" o chiave="IsGreater"
- se è indicatore (non segnale), la sua chiave è preceduta dalla stringa "Indicatore.", ad esempio key="Indicatori.ADX"
- se è prezzo, la sua chiave è preceduta dalla stringa "Prezzi", ad esempio key="Prices.High"
- se è livello di arresto/limite (per gli ordini Stop o Limit), la sua chiave è preceduta dalla stringa "Stop/Limit Price Levels.", ad esempio key="Livelli di prezzo stop/limite.TEMA"
- se è intervallo di arresto/limite (per gli ordini Stop o Limit), la sua chiave è preceduta dalla stringa "Stop/Limit Price Ranges.", ad esempio key="Intervalli di prezzo stop/limite.BBWidthRatio"
Un altro importante attributo dell'elemento è utilizzo. Se si vuole che il blocco sia usato durante la compilazione, occorre impostarlo su "true", altrimenti su "false".
Quindi, se si desidera attivare o disattivare un blocco particolare, è sufficiente farlo:
- trovare il suo elemento <Block
- impostare l'attributo use su true o false in questo modo: ...
In questo articolo è allegato un esempio di XML dell'attività del costruttore: il file Build-Task1.xml.
Esempio
Come esempio di questa funzionalità, passeremo programmaticamente tra i blocchi di segnali Keltner Channel (KC) e Bollinger Bands (BB), mentre tutti gli altri blocchi saranno disabilitati.
Avremo un progetto personalizzato con due task: il primo sarà il task Analisi personalizzata che applicherà il nostro frammento di analisi personalizzata. Il secondo è il task Builder, di cui modificheremo la configurazione nel nostro snippet CA.
Pertanto, quando si esegue il progetto personalizzato per la prima volta, vengono abilitati solo i blocchi dei segnali delle Bande di Bollinger. Quando si esegue la seconda volta, vengono abilitati solo i blocchi del Canale di Keltner e così via.
Tutti i blocchi di segnali delle Bande di Bollinger hanno snippet denominati con il prefisso BB - BB*********, ad esempio key="BBBarClosesAboveDown", e tutti i blocchi di segnali del Canale Keltner hanno snippet denominati KC*********, ad esempio key="KCBarClosesAboveLower".
Utilizzeremo il prefisso BB o KC per riconoscere il blocco di segnali Keltner Channel o Bollinger Bands.
L'esempio riportato di seguito è essenzialmente lo stesso dell'articolo https://strategyquant.com/doc/programming-for-sq/changing-task-config-programmatically/ - solo che qui facciamo cose diverse con l'XML.
Utilizziamo lo standard JDOM per esaminare l'XML e ottenere o modificare i suoi attributi.
Passo 1 - Ottenere tutti gli elementi del blocco
Elemento elBlocks = XMLUtil.getChildElem(elNewConfig, "Blocks");
if(elBlocks == null) {
throw new Exception("Non esiste alcun elemento , è un compito del costruttore?");
}
Element buildingBlocks = XMLUtil.getChildElem(elBlocks, "BuildingBlocks");
// In alternativa, si può caricare la configurazione del nuovo task da un file preparato
//Element elNewConfig = XMLUtil.fileToXmlElement(new File("c:/BuildTask2009_2019.xml"));
List blocks = buildingBlocks.getChildren("Block");
Passo 2 - Inizializzare la variabile activeBlock
useremo questa variabile per determinare se devono essere usati i blocchi BB o KC - ricordiamo che stiamo passando da un blocco BB a uno KC, quindi dobbiamo determinare quale dei due deve essere attivato e disattivato.
// useremo questa variabile per passare da BB a KC. I valori sono: // 0 - non conosciuto, sarà impostato dal primo blocco trovato // 1 - i blocchi BB devono essere attivi // 2 - I blocchi KC devono essere attivi int activeBlock = 0;
Fase 3 - Passare attraverso tutti i blocchi in un ciclo
for(int i=0; i<blocks.size(); i++) {
Elemento elBlock = blocks.get(i);
String key = elBlock.getAttributeValue("key");
Fase 4 - Se la chiave non inizia con BB o KC, si tratta di un blocco diverso e deve essere disattivato.
if(!key.startsWith("BB") && !key.startsWith("KC")) {
// non è un blocco Bande di Bollinger o Canale di Keltner, disattivarlo
elBlock.setAttribute("use", "false");
continua;
}
Fase 5 - Altrimenti è un blocco KC o BB
Ora riconosciamo il valore corretto della variabile activeBlock:
// è un blocco BB o KC
String use = elBlock.getAttributeValue("use");
if(activeBlock == 0) {
// determineremo se i blocchi BB o KC devono essere attivi in base al primo blocco trovato
if(key.startsWith("BB")) {
if (use.equals("true")) {
// Prima era attivo BB, ora sarà attivo KC
activeBlock = 2;
}
} else if(key.startsWith("KC")) {
if(use.equals("true")) {
// Prima era attivo KC, ora sarà attivo BB
activeBlock = 1;
}
}
if(activeBlock == 0) {
activeBlock = 1;
}
Log.info("----- Girando su "+(activeBlock == 1 ? "Bollinger Bands" : "Keltner Channel")+" blocchi.");
}
Fase 6 - la cosa principale
Attivare i blocchi BB o KC in base alla blocco attivo impostando l'attributo use su true o false:
// ora attivare o disattivare il blocco in base al valore di activeBlock
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 - applicare la configurazione modificata all'attività
Abbiamo finito di esaminare tutti i blocchi di costruzione, ora basta applicare la configurazione modificata all'attività:
// Applicare la configurazione modificata al task
buildTask.setConfig(elNewConfig, true);
// questo notifica l'interfaccia utente per caricare la configurazione modificata e applicarla all'interfaccia utente.
// Senza questa operazione, funzionerebbe comunque, ma non si vedrebbero le modifiche nell'interfaccia utente.
JSONObject jsonData = new JSONObject().put("projectConfig", sqProject.toJSON());
DataToSend dataToSend = new DataToSend(WebSocketConst.UpdateProject, jsonData);
SQWebSocketManager.addToDataQueue(dataToSend, SQConst.CODE_TASKMANAGER);
E questo è tutto.
Ora, ogni volta che si avvia il progetto personalizzato, i blocchi di costruzione vengono commutati tra le Bande di Bollinger e i segnali del Canale di Keltner.
Codice completo dello snippet CAChangeBlocksConfig:
pacchetto SQ.CustomAnalysis;
importare com.strategyquant.lib.XMLUtil;
importare com.strategyquant.lib.constants.SQConst;
importare com.strategyquant.tradinglib.CustomAnalysisMethod;
importare com.strategyquant.tradinglib.ResultsGroup;
importare com.strategyquant.tradinglib.project.ProjectEngine;
importare com.strategyquant.tradinglib.project.SQProject;
importare com.strategyquant.tradinglib.project.websocket.DataToSend;
importare com.strategyquant.tradinglib.project.websocket.SQWebSocketManager;
importare com.strategyquant.tradinglib.project.websocket.WebSocketConst;
importare com.strategyquant.tradinglib.taskImpl.ISQTask;
importare org.jdom2.Element;
importare org.json.JSONObject;
importare java.util.ArrayList;
importare 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 {
// ottenere il progetto corrente
SQProject sqProject = ProjectEngine.get(project);
// ottenere l'attività per nome
ISQTask buildTask = sqProject.getTaskByName("Build strategies");
if(buildTask == null) {
lancia una nuova eccezione("Non esiste un task di questo tipo!");
}
// In alternativa, è possibile utilizzare sqProject.getTasks() per ottenere un elenco di tutti i task
// e scorrerli per ottenere quello che si desidera
// questo è il modo in cui si ottiene l'XML delle impostazioni delle attività nel nuovo modo (SQ 136 up)
// Restituisce l'elemento XML JDOM con la configurazione completa dell'attività
Element elConfig = buildTask.getConfig();
// creare una nuova configurazione clonandola - è importante fare un clone,
// altrimenti la nuova configurazione non verrà applicata
Element elNewConfig = elConfig.clone();
// ora modificare qualsiasi cosa nella nuova configurazione
Element elBlocks = XMLUtil.getChildElem(elNewConfig, "Blocks");
if(elBlocks == null) {
throw new Exception("Non esiste alcun elemento , è un compito del costruttore?");
}
Element buildingBlocks = XMLUtil.getChildElem(elBlocks, "BuildingBlocks");
// In alternativa, si può caricare la configurazione del nuovo task da un file preparato
//Element elNewConfig = XMLUtil.fileToXmlElement(new File("c:/BuildTask2009_2019.xml"));
List blocks = buildingBlocks.getChildren("Block");
// Useremo questa variabile per passare da BB a KC. I valori sono:
// 0 - non conosciuto, sarà impostato dal primo blocco trovato
// 1 - i blocchi BB devono essere attivi
// 2 - I blocchi KC devono essere attivi
int activeBlock = 0;
for(int i=0; i<blocks.size(); i++) {
Elemento elBlock = blocks.get(i);
String key = elBlock.getAttributeValue("key");
if(!key.startsWith("BB") && !key.startsWith("KC")) {
// non è un blocco Bande di Bollinger o Canale di Keltner, disattivarlo
elBlock.setAttribute("use", "false");
continua;
}
// è un blocco BB o KC
String use = elBlock.getAttributeValue("use");
if(activeBlock == 0) {
// determineremo se i blocchi BB o KC devono essere attivi in base al primo blocco trovato
if(key.startsWith("BB")) {
if (use.equals("true")) {
// Prima era attivo BB, ora sarà attivo KC
activeBlock = 2;
}
} else if(key.startsWith("KC")) {
if(use.equals("true")) {
// Prima era attivo KC, ora sarà attivo BB
activeBlock = 1;
}
}
if(activeBlock == 0) {
activeBlock = 1;
}
Log.info("----- Girando su "+(activeBlock == 1 ? "Bollinger Bands" : "Keltner Channel")+" blocchi.");
}
// ora attiva o disattiva il blocco in base al valore di activeBlock
if(key.startsWith("BB")) {
elBlock.setAttribute("use", (activeBlock == 1 ? "true" : "false"));
} else if(key.startsWith("KC")) {
elBlock.setAttribute("use", (activeBlock == 2 ? "true" : "false"));
}
}
// Applicare la configurazione modificata al task
buildTask.setConfig(elNewConfig, true);
// questo notifica l'interfaccia utente per caricare la configurazione modificata e applicarla all'interfaccia utente.
// Senza questa operazione funzionerebbe comunque, ma non si vedrebbero le modifiche nell'interfaccia utente.
JSONObject jsonData = new JSONObject().put("projectConfig", sqProject.toJSON());
DataToSend dataToSend = new DataToSend(WebSocketConst.UpdateProject, jsonData);
SQWebSocketManager.addToDataQueue(dataToSend, SQConst.CODE_TASKMANAGER);
restituire databankRG;
}
}
Questo articolo è stato utile? L'articolo è stato utile L'articolo non è stato utile

Grazie Mark per questo eccellente esempio
Sarà molto utile