Analyzujte XML strategie a extrahujte nastavení, proměnné, pravidla a parametry včetně stop lossu a profit targetu pro vlastní analýzu a automatizaci.
Díky dokumentaci pro zobrazení a změnu parametrů strategie můžeme číst proměnné strategie.
Tento příklad kódu čte XML strategie, proměnné a pravidla.
1. Přehled strategie
- XML strategie lze načíst pomocí XMLUtil.elementToString().
Spusťte Custom Analysis XmlStrategyToFile nebo XmlStrategyToFileSym (symetrické strategie) pro export z Databanky na disk. Soubory XML otevřete v libovolném prohlížeči XML, například https://jsonformatter.org/xml-editor.

- Strategie mají pravidla a proměnné.

V rozšíření SQ.utils.Bouillant zobrazuje funkce toBuildingBlocksName dvě oblasti: Variables a Rules.

2. Třída XMLUtil a prvek JDOM
Dokumentace XMLUtil API
3. Čtení proměnných strategie
Získání hodnot proměnných:
- getVariableValueToBoolean
- getVariableValueToInt
- getVariableValueToDouble
4. Příklad: Extrakce Stop Lossu a Profit Targetu
Custom Analysis CA_StrategySettings nebo CA_StrategySettingsSym:

@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);
return true;
}


5. Čtení XML strategie krok za krokem
A. Získání kořenového prvku (root Element):
StrategyBase strategyBase = getStrategyBase(strategyRG, symmetricVariables);
Element Strategie1 = strategyBase.getStrategyXml();
B. Získání konkrétního potomka (child Element):
Element elParams = Strategie1.getChild("Strategy").getChild("Variables");
elParams = Strategie1.getChild("Strategy").getChild("Rules").getChild("Events");
C. Získání podřízených prvků do Listu:
List<Element> paramElems = elParams.getChildren();
D. Načtení NodeValue:
for (i = 0; i < paramElems.size(); i++) {
Element elParam = paramElems.get(i);
String name = XMLUtil.getNodeValue(elParam,"name");
String id = XMLUtil.getNodeValue(elParam,"id");
}
E. Získání AttributeValue:
String elParamKey = elParam.getAttributeValue("key");
F. Převod Elementu na String:
String String1 = XMLUtil.elementToString(elParam);
6. Aplikace: Volání funkce

Úryvek kódu pro sloupec Databanky:
Bouillant BouilltParaObj1 = new Bouillant();
String StringTotal = BouilltParaObj1.toBuildingBlocksName(results,false, "LongEntrySignal",100);
Vyberte vstupní/výstupní signály (LongEntrySignal, ShortEntrySignal, LongExitSignal, ShortExitSignal atd.).
package SQ.Columns.Databanks;
import SQ.Utils.Bouillant;
import com.strategyquant.lib.L;
import com.strategyquant.tradinglib.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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
{
String StringTotal = "";
Bouillant BouilltParaObj1 = new Bouillant();
String String1 = BouilltParaObj1.toBuildingBlocksName(results,false, "LongEntrySignal",100);
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("Error StrategyBuildingBlocks", e);
return "";
}
}
}
7. Názvy stavebních bloků (Building Blocks) v Databance

8. Funkce toBuildingBlocksName
Přečte proměnné i pravidla a vrátí názvy stavebních bloků:
public String toBuildingBlocksName(ResultsGroup strategyRG, boolean symmetricVariables, String TradingSignalName, int breakdownLevelMax) throws Exception
{
try
{
String SignalID = "";
String strName = strategyRG.getName();
if(strName.startsWith("Filtered portfolio") || strName.startsWith("Portfolio")) { return ""; }
StrategyBase strategyBase = getStrategyBase(strategyRG, symmetricVariables);
Element Strategie1 = strategyBase.getStrategyXml();
if (Strategie1 != null)
{
Element elParams = Strategie1.getChild("Strategy").getChild("Variables");
if (elParams != null)
{
List<Element> paramElems = elParams.getChildren();
VariableValues = new HashMap<String, String>();
VariableID = new HashMap<String, String>();
VariableType = new HashMap<String, String>();
for (int i = 0; i < paramElems.size(); i++)
{
Element 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(name, id);
VariableValues.put(name, value);
VariableType.put(name, Type);
if (name.equals(TradingSignalName)) { SignalID = id; }
}
}
}
elParams = Strategie1.getChild("Strategy").getChild("Rules").getChild("Events");
if (elParams != null)
{
List<Element> paramElems = elParams.getChildren();
for (int i = 0; i < paramElems.size(); i++)
{
Element elParam2 = paramElems.get(i);
if (elParam2 != null) {
String elParamKey2 = elParam2.getAttributeValue("key");
if (elParamKey2.equals("OnBarUpdate")) {
List<Element> paramElems3 = elParam2.getChildren();
for (int i2 = 0; i2 < paramElems3.size(); i2++) {
Element elParam3 = paramElems3.get(i2);
if (elParam3 != null) {
String elParamKey3 = elParam3.getAttributeValue("name");
if (elParamKey3.equals("Trading signals")) {
Element elParams4 = elParam3.getChild("signals");
List<Element> paramElems4 = elParams4.getChildren();
for (int i3 = 0; i3 < paramElems4.size(); i3++) {
Element elParam4 = paramElems4.get(i3);
if (elParam4 != null) {
String elParamKey4 = elParam4.getAttributeValue("variable");
if (elParamKey4.equals(SignalID)) {
Element elParams5 = elParam4.getChild("Item");
if (elParams5 != null) {
String key = elParams5.getAttributeValue("key");
if (!key.equals("Boolean")) {
ArrayListElemsAll = new ArrayList<Element>();
UpdateNodesValues(strategyRG, symmetricVariables, elParams5, breakdownLevelMax, 0);
AddToList(strategyRG, symmetricVariables, elParams5, breakdownLevelMax, 0);
StringBuilder sb = new StringBuilder();
if (ArrayListElemsAll.size()>=1) {
for (int i5 = 0; i5 < ArrayListElemsAll.size(); i5++) {
Element elParam6Temp = ArrayListElemsAll.get(i5);
if (elParam6Temp != null) {
String elParamKey8Temp = elParam6Temp.getAttributeValue("name");
sb.append(elParamKey8Temp);
sb.append(ParamDelimiter);
}
}
}
return sb.toString();
}
}
}
}
}
}
}
}
}
}
}
}
}
return "";
} catch (Exception e) {
Log.error("Error toBuildingBlocksName", e);
return "";
}
}
9. Rekurzivní funkce: UpdateNodesValues a AddToList
public void UpdateNodesValues(ResultsGroup strategyRG, boolean symmetricVariables, Element element, int breakdownLevelMax, int breakdownLevel) throws Exception
{
if (element != null) {
breakdownLevel++;
List<Element> element1 = element.getChildren();
for (int 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");
for (int i = 0; i < listParams.size(); i++) {
Element courant = listParams.get(i);
if (courant != null) {
String elParamKey5 = courant.getAttributeValue("key");
String elParamVariable3 = courant.getAttributeValue("variable");
if (elParamKey5.startsWith("#") && elParamVariable3=="true") {
String Temp1 = VariableValues.get(courant.getText());
if (Temp1 != null) { courant.setText(Temp1); }
}
}
}
}
}
public void AddToList(ResultsGroup strategyRG, boolean symmetricVariables, Element element, int breakdownLevelMax, int breakdownLevel) throws Exception
{
boolean Condition1 = false;
if (element != null) {
breakdownLevel++;
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();
for (int 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); }
}
}
}
}
}
10. Závěr
Začněte načtením struktury XML pomocí XMLUtil.elementToString(), poté použijte funkce A–F uvedené výše. Více naleznete v Dokumentaci k API XMLUtil.
Odkazy: Viewing and Changing Strategy Parameters, W3Schools XML, Java JDOM Parse Document
Autor: Emmanuel Bouillant-Evrard, inženýr se specializací na finance s 24 lety zkušeností v oblasti výzkumu a vývoje v USA, Kanadě a Francii.