Dokumentation
Anwendungen
Zuletzt aktualisiert am 21. 7. 2022 von Mark Fric
Zusammenführung mehrerer Ergebnisse zu einem Portfolio
Inhalt der Seite
In diesem Artikel zeigen wir, wie StrategyQuant X mit Backtest-Ergebnissen umgeht und wie wir sie in ein Portfolio einbinden können.
Dies ist bereits in SQX möglich, indem Sie mehrere Strategien auswählen und die Option Portfolio -> Strategien zusammenführenaber wir werden zeigen, wie es auf dem Hintergrund gemacht wird.
Dies ist als erster Teil einer mehrteiligen Serie gedacht. Wir möchten diese Funktionalität nutzen, um zu untersuchen, ob der Handel durch die Auswahl bestimmter Teilstrategien verbessert werden kann - dies wird in den nächsten Artikeln untersucht.
Beachten Sie, dass wir mit der Zusammenführung zum Portfolio die Zusammenführung der endgültigen Backtest-Ergebnisse zu einem Portfolio-Ergebnis meinen und nicht die Zusammenführung einzelner Handelsstrategien.
Diese Funktion ist wieder in Form von benutzerdefinierten Analyse-Snippet gemacht, und die vollständige Snippet ist zu diesem Artikel beigefügt.
Arbeiten mit Backtest-Ergebnissen - ResultsGroup-Objekt
Nur zur Erinnerung: In SQX werden alle Backtest-Ergebnisse in einem Result-Objekt gespeichert und in einem ResultsGroup-Objekt gruppiert.
RegultGroup ist das, was Sie in der Datenbank sehen - es kann ein oder mehrere Ergebnisse enthalten - Backtests der Strategie auf dem Hauptmarkt, zusätzlichen Märkten, etc.
Es gibt einen Artikel mit Einführung: Arbeiten mit ResultsGroup
Wenn wir mehrere Strategieergebnisse in einem Portfolio zusammenführen wollen, müssen wir
- ein neues ResultsGroup-Objekt erstellen, das das Portfolio enthält
- Durchlaufen des ResultsGroup-Objekts jeder Strategie in der Databank
- Finden Sie das Hauptergebnis - das Ergebnis des Backtests mit den Hauptdaten - das ist das Ergebnis, das wir zusammenführen werden.
- ein neues Ergebnisobjekt für diese Strategie zu erstellen und es dem Portfolio hinzuzufügen
- Klonen und Kopieren von Aufträgen aus der ursprünglichen ResultsGroup in das Portfolio
- Kopieren von Symbolen aus der ursprünglichen ResultsGroup in das Portfolio - dies ist für die Berechnung von PL usw. erforderlich.
- am Ende ein neues Portfolio-Ergebnis erstellen und alle Statistiken berechnen
Vollständiger Quellcode des Snippets
Der Code ist ausführlich kommentiert, Sie können seine Logik nachvollziehen.
Es werden zwei neue Portfolio-Ergebnisse erstellt - eines, das wir manuell erstellt haben, und ein weiteres, das mit der SQX-Methode zum Vergleich erstellt wurde.
Paket SQ.CustomAnalysis; import com.strategyquant.lib.SQUtils; import com.strategyquant.lib.SettingsMap; import com.strategyquant.lib.utils.IUniqueNameChecker; import com.strategyquant.tradinglib.*; import com.strategyquant.tradinglib.project.ProjectEngine; import com.strategyquant.tradinglib.results.SpecialValues; import com.strategyquant.tradinglib.results.stats.comparator.OrderComparatorByOpenTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; public class CAMergeStrategiesToPortfolio extends CustomAnalysisMethod { public static final Logger Log = LoggerFactory.getLogger("CAMergeStrategiesToPortfolio"); //------------------------------------------------------------------------ //------------------------------------------------------------------------ //------------------------------------------------------------------------ public CAMergeStrategiesToPortfolio() { super("Strategien zu Portfolio zusammenführen", TYPE_PROCESS_DATABANK); } //------------------------------------------------------------------------ @Override public boolean filterStrategy(String project, String task, String databankName, ResultsGroup rg) throws Exception { return false; } //------------------------------------------------------------------------ @Override public ArrayList processDatabank(String project, String task, String databankName, ArrayList databankRG) throws Exception { if(databankRG.size() <= 1) { // wenn es keine oder nur eine Strategie gibt, gibt es nichts zu fusionieren return databankRG; } // Abrufen der Zieldatenbank zum Speichern des Endergebnisses Databank targetDatabank = ProjectEngine.get(project).getDatabanks().get("Portfolios"); if(targetDatabank == null) { throw new Exception("Bitte erstellen Sie eine neue Datenbank mit dem Namen 'Portfolios' !"); } // ------------------------------ // Portfolio manuell erstellen // Alle Strategien in der Datenbank zu einem Portfolio zusammenführen ErgebnisGruppe caPortfolio = mergeStrategiesToPortfolio(databankRG); // Erstellen des endgültigen Portfolioergebnisses, um alle Teilergebnisse zu summieren createPortfolioResult(caPortfolio); // neues Portfolio zu unserer Zieldatenbank hinzufügen targetDatabank.add(caPortfolio, false); // ------------------------------ // Erstellen eines Portfolios auf standardmäßige Weise durch Aufruf der SQ-Methode - zur Kontrolle ResultsGroup standardPortfolio = ResultsGroup.merge(databankRG, new String[] { ResultsGroup.AdditionalMarket }, null); standardPortfolio.createPortfolioResult(PortfolioInitialBalanceTypes.SINGLE, null); targetDatabank.add(standardPortfolio, false); return databankRG; } //------------------------------------------------------------------------ private ResultsGroup mergeStrategiesToPortfolio(ArrayList databankRG) throws Exception { ResultsGroup caPortfolio = new ResultsGroup("PortfolioMadeByCA"); // einzelne Strategien zum Portfolio hinzufügen for(ResultsGroup rg : databankRG) { addResult(caPortfolio, rg); } addSymbolsMap(caPortfolio, databankRG); caPortfolio zurückgeben; } //------------------------------------------------------------------------ private void addSymbolsMap(ResultsGroup rgCSPortfolio, ArrayList databankRG) { for(ResultsGroup rg : databankRG) { // Hinzufügen aller Symbole aus den zusammengeführten RGs zur Portfolio-Symbolkarte rgCSPortfolio.symbols().add(rg.symbols()); } } //------------------------------------------------------------------------ private void addResult(ResultsGroup caPortfolio, ResultsGroup rg) throws Exception { // zuerst ein neues Ergebnis für RG in unserem neuen Portfolio erstellen // newResultKey wird als Ergebnisschlüssel zurückgegeben und in unserem Portfolio verwendet String newResultKey = mergeResult(caPortfolio, rg); // nächstes Klonen und Kopieren von Aufträgen für dieses Ergebnis von RG in das Portfolio copyOrdersToPortfolio(caPortfolio, rg, newResultKey); // Hinzufügen aller Symboldaten aus dem zusammengeführten RG zur Portfolio-Symbole-Map - dies ist für die Berechnung von PL usw. erforderlich caPortfolio.symbols().add(rg.symbols()); } //------------------------------------------------------------------------ private String mergeResult(ErgebnisGruppe caPortfolio, ErgebnisGruppe rg) throws Exception { // Abrufen des Hauptergebnisses der aktuellen Strategie - dies ist das Ergebnis, das wir zusammenführen werden Ergebnis rgMainResult = rg.mainResult(); String mainResultKey = rgMainResult.getResultKey(); // neuen Ergebnisschlüssel bestimmen - er muss eindeutig sein, also müssen wir prüfen // ob es nicht bereits ein Ergebnis mit diesem Schlüssel in unserem Portfolio gibt String newResultKey = rg.getName(); if(caPortfolio.hasResult(newResultKey)) { // derselbe Schlüssel existiert bereits, wir müssen einen neuen Schlüssel finden newResultKey = SQUtils.generateUniqueName(mainResultKey, new IUniqueNameChecker() { public boolean checkNameExist(String name) throws Exception { return caPortfolio.hasResult(name); } }); } // Zusammengeführtes Ergebnis erstellen SettingsMap copiedSettingsMap = rgMainResult.getSettings().clone(); // Neues zusammengeführtes Ergebnis erstellen und zum Portfolio hinzufügen Ergebnis mergedResult = new Result(newResultKey, caPortfolio, copiedSettingsMap); caPortfolio.addSubresult(newResultKey, copiedSettingsMap, mergedResult); // Symbol und Zeitrahmen der zusammengeführten Strategie festlegen mergedResult.setString(SpecialValues.Symbol, rg.mainResult().getString(SpecialValues.Symbol)); mergedResult.setString(SpecialValues.Timeframe, rg.mainResult().getString(SpecialValues.Timeframe)); long rgDateFrom = rg.specialValues().getLong(SpecialValues.HistoryFrom, Long.MAX_VALUE); long rgDateTo = rg.specialValues().getLong(SpecialValues.HistoryTo, Long.MIN_VALUE); long caDateFrom = caPortfolio.specialValues().getLong(SpecialValues.PortfolioHistoryFrom, Long.MAX_VALUE); long caDateTo = caPortfolio.specialValues().getLong(SpecialValues.PortfolioHistoryTo, Long.MIN_VALUE); caPortfolio.specialValues().set(SpecialValues.HistoryFrom, Math.min(rgDateFrom, caDateFrom)); caPortfolio.specialValues().set(SpecialValues.HistoryTo, Math.max(rgDateTo, caDateTo)); copiedSettingsMap.set(SettingsKeys.PortfolioDataStart, Math.min(rgDateFrom, caDateFrom)); copiedSettingsMap.set(SettingsKeys.PortfolioDataEnd, Math.max(rgDateTo, caDateTo)); return newResultKey; } //------------------------------------------------------------------------ private void copyOrdersToPortfolio(ResultsGroup caPortfolio, ResultsGroup rg, String newResultKey) throws Exception { // Abrufen der Auftragsliste aus unserem aktuellen Portfolio OrdersList mergedOrdersList = caPortfolio.orders(); // holt alle Aufträge aus dem Ergebnis der zusammengefassten Strategie - beachten Sie, dass sie geklont werden müssen! String mainResultKey = rg.mainResult().getResultKey(); OrdersList filteredOL = rg.orders().filterWithClone(mainResultKey, Directions.Both, SampleTypes.FullSample); // nicht durch diese Aufträge gehen und sie zur Liste der Portfolioaufträge hinzufügen for(int i=0; i<filteredOL.size(); i++) { Order order = filteredOL.get(i); // order.SetupName wird als Bezeichner verwendet, damit wir wissen, zu welchem Ergebnis die Order gehört // daher müssen wir ihn auf newResultKey setzen order.SetupName = newResultKey; mergedOrdersList.add(order); } } //------------------------------------------------------------------------ private void createPortfolioResult(ResultsGroup caPortfolio) throws Exception { SettingsMap settings = caPortfolio.mainResult().getSettings(); Ergebnis portfolioResult = new Result(ResultsGroup.Portfolio, caPortfolio, settings); caPortfolio.removeSubresult(ResultsGroup.Portfolio, true); caPortfolio.addSubresult(ResultsGroup.Portfolio, settings, portfolioResult); caPortfolio.specialValues().setString(SpecialValues.Symbol, ResultsGroup.Portfolio); // für Portfolio Aufträge nach ihrer Öffnungszeit sortieren OrdersList ordersList = caPortfolio.orders(); ordersList.sort(new OrderComparatorByOpenTime()); portfolioResult.computeAllStats(caPortfolio.specialValues(), caPortfolio.getOOS()); caPortfolio.updated = true; } }
War dieser Artikel hilfreich? Der Artikel war nützlich Der Artikel war nicht nützlich
Ausgezeichnetes Beispiel! Genau das, was ich brauchte! Vielen Dank Mark