Documentazione
Applicazioni
Ultimo aggiornamento il 16. 11. 2021 da Mark Fric
Esempio - analisi personalizzata per banca dati
Contenuto della pagina
Questo esempio riguarda l'analisi personalizzata per banca dati. Diversamente dall'analisi personalizzata per strategia, che elabora una sola strategia, questo frammento di CA analizza l'intera banca dati e può accedere a tutti i risultati della strategia in una banca dati.
L'analisi personalizzata per banca dati può essere eseguita solo da un'attività personalizzata nel progetto personalizzato.
In questo esempio realizzeremo un esempio abbastanza complesso di snippet di analisi personalizzato che costruirà un portafoglio a partire dai risultati Walk-Forward delle strategie presenti nella banca dati.
Questa era una richiesta della nostra prima sessione di codifica.
Passo 1 - Creare un nuovo snippet di analisi personalizzato
Aprire CodeEditor, fare clic su Crea nuovo e scegliere l'opzione Analisi personalizzata (CA) in basso. Nominarla Portafoglio del PAM.
Questo creerà un nuovo snippet WFPortfolio.java in cartella Utente/Snippet/SQ/Analisi personalizzata
Questa volta, lo imposteremo come TIPO_PROCESSO_DI_BANCA_DATI nel costruttore della classe:
public WFPortfolio() { super("WFPortfolio", TYPE_PROCESS_DATABANK); }
Passo 2 - Implementare il metodo processDatabank()
Questa CA chiama il metodo elaboraBancaDati() che ha 4 parametri:
- Progetto di stringa - nome del progetto in cui è inserito il task CA
- Compito di stringa - nome del task CA
- Stringa databankName - nome della banca dati su cui lavora lo snippet di CA
- ArrayList databankRG - elenco di tutte le strategie (RisultatiGruppi) da questa banca dati.
Restituisce inoltre un elenco ArrayList, che deve contenere solo le strategie dell'elenco di input che devono essere conservate nella banca dati.
In questo modo può essere utilizzato come filtro: si possono scorrere le strategie nell'elenco di databankRG e creare un nuovo elenco in cui inserire solo quelle che corrispondono a qualche criterio. Le strategie non presenti nell'elenco di output saranno eliminate dalla banca dati.
Nel nostro caso non vogliamo cancellare qualcosa dalla banca dati, ma aggiungere una nuova strategia (il nostro portafoglio appena creato). Vediamo come fare.
In sintesi, il codice fa questo:
- Crea un nuovo gruppo di risultati per il portafoglio, che sarà vuoto all'inizio.
- Esamina ogni strategia nella banca dati e verifica se ha un risultato WF. In caso affermativo, copierà questo risultato in un nuovo portafoglio che include tutti gli ordini WF.
- Calcolo del risultato del portafoglio dai risultati secondari - per impostazione predefinita non viene calcolato dai risultati di WF, quindi dobbiamo farlo da soli nel codice.
- Aggiungere il gruppo di risultati del portafoglio finito alla banca dati
Il codice è lungo e complesso, non lo spiegheremo tutto qui. È mostrato alla fine di questo articolo completamente commentato.
Passo 3 - esecuzione dello snippet CA personalizzato
Per eseguire uno snippet CA "per banca dati", occorre creare un progetto personalizzato e un task personalizzato di tipo Analisi personalizzata.
Selezionare la voce Portafoglio del PAM nell'attività personalizzata.
Quindi aggiungere alcune strategie con risultati Walk-Forward alla banca dati dei risultati ed eseguire l'attività.
Dovrebbe creare una nuova strategia denominata Portafoglio azionario WF che conterrà le azioni WF di tutte le strategie presenti in Risultati.
e il patrimonio netto del portafoglio di tutti i risultati del WF si presenta così:
Codice commentato completo dello snippet
package SQ.CustomAnalysis; import com.strategyquant.lib.*; import java.util.ArrayList; import com.strategyquant.tradinglib.*; import com.strategyquant.tradinglib.project.ProjectEngine; import com.strategyquant.tradinglib.results.SpecialValues; import com.strategyquant.tradinglib.results.stats.comparator.OrderComparatorByOpenTime; public class WFPortfolio extends CustomAnalysisMethod { //------------------------------------------------------------------------ //------------------------------------------------------------------------ //------------------------------------------------------------------------ public WFPortfolio() { super("WFPortfolio", TYPE_PROCESS_DATABANK); } //------------------------------------------------------------------------ @Override public boolean filterStrategy(String project, String task, String databankName, ResultsGroup rg) throws Exception { return true; } //------------------------------------------------------------------------ @Override public ArrayList<ResultsGroup> processDatabank(String project, String task, String databankName, ArrayList<ResultsGroup> databankRG) throws Exception { // create new ResultsGroup for our new portfolio ResultsGroup portfolioRG = new ResultsGroup("WF Equity portfolio"); // get OrderList from new portfolio (empty so far), // we will insert WF orders there OrdersList portfolioOrdersList = portfolioRG.orders(); // go through all strategy results in databank for(ResultsGroup strategyRG : databankRG) { // skip strategies whose name starts with "WF Equity portfolio" // this will ensure that we'll ignore our portfolios created // in previous runs String strName = strategyRG.getName(); if(strName.startsWith("WF Equity portfolio")) { continue; } // get best Walk-Forward result from a strategy // If it doesn't exist it will return null Result wfResult = getWFResult(strategyRG); if(wfResult == null) { continue; } // --------------------- // wfResult is the best Walk-Forward result from existing strategy // clone it to a new result with all its settings String wfResultKey = wfResult.getResultKey(); // we'll name the new subresult as "StrategyName "+ "existing WF result name" String newSubResultKey = String.format("%s-%s", strategyRG.getName(), wfResultKey); // clone settings to use them in the new result SettingsMap settingsMapCopy = wfResult.getSettings().clone(); // create new result that will be added to the portfolio Result wfResultCopied = new Result(newSubResultKey, portfolioRG, settingsMapCopy); portfolioRG.addSubresult(newSubResultKey, settingsMapCopy, wfResultCopied); // --------------------- // copy WF orders from original strategy to new results group OrdersList filteredOL = strategyRG.orders().filterWithClone(wfResultKey, Directions.Both, SampleTypes.FullSample); for(int i=0; i<filteredOL.size(); i++) { Order order = filteredOL.get(i); // change setup name to match the new result name in the new portfolio order.SetupName = newSubResultKey; order.IsInPortfolio = 1; // add the order to the portfolio OrdersList portfolioOrdersList.add(order); } // copy also symbol definitions from old strategy // this is needed for proper cancullation of PL and metrics portfolioRG.symbols().add(strategyRG.symbols()); } // --------------------- // compute portfolio result // normally we'd call portfolioRG.createPortfolioResult() but the default version // ignores WF results, so we have to implement it by ourselves createPortfolioResult(portfolioRG); // portfolio ResultsGroup is complete, now add it to the databank Databank databank = ProjectEngine.get(project).getDatabanks().get(databankName); databank.add(portfolioRG, true); return databankRG; } //------------------------------------------------------------------------ /** * returns best Walk-Forward result - if it exists */ private Result getWFResult(ResultsGroup rg) throws Exception { String wfKey = rg.getBestWFResultKey(); if(wfKey == null) { return null; } return rg.subResult(wfKey); } //------------------------------------------------------------------------ /** * creates a Portfolio result from all the existing sub-results in the ResultsGroup * This is function from standard SQ library, with only exception that this works * also on WF results - standard ResultsGroup.createPortfolioResult() * ignores WF results when creating portfolio. * * @param portfolioRG * @throws Exception */ public void createPortfolioResult(ResultsGroup portfolioRG) throws Exception { Result firstResult = null; String tf = null; int resultsInPortfolio = 0; // go through all existing sub-results and get their initial capital and from-to dates for(String existingResultKey : portfolioRG.getResultKeys()) { Result result = portfolioRG.subResult(existingResultKey); resultsInPortfolio++; if(firstResult == null) { firstResult = result; } } if(resultsInPortfolio <= 1) { throw new Exception("ResultGroup doesn't contain more Results, cannot create a portfolio!"); } if(firstResult == null) { throw new Exception("No Result in ResultGroup to create portfolio!"); } SettingsMap settings = firstResult.getSettings(); Result portfolioResult = new Result(ResultsGroup.Portfolio, portfolioRG, settings); portfolioRG.removeSubresult(ResultsGroup.Portfolio, true); portfolioRG.addSubresult(ResultsGroup.Portfolio, settings, portfolioResult); portfolioRG.specialValues().setString(SpecialValues.Symbol, ResultsGroup.Portfolio); portfolioRG.specialValues().setString(SpecialValues.Timeframe, "N/A"); // for portfolio sort orders by their open time OrdersList ordersList = portfolioRG.orders(); ordersList.sort(new OrderComparatorByOpenTime()); // compute all metrics on the portfolio portfolioResult.computeAllStats(portfolioRG.specialValues(), portfolioRG.getOOS()); } }
Questo articolo è stato utile? L'articolo è stato utile L'articolo non è stato utile
Mark, grazie mille per questo impressionante lavoro !!!!!! È esattamente ciò di cui ho bisogno !!!!
SQX è davvero unico.
Con l'esempio, sarò in grado di costruire nuove idee.
Il codice commentato completo è davvero utile
Funziona bene !!!!!!! Grazie