Leggere le impostazioni della strategia, le variabili, le regole e i blocchi di costruzione in pochi semplici passi utilizzando Xml.
Contenuto della pagina
Grazie ad un esempio precedente : https://strategyquant.com/doc/programming-for-sq/viewing-and-changing-strategy-parameters-version-2/, possiamo leggere una strategia e le sue variabili.
Questo esempio di codice si spinge oltre, leggendo l'XML di una strategia, le sue variabili e le sue regole.
1/ Panoramica di una strategia
- Una strategia Xml può essere letta con il Funzione XMLUtil.elementToString().
È possibile eseguire un'analisi personalizzata XmlStrategiaPerFile o XmlStrategiaPerFileSym (per le strategie simmetriche) per trasformare qualsiasi strategia dalla banca dati all'unità in un percorso di uscita come "C:\Temp"
Poi si può aprire questo file XML in qualsiasi lettore xml (come ad esempio https://jsonformatter.org/xml-editor per esempio).
È possibile leggere anche un modello, se si carica il modello in Databank.
(Si veda l'allegato Progetto personalizzato StrategiaPerXmlFile e l'Xml allegato di una strategia Strategia 1.6.22(1)B)
- Le strategie A hanno regole e variabili :
Se si apre la finestra Estensione SQ.utils.Bouillant, troverete una struttura simile per aprire una strategia:
In "toBuildingBlocksName", possiamo vedere due regioni del codice, Variabili e regole anche
2/ Stiamo utilizzando Classe XMLUtil e l'elemento JDOM
https://strategyquant.com/sqxapi/com/strategyquant/lib/XMLUtil.html
3/ Come leggere le variabili della strategia
Una volta ottenuto l'XML da una strategia, dobbiamo ottenere i valori delle sue variabili. Esse possono essere Booleano, Intero, o Doppio.
Per ottenerli, sono disponibili tre funzioni :
-
getVariableValueToBoolean
-
getVariableValueToInt
-
getVariableValueToDouble
Da queste funzioni si possono ottenere i valori di qualsiasi variabile di una strategia.
4/ Ad esempio, possiamo ottenere un valore di Stop loss o un valore di Profit Target dalle impostazioni della strategia e inserire i risultati in una banca dati:
Con questa estensione, è possibile trovare un'analisi personalizzata "CA_StrategySettings" o "CA_StrategySettingsSym" (per strategie simmetriche)
Queste analisi personalizzate chiameranno SQ.utils.Bouillant e richiedere un valore di Stop Loss o un valore di Profit Target da un segnale :
@Override public boolean filterStrategy(String project, String task, String databankName, ResultsGroup rg) throws Exception { Bouillant BouilltParaObj1 = new Bouillant(); int IntTemp = BouilltParaObj1.getVariableValueToInt(rg, false, "LongProfitTarget"); rg.specialValues().set("CA_Long_ProfitTarget", IntTemp); IntTemp = BouilltParaObj1.getVariableValueToInt(rg, false, "ShortProfitTarget"); rg.specialValues().set("CA_Short_ProfitTarget", IntTemp); IntTemp = BouilltParaObj1.getVariableValueToInt(rg, false, "LongStopLoss"); rg.specialValues().set("CA_Long_StopLoss", IntTemp); IntTemp = BouilltParaObj1.getVariableValueToInt(rg, false, "ShortStopLoss"); rg.specialValues().set("CA_Short_StopLoss", IntTemp); IntTemp = BouilltParaObj1.getVariableValueToInt(rg, false, "LongTrailingStop"); rg.specialValues().set("CA_Long_TrailingStop", IntTemp); IntTemp = BouilltParaObj1.getVariableValueToInt(rg, false, "ShortTrailingStop"); rg.specialValues().set("CA_Short_TrailingStop", IntTemp); restituire true; }
(Come si può vedere nell'allegato Progetto personalizzato : StrategySettings)
Una volta eseguito "CA_StrategySettings" analisi personalizzata o "CA_StrategySettingsSym" analisi personalizzata , è possibile leggere un valore di stop loss o un valore di obiettivo di profitto da qualsiasi impostazione della strategia e aggiornare la banca dati con i seguenti snippet:
Ecco i valori di Profit Target e Stop Loss delle impostazioni della strategia.
5/ Come leggere la strategia XML passo dopo passo
(dalla nostra funzione toBuildingBlocksName in SQ.Utils.Bouillant)
A/ Il nostro esempio utilizza getStrategiaBase per ottenere la funzione Elemento radice di una strategia :
StrategyBase strategyBase = getStrategyBase(strategyRG, symmetricVariables); Element Strategie1 = strategyBase.getStrategyXml();
B/ Dal Strategia1 Elemento, sta diventando un bambino specifico Elemento
Element elParams = Strategie1.getChild("Strategy").getChild("Variables");
o
elParams = Strategie1.getChild("Strategy").getChild("Rules").getChild("Events"); // andare alla sezione Regole dell'Xml di Strategia
C/ Dal elParam Elemento, sta ottenendo il elementi per bambini a un Elenco degli elementi paramElementi
List paramElems = elParams.getChildren();
D/ Da Elenco degli elementi paramElementi, è possibile ottenere ciascuno Elemento e leggere il Valore del nodo utilizzando getNodeValue :
per (i = 0; i < paramElems.size(); i++) { Element elParam = paramElems.get(i); String name = XMLUtil.getNodeValue(elParam, "name"); String id = XMLUtil.getNodeValue(elParam, "id"); if (name.equals(TradingSignalName)) // Cerchiamo l'id del TradingSignalName, necessario per trovare la regola corrispondente { SignalID = id; } }
E/ Da Elenco degli elementi paramElementi, è possibile ottenere ogni AttributoValore di un Elemento :
String elParamKey = elParam.getAttributeValue("key");
F/ Da un elemento a una stringa
Come nel caso di una strategia, se si vuole leggere un elemento e osservarne la strutturaè possibile utilizzare la funzione XMLUtil.elementToString e inviarlo a un file.
String1 = XMLUtil.elementToString(elParam);
6/ Applicazione: come chiamare questa funzione, come utilizzarla.
In questo esempio, abbiamo gli snippet delle colonne di DataBank per applicare questa funzione:
Bouillant BouilltParaObj1 = new Bouillant(); StringTotal = BouilltParaObj1.toBuildingBlocksName(results,false, "LongEntrySignal",100);
Questa funzione chiede ai Building Blocks con un Gruppo di risultati e un TradingSignal Nome. (LongEntrySignal, ShortEntrySignal, LongExitSignal, ShortExitSignal,...)
È davvero pratico perché è possibile selezionare un segnale di entrata lunga, un segnale di entrata corta, un segnale di uscita lunga o corta o tutti insieme.
È anche possibile selezionare il nome del segnale dal modello.
Ecco il codice :
pacchetto SQ.Columns.Databanks; importare SQ.Utils.Bouillant; importare com.strategyquant.lib.L; import com.strategyquant.tradinglib.*; importare com.strategyquant.tradinglib.optimization.WalkForwardMatrixResult; importare com.strategyquant.lib.ValuesMap; importare org.slf4j.Logger; import org.slf4j.LoggerFactory; // Creato in Francia da Emmanuel Bouillant-Evrard per la comunità StrategyQuantX :) public class StrategyBuildingBlocks extends DatabankColumn { public static final Logger Log = LoggerFactory.getLogger(StrategyBuildingBlocks.class); public StrategyBuildingBlocks() { super(L.tsq("Strategy Building Blocks"), DatabankColumn.Text, ValueTypes.Maximize, 0, 0, 1); setWidth(1000); } //------------------------------------------------------------------------ @Override public double getNumericValue(ResultsGroup results, String resultKey, byte direction, byte plType, byte sampleType) throws Exception { return 0; } //------------------------------------------------------------------------ @Override public String getValue(ResultsGroup results, String resultKey, byte direction, byte plType, byte sampleType) throws Exception { try { StringTotal = ""; Bouillant BouilltParaObj1 = new Bouillant(); String1 = BouilltParaObj1.toBuildingBlocksName(results,false, "LongEntrySignal",100); // 100 per avere il nome dei blocchi di edifici BouilltParaObj1 = new Bouillant(); String String2 = BouilltParaObj1.toBuildingBlocksName(results,false, "ShortEntrySignal",100); if (String1 == null || String2 == null) { return "";} int maxLength = (String1.length() < 100)?String1.length():100; String1 = String1.substring(0, maxLength); maxLength = (String2.length() < 100)?String2.length():100; String2 = String2.substring(0, maxLength); if (!String1.equals("") && !String2.equals("")) { StringTotal += String1 + "," + String2; } else if (!String1.equals("")) { StringTotal += String1; } else if (!String2.equals("")) { StringTotal += String2; } return StringTotal; } catch(Exception e) { Log.error("Errore StrategyBuildingBlocks", e); return ""; // "Errore: " + e.getMessage(); } } }
7/ Gli elementi costitutivi Nome di ogni strategia nella banca dati
8/ Il codice della funzione toBuildingBlocksName
/** * Questa funzione legge il nome delle variabili, le regole e restituisce una stringa di nomi di blocchi di costruzione. * @param strategiaRG * @param variabili simmetriche * @param TradingSignal * @Ritorno */ public String toBuildingBlocksName(ResultsGroup strategyRG, boolean symmetricVariables, String TradingSignalName, int breakdownLevelMax) throws Exception { try { int i; String SignalID = ""; String strName = strategyRG.getName(); if(strName.startsWith("Portafoglio filtrato") || strName.startsWith("Portafoglio")) { return ""; } StrategyBase strategyBase = getStrategyBase(strategyRG, symmetricVariables); Element Strategie1 = strategyBase.getStrategyXml(); se (DebugMode){ OutputPath = "C:\\Tempi\"+strName+".txt"; FileWriter myWriter = new FileWriter(OutputPath , true); } if (Strategie1 != null) { //#region ********************************************************* Variables ************************************************************************************** Stringa test4 = "" ; Element elParams = Strategie1.getChild("Strategy").getChild("Variables"); if (elParams != null) { List paramElems = elParams.getChildren(); VariableValues = new HashMap(); VariableID = new HashMap(); VariableType = new HashMap(); per (i = 0; i < paramElems.size(); i++) { Elemento elParam = paramElems.get(i); if (elParam = null) { String name = XMLUtil.getNodeValue(elParam, "name"); String id = XMLUtil.getNodeValue(elParam, "id"); String value = XMLUtil.getNodeValue(elParam, "value"); String Type = XMLUtil.getNodeValue(elParam, "type"); VariableID.put(nome, id); VariableValues.put(nome, valore); VariableType.put(nome, Tipo); se (DebugMode){ test4 = XMLUtil.getNodeValue(elParam, "nome") + " " + XMLUtil.getNodeValue(elParam, "id"); myWriter.write("nome + id : "+ test4 + "\r\n"); myWriter.write("VariableID : "+ VariableID.get(name) + "\r\n"); test4 = XMLUtil.getNodeValue(elParam, "nome") + " " + XMLUtil.getNodeValue(elParam, "valore"); myWriter.write("nome + valore : "+ test4 + "\r\n"); myWriter.write("VariableValues : "+ VariableValues.get(name) + "\r\n"); test4 = XMLUtil.getNodeValue(elParam, "nome") + " " + XMLUtil.getNodeValue(elParam, "tipo"); myWriter.write("nome + tipo : "+ test4 + "\r\n"); myWriter.write("VariableType : " + VariableType.get(name) + "\r\n");} if (name.equals(TradingSignalName)) // Cerchiamo l'Id del TradingSignalName, necessario per trovare la regola corrispondente { SignalID = id; } } } se (DebugMode){ myWriter.close();} } //#endregion //#region ********************************************************* Rules ****************************************************************************************** elParams = Strategie1.getChild("Strategy").getChild("Rules").getChild("Events"); // andare alla sezione Regole dell'Xml della Strategia if (elParams != null) { List paramElems = elParams.getChildren(); for (i = 0; i < paramElems.size(); i++) { Element elParam2 = paramElems.get(i); if (elParam2 != null) { String elParamKey2 = elParam2.getAttributeValue("key"); if (elParamKey2.equals("OnBarUpdate")) // Cerca la regola OnBarUpdate { List paramElems3 = elParam2.getChildren(); for (int i2 = 0; i2 < paramElems3.size(); i2++) { Elemento elParam3 = paramElems3.get(i2); if (elParam3 != null) { String elParamKey3 = elParam3.getAttributeValue("name"); if (elParamKey3.equals("Segnali di trading")) // Cerca la regola dei segnali di trading { Element elParams4 = elParam3.getChild("signals"); List paramElems4 = elParams4.getChildren(); for (int i3 = 0; i3 < paramElems4.size(); i3++) { Elemento elParam4 = paramElems4.get(i3); if (elParam4 != null) { String elParamKey4 = elParam4.getAttributeValue("variabile"); if (elParamKey4.equals(SignalID)) // Cerca il TradingSignalName richiesto dal suo ID : SignalID { se (DebugMode){ myWriter = new FileWriter(OutputPath , true); String String1 = XMLUtil.elementToString(elParam4); myWriter.write(String1); myWriter.close();} Element elParams5 = elParam4.getChild("Item"); se (DebugMode){ myWriter = new FileWriter(OutputPath , true); String1 = XMLUtil.elementToString(elParams5); myWriter.write(String1); myWriter.close();} if (elParams5 != null) { String key = elParams5.getAttributeValue("key"); // il nome if (!key.equals("Boolean")) { Elemento elParam5Temp = elParams5; Elemento elParam6Temp = elParams5; strName = strategyRG.getName(); ArrayListElemsAll = new ArrayList(); UpdateNodesValues(strategyRG, symmetricVariables, elParams5, breakdownLevelMax, 0); AddToList(strategyRG, symmetricVariables, elParams5, breakdownLevelMax, 0); se (!StrategyName2.equals(strName) && OutPutBlockMode) { StrategyName2 = strName; strategyBase = getStrategyBase(strategyRG, symmetricVariables); Strategie1 = strategyBase.getStrategyXml(); OutputPath = "C:\\Temp\"+strName+"B.txt"; FileWriter myWriter = new FileWriter(OutputPath , false); String1 = XMLUtil.elementToString(Strategia1); myWriter.write(String1+"\r\n"); myWriter.close(); } StringBuilder sb = new StringBuilder(); // crea la stringa del nome del blocco di costruzione if (ArrayListElemsAll.size()>=1) { se (DebugMode){ myWriter = new FileWriter(OutputPath , true); myWriter.write("ArrayListElemsAll.size() : " + String.valueOf(ArrayListElemsAll.size()) + "\r\n"); String1 = XMLUtil.elementToString(elParam5Temp); myWriter.write(String1); myWriter.close();} for (int i5 = 0; i5 < ArrayListElemsAll.size(); i5++) { elParam6Temp = ArrayListElemsAll.get(i5); if (elParam6Temp != null) { String elParamKey8Temp = elParam6Temp.getAttributeValue("name"); // elParam6Temp.getAttributeValue("key"); sb.append(elParamKey8Temp); sb.append(ParamDelimiter); } } } return sb.toString(); }} }} } }} } }} } } //#endregion } return ""; } catch (Exception e) { if (DebugMode2){ String strName = strategyRG.getName(); OutputPath = "C:\\Tempi\i}aBuildingBlocksName "+strName+".txt"; FileWriter myWriter = new FileWriter(OutputPath , true); myWriter.write("Errore : "+ strName +" "+ "\r\n"); myWriter.write("Errore : "+ e + "\r\n"); StrategyBase strategyBase = getStrategyBase(strategyRG, symmetricVariables); Element Strategie1 = strategyBase.getStrategyXml(); String String1 = XMLUtil.elementToString(Strategie1); myWriter.write(String1 + "\r\n"); myWriter.close();} Log.error("Errore toBuildingBlocksName", e); restituire ""; } }
9/ Per leggere ogni blocco, questo esempio utilizza due funzioni ricorsive: UpdateNodesValues e AddToList.
Queste funzioni cercano ogni blocco di costruzione, qualunque sia la struttura XML della strategia.
Ecco il Codice :
/** * Recursive function that read the Building Blocks Name from the Xml to update Nodes Values * @param strategyRG * @param symmetricVariables * @param Element * @param breakdownLevelMax * @param breakdownLevel * @return */ public void UpdateNodesValues(ResultsGroup strategyRG, boolean symmetricVariables, Element element, int breakdownLevelMax, int breakdownLevel) throws Exception { int i; if (element != null) { breakdownLevel = breakdownLevel + 1 ; List<Element> element1 = element.getChildren(); if (element1.size() >= 1) { for (i = 0; i < element1.size(); i++) { Element element11 = element1.get(i); if (element11 != null) { UpdateNodesValues(strategyRG, symmetricVariables, element11, breakdownLevelMax, breakdownLevel); } } } } if (element != null) { List<Element> listParams = element.getChildren("Param"); if (listParams.size() >= 1) { boolean VariableFounded = false; for (i = 0; i < listParams.size(); i++) { Element courant = listParams.get(i); if (courant != null) { String elParamKey5 = courant.getAttributeValue("key"); // the name String elParamVariable3 = courant.getAttributeValue("variable"); // the variable if (elParamKey5.startsWith("#") && elParamVariable3=="true") { String Temp1 = VariableValues.get(courant.getText()); String Temp2 = courant.getText(); if (Temp1 != null) { courant.setText(Temp1); } VariableFounded = true; } } } } } } /** * Recursive function that read the Building Blocks Name from the Xml to the ArrayList : ArrayListElemsAll * @param strategyRG * @param symmetricVariables * @param Element * @param breakdownLevelMax * @param breakdownLevel * @return */ public void AddToList(ResultsGroup strategyRG, boolean symmetricVariables, Element element, int breakdownLevelMax, int breakdownLevel) throws Exception { int i; boolean Condition1 = false; if (element != null) { breakdownLevel = breakdownLevel + 1 ; String elParamKey = element.getAttributeValue("key"); String categoryType = element.getAttributeValue("categoryType"); if (categoryType == null){categoryType = "";} if (breakdownLevelMax < 100) { Condition1 = (elParamKey.equals("IsRising") || elParamKey.equals("IsFalling") || elParamKey.equals("IsLowerCount") || elParamKey.equals("IsGreaterCount") || elParamKey.equals("IsLower") || elParamKey.equals("IsLowerOrEqual") || elParamKey.equals("IsGreater") || elParamKey.equals("IsGreaterOrEqual") || elParamKey.equals("CrossesAbove") || elParamKey.equals("CrossesBelow") || elParamKey.startsWith("CBlock")); } if (!Condition1) { List<Element> element1 = element.getChildren(); if (element1.size() >= 1) { for (i = 0; i < element1.size(); i++) { Element element11 = element1.get(i); if (element11 != null) { AddToList(strategyRG, symmetricVariables, element11, breakdownLevelMax, breakdownLevel); } } } } List<Element> listParams = element.getChildren("Param"); if (listParams.size() >= 1 || Condition1) { Element elementCopy = (Element)element.clone(); elParamKey = elementCopy.getAttributeValue("key"); listParams = elementCopy.getChildren("Param"); List<Element> listParamsBlock = element.getChildren("Block"); if (listParamsBlock.size() == 0 || Condition1) { if ((listParams.size() == 1 && !elParamKey.equals("Number")) || !elParamKey.equals("Number")) { if (breakdownLevel <= breakdownLevelMax) { ArrayListElemsAll.add(elementCopy); } } } if (breakdownLevel <= breakdownLevelMax && OutPutBlockMode) { String strName = strategyRG.getName(); OutputPath = "C:\\Temp\\"+strName+".txt"; FileWriter myWriter = new FileWriter(OutputPath , true); String String1 = XMLUtil.elementToString(elementCopy); myWriter.write(String1+"\r\n"); myWriter.write("________________________________________________________________________________________________________________________________________________________________________________________________________________"+"\r\n"); myWriter.close(); } } } }
10/ Conclusione
In sintesi, è semplice, di solito si inizia leggendo la struttura del file XML dal file XMLUtil.elementToString si utilizzano le funzioni di cui sopra (A,B,C,D,E).
Se necessario, possiamo trovare altre funzioni a :
https://strategyquant.com/sqxapi/com/strategyquant/lib/XMLUtil.html
Fonte dell'informazione :
https://strategyquant.com/doc/programming-for-sq/viewing-and-changing-strategy-parameters-version-2/
https://www.w3schools.com/xml/default.asp
https://strategyquant.com/sqxapi/com/strategyquant/lib/XMLUtil.html
https://www.tutorialspoint.com/java_xml/java_jdom_parse_document.htm
Un utile lettore Xml :
https://jsonformatter.org/xml-editor
Mi chiamo Emmanuel Bouillant-Evrard, ingegnere specializzato in finanza. Ho lavorato per 24 anni nella ricerca e nello sviluppo nel settore finanziario negli Stati Uniti, in Canada e in Francia.
eccellente
Grazie
Grazie Emmanuel !
Ottimo lavoro svolto