[Quantproject-developers] QuantProject/b7_Scripts/TechnicalAnalysisTesting/Oscillators/FixedLevelOs
Brought to you by:
glauco_1
|
From: Marco M. <mi...@us...> - 2007-02-27 22:52:47
|
Update of /cvsroot/quantproject/QuantProject/b7_Scripts/TechnicalAnalysisTesting/Oscillators/FixedLevelOscillators/PortfolioValueOscillator/BiasedPVO/BiasedPVONoThresholds In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv6633/BiasedPVO/BiasedPVONoThresholds Added Files: RunBiasedPVONoThresholds.cs GenomeManagerBiasedPVONoThresholds.cs EndOfDayTimerHandlerBiasedPVONoThresholds.cs Log Message: Added variations of Portfolio Value Oscillator strategy (some of these files have to be tested yet and will be re-written as soon as possible ...): - WeightedPVO: basic PVO (with thresholds); - weigthedBalancedPVO: the weighted PVO with 50% of portfolio invested in short positions and the remaining half in long ones; - biasedPVO: it is not simply chosen the genome with the highest fitness (as in the PVO base), but it is chosen the genome (from a given set of genomes with a good fitness) that has the highest degree of deviation from a threshold; - biasedPVO No Thresholds: as the biased, but the signal is just the highest gain or loss; - biasedOTC_PVONoThresholds: as the previous one, but with these differences: new positions are opened at market open, choosing the genome that opens with the highest gain or loss with respect to the last close All positions are closed at market close (at the moment ...tests are in progress ...) --- NEW FILE: RunBiasedPVONoThresholds.cs --- /* QuantProject - Quantitative Finance Library RunBiasedPVONoThresholds.cs Copyright (C) 2007 Marco Milletti This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ using System; using System.Collections; using System.Data; using QuantProject.ADT; using QuantProject.ADT.Optimizing.Genetic; using QuantProject.Business.DataProviders; using QuantProject.Business.Financial.Accounting; using QuantProject.Business.Financial.Accounting.Reporting; using QuantProject.Business.Financial.Instruments; using QuantProject.Business.Financial.Ordering; using QuantProject.Business.Scripting; using QuantProject.Business.Strategies; using QuantProject.Business.Testing; using QuantProject.Business.Timing; using QuantProject.Data.DataProviders; using QuantProject.Data.Selectors; using QuantProject.Scripts.TickerSelectionTesting.EfficientPortfolios; using QuantProject.Presentation.Reporting.WindowsForm; using QuantProject.ADT.FileManaging; using QuantProject.Scripts.WalkForwardTesting.LinearCombination; using QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator; namespace QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator.BiasedPVO.BiasedPVONoThresholds { /// <summary> /// Script that implements the PVO strategy, /// with these differences: /// when it is time to open new positions, /// it is not simply chosen the genome with the highest fitness /// (as in the PVO base), but it is chosen the genome (from a /// given set of genomes with a good fitness) that /// has the highest gain or loss /// </summary> [Serializable] public class RunBiasedPVONoThresholds : RunPVO { private int numOfDifferentGenomesToEvaluateOutOfSample; private double minimumAcceptableGain; public RunBiasedPVONoThresholds(string tickerGroupID, int maxNumOfEligibleTickersForOptimization, int numberOfTickersToBeChosen, int numDaysForOptimizationPeriod, int generationNumberForGeneticOptimizer, int populationSizeForGeneticOptimizer, string benchmark, DateTime startDate, DateTime endDate, int numOfDifferentGenomesToEvaluateOutOfSample, int numDaysBetweenEachOptimization, PortfolioType inSamplePortfolioType, double maxAcceptableCloseToCloseDrawdown, double minimumAcceptableGain, double maxRunningHours): base(tickerGroupID, maxNumOfEligibleTickersForOptimization, numberOfTickersToBeChosen, numDaysForOptimizationPeriod, generationNumberForGeneticOptimizer, populationSizeForGeneticOptimizer, benchmark, startDate, endDate, 2, 0, 0, 0, 0, 1, true, false, numDaysBetweenEachOptimization, inSamplePortfolioType, maxAcceptableCloseToCloseDrawdown, maxRunningHours) { this.numOfDifferentGenomesToEvaluateOutOfSample = numOfDifferentGenomesToEvaluateOutOfSample; this.minimumAcceptableGain = minimumAcceptableGain; this.scriptName = "PVO_PriceSel_NoWeightsAndThresholds"; } #region auxiliary overriden methods for Run protected override void run_initializeEndOfDayTimerHandler() { this.endOfDayTimerHandler = new EndOfDayTimerHandlerBiasedPVONoThresholds(this.tickerGroupID, this.numberOfEligibleTickers, this.numberOfTickersToBeChosen, this.numDaysForOptimizationPeriod, this.account, this.generationNumberForGeneticOptimizer, this.populationSizeForGeneticOptimizer, this.benchmark, this.numOfDifferentGenomesToEvaluateOutOfSample, this.numDaysBetweenEachOptimization, this.portfolioType, this.maxAcceptableCloseToCloseDrawdown, this.minimumAcceptableGain); } public override void SaveScriptResults() { string fileName = DateTime.Now.Hour.ToString().PadLeft(2,'0') + "_" + DateTime.Now.Minute.ToString().PadLeft(2,'0') + "_" + this.scriptName + "GenOS_" + this.numOfDifferentGenomesToEvaluateOutOfSample + "_OsDays_" + numDaysForOscillatingPeriod + "_From_" + this.tickerGroupID + "_" + this.numberOfEligibleTickers + "_DaysForOpt" + this.numDaysForOptimizationPeriod + "Tick" + this.numberOfTickersToBeChosen + "GenN°" + this.generationNumberForGeneticOptimizer + "PopSize" + this.populationSizeForGeneticOptimizer + Convert.ToString(this.portfolioType); string dirNameWhereToSaveReports = System.Configuration.ConfigurationSettings.AppSettings["ReportsArchive"] + "\\" + this.ScriptName + "\\"; string dirNameWhereToSaveTransactions = System.Configuration.ConfigurationSettings.AppSettings["TransactionsArchive"] + "\\" + this.ScriptName + "\\"; string dirNameWhereToSaveBestGenomes = System.Configuration.ConfigurationSettings.AppSettings["GenomesArchive"] + "\\" + this.ScriptName + "\\"; this.checkDateForReport_createDirIfNotPresent(dirNameWhereToSaveBestGenomes); OptimizationOutput optimizationOutput = new OptimizationOutput(); foreach(GenomeRepresentation genomeRepresentation in this.endOfDayTimerHandler.BestGenomes) optimizationOutput.Add(genomeRepresentation); ObjectArchiver.Archive(optimizationOutput, dirNameWhereToSaveBestGenomes + fileName + ".bgn"); //default report with numIntervalDays = 1 AccountReport accountReport = this.account.CreateReport(fileName,1, this.endOfDayTimer.GetCurrentTime(), this.benchmark, new HistoricalAdjustedQuoteProvider()); this.checkDateForReport_createDirIfNotPresent(dirNameWhereToSaveReports); ObjectArchiver.Archive(accountReport, dirNameWhereToSaveReports + fileName + ".qPr"); this.endOfDayTimer.Stop(); } #endregion } } --- NEW FILE: GenomeManagerBiasedPVONoThresholds.cs --- /* QuantProject - Quantitative Finance Library GenomeManagerBiasedPVONoThresholds.cs Copyright (C) 2007 Marco Milletti This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ using System; using System.Data; using System.Collections; using QuantProject.ADT; using QuantProject.ADT.Statistics; using QuantProject.ADT.Optimizing.Genetic; using QuantProject.Data; using QuantProject.Data.DataTables; using QuantProject.Scripts.TickerSelectionTesting.EfficientPortfolios; namespace QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator.BiasedPVO.BiasedPVONoThresholds { /// <summary> /// Implements what needed to use the Genetic Optimizer /// for finding the portfolio that best suites /// the Biased Portfolio Value Oscillator strategy, with no thresholds /// </summary> [Serializable] public class GenomeManagerBiasedPVONoThresholds : GenomeManagerForEfficientPortfolio { public GenomeManagerBiasedPVONoThresholds(DataTable setOfInitialTickers, DateTime firstQuoteDate, DateTime lastQuoteDate, int numberOfTickersInPortfolio, PortfolioType inSamplePortfolioType) : base(setOfInitialTickers, firstQuoteDate, lastQuoteDate, numberOfTickersInPortfolio, 0.0, inSamplePortfolioType) { this.retrieveData(); } #region Get Min and Max Value public override int GetMinValueForGenes(int genePosition) { int returnValue; switch (this.portfolioType) { case PortfolioType.OnlyLong : returnValue = 0; break; default://For ShortAndLong or OnlyShort portfolios returnValue = - this.originalNumOfTickers; break; } return returnValue; } public override int GetMaxValueForGenes(int genePosition) { int returnValue; switch (this.portfolioType) { case PortfolioType.OnlyShort : returnValue = - 1; break; default ://For ShortAndLong or OnlyLong portfolios returnValue = this.originalNumOfTickers - 1; break; } return returnValue; } #endregion protected override float[] getArrayOfRatesOfReturn(string ticker) { float[] returnValue = null; Quotes tickerQuotes = new Quotes(ticker, this.firstQuoteDate, this.lastQuoteDate); tickerQuotes.RecalculateCloseToCloseRatios(); returnValue = QuantProject.ADT.ExtendedDataTable.GetArrayOfFloatFromColumn(tickerQuotes, Quotes.AdjustedCloseToCloseRatio); for(int i = 0; i<returnValue.Length; i++) returnValue[i] = returnValue[i] - 1.0f; this.numberOfExaminedReturns = returnValue.Length; return returnValue; } //fitness is a number that indicates how much the portfolio //tends to preserve equity (no gain and no loss), with a low std dev public override double GetFitnessValue(Genome genome) { double returnValue = -1.0; this.portfolioRatesOfReturn = this.getPortfolioRatesOfReturn( genome.Genes() ); //double[] asbolutePortfolioRatesOfReturns = new double[this.portfolioRatesOfReturn.Length]; // for( int i = 0; i<asbolutePortfolioRatesOfReturns.Length; i++ ) // asbolutePortfolioRatesOfReturns[i] = Math.Abs(this.portfolioRatesOfReturn[i]); returnValue = 1.0/ //( BasicFunctions.SimpleAverage(asbolutePortfolioRatesOfReturns) * ( Math.Abs( BasicFunctions.SimpleAverage(this.portfolioRatesOfReturn) ) * BasicFunctions.StdDev(this.portfolioRatesOfReturn) ); //); return returnValue; } public override object Decode(Genome genome) { string[] arrayOfTickers = new string[genome.Genes().Length]; int indexOfTicker; for(int index = 0; index < genome.Genes().Length; index++) { indexOfTicker = (int)genome.Genes().GetValue(index); arrayOfTickers[index] = this.decode_getTickerCodeForLongOrShortTrade(indexOfTicker); } GenomeMeaningPVO meaning = new GenomeMeaningPVO(arrayOfTickers, 0.0, 0.0, 2); return meaning; } } } --- NEW FILE: EndOfDayTimerHandlerBiasedPVONoThresholds.cs --- /* QuantProject - Quantitative Finance Library EndOfDayTimerHandlerBiasedPVONoThresholds.cs Copyright (C) 2007 Marco Milletti This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ using System; using System.Data; using System.Collections; using QuantProject.ADT; using QuantProject.Business.Financial.Accounting; using QuantProject.Business.Financial.Instruments; using QuantProject.Business.Financial.Ordering; using QuantProject.Business.Timing; using QuantProject.Business.Strategies; using QuantProject.Data; using QuantProject.Data.DataProviders; using QuantProject.Data.Selectors; using QuantProject.Data.DataTables; using QuantProject.ADT.Optimizing.Genetic; using QuantProject.Scripts.TickerSelectionTesting.EfficientPortfolios; using QuantProject.Scripts.WalkForwardTesting.LinearCombination; using QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator; namespace QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator.BiasedPVO.BiasedPVONoThresholds { /// <summary> /// Implements MarketOpenEventHandler and MarketCloseEventHandler /// These handlers contain the core strategy for the Biased Portfolio Value /// Oscillator, with no thresholds /// </summary> [Serializable] public class EndOfDayTimerHandlerBiasedPVONoThresholds : EndOfDayTimerHandlerPVO { protected int numOfDifferentGenomesToEvaluateOutOfSample; protected double minimumAcceptableGain; protected int currentGenomeIndex = 0; protected double currentTickersGainOrLoss = 0.0; protected Hashtable genomesCollector; protected bool takeProfitConditionReached; new protected string[,] chosenTickers; new protected double[,] chosenTickersPortfolioWeights; public EndOfDayTimerHandlerBiasedPVONoThresholds(string tickerGroupID, int numberOfEligibleTickers, int numberOfTickersToBeChosen, int numDaysForOptimizationPeriod, Account account, int generationNumberForGeneticOptimizer, int populationSizeForGeneticOptimizer, string benchmark, int numOfDifferentGenomesToEvaluateOutOfSample, int numDaysBetweenEachOptimization, PortfolioType portfolioType, double maxAcceptableCloseToCloseDrawdown, double minimumAcceptableGain): base(tickerGroupID, numberOfEligibleTickers, numberOfTickersToBeChosen, numDaysForOptimizationPeriod, account, generationNumberForGeneticOptimizer, populationSizeForGeneticOptimizer, benchmark, 2, 0, 0, 0, 0, 1, true, false, numDaysBetweenEachOptimization, portfolioType, maxAcceptableCloseToCloseDrawdown) { this.numOfDifferentGenomesToEvaluateOutOfSample = numOfDifferentGenomesToEvaluateOutOfSample; this.minimumAcceptableGain = minimumAcceptableGain; this.chosenTickers = new string[numOfDifferentGenomesToEvaluateOutOfSample, numberOfTickersToBeChosen]; this.chosenTickersPortfolioWeights = new double[numOfDifferentGenomesToEvaluateOutOfSample, numberOfTickersToBeChosen]; this.genomesCollector = new Hashtable(); } #region MarketCloseEventHandler protected virtual double getCurrentChosenTickersGainOrLoss(IndexBasedEndOfDayTimer timer, int indexForChosenTickers) { double returnValue = 999.0; try { DateTime date = (DateTime)timer.IndexQuotes.Rows[timer.CurrentDateArrayPosition]["quDate"]; string[] tickers = new string[this.numberOfTickersToBeChosen]; double[] tickerWeights = new double[this.numberOfTickersToBeChosen]; for(int i = 0; i < this.numberOfTickersToBeChosen; i++) { tickers[i] = this.chosenTickers[indexForChosenTickers,i]; tickerWeights[i] = this.chosenTickersPortfolioWeights[indexForChosenTickers,i]; } returnValue = SignedTicker.GetCloseToClosePortfolioReturn( tickers, tickerWeights, date,date); } catch(MissingQuotesException ex) { ex = ex; } return returnValue; } //sets currentGenomeIndex with the genome's index that crosses an overbought/oversold threshold with the //highest degree and sets currentTickersGainOrLoss accordingly private void marketCloseEventHandler_openPositions_chooseBestGenome(IndexBasedEndOfDayTimer timer) { //default genome index is the first //genome (with the highest plain fitness), if no other genome //presents a gain or a loss greater than the first genome double currentTickersGainOrLoss = 0.0; double currentMaxAbsoluteMove = 0.0; double currentAbsoluteMove = 0.0; for(int i = 0; i < this.numOfDifferentGenomesToEvaluateOutOfSample; i++) { currentTickersGainOrLoss = this.getCurrentChosenTickersGainOrLoss(timer, i); currentAbsoluteMove = Math.Abs( currentTickersGainOrLoss ); if(currentAbsoluteMove != 999.0 && currentAbsoluteMove > currentMaxAbsoluteMove) //currentAbsoluteMove has been properly computed and it is //greater than the current greatest move up to date { currentMaxAbsoluteMove = currentAbsoluteMove; this.currentGenomeIndex = i; this.currentTickersGainOrLoss = currentTickersGainOrLoss; } } } private void marketCloseEventHandler_openPositions(IndexBasedEndOfDayTimer timer) { this.currentTickersGainOrLoss = 999.0; this.marketCloseEventHandler_openPositions_chooseBestGenome(timer); if(this.currentTickersGainOrLoss != 999.0) //currentChosenTickersValue has been properly computed { string[] tickers = new string[this.numberOfTickersToBeChosen]; for(int i = 0; i < this.numberOfTickersToBeChosen; i++) tickers[i] = this.chosenTickers[this.currentGenomeIndex,i]; if(this.currentTickersGainOrLoss > 0.0) { SignedTicker.ChangeSignOfEachTicker(tickers); base.openPositions(tickers); } else //(currentChosenTickersGainOrLoss < 0.0) { base.openPositions(tickers); } this.currentAccountValue = this.account.GetMarketValue(); } } private void marketCloseEventHandler_closeIfItIsTimeToClose_updateStopLossAndTakeProfitConditions() { this.previousAccountValue = this.currentAccountValue; this.currentAccountValue = this.account.GetMarketValue(); double portfolioGainOrLoss = (this.currentAccountValue - this.previousAccountValue) /this.previousAccountValue; if( portfolioGainOrLoss < -this.maxAcceptableCloseToCloseDrawdown ) { this.stopLossConditionReached = true; this.takeProfitConditionReached = false; } else if (portfolioGainOrLoss >= this.minimumAcceptableGain) { this.stopLossConditionReached = false; this.takeProfitConditionReached = true; } else { this.stopLossConditionReached = false; this.takeProfitConditionReached = false; } } private void marketCloseEventHandler_closeIfItIsTimeToClose() { this.marketCloseEventHandler_closeIfItIsTimeToClose_updateStopLossAndTakeProfitConditions(); if(this.stopLossConditionReached || this.takeProfitConditionReached || this.numDaysElapsedSinceLastOptimization + 1 == this.numDaysBetweenEachOptimization ) //reversal conditions have not been reached but //stop loss or take profit conditions yes //or after the close it is necessary to run //another optimization { base.closePositions(); this.orders.Clear(); } } public override void MarketCloseEventHandler( Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { if(this.account.Portfolio.Count > 0) //this.marketCloseEventHandler_reverseOrClose((IndexBasedEndOfDayTimer)sender); this.marketCloseEventHandler_closeIfItIsTimeToClose(); else if ( this.account.Portfolio.Count == 0 && this.chosenTickers[0,0] != null ) //portfolio is empty and optimization has been already launched this.marketCloseEventHandler_openPositions((IndexBasedEndOfDayTimer)sender); } #endregion #region OneHourAfterMarketCloseEventHandler private void setTickers_updateTickersListAndAddGenomesForLog(GeneticOptimizer GO, int eligibleTickersForGO) { int addedGenomes = 0; int counter = 0; Genome currentGenome = null; this.genomesCollector.Clear(); while(addedGenomes < this.numOfDifferentGenomesToEvaluateOutOfSample && counter < GO.PopulationSize) { currentGenome = (Genome)GO.CurrentGeneration[GO.PopulationSize - 1 - counter]; if(counter == 0 || !this.genomesCollector.ContainsKey(currentGenome.Fitness) ) //it is the first genome to be added or no genome with the current // fitness has been added to the hashtable yet { for(int i = 0; i<this.numberOfTickersToBeChosen; i++) { this.chosenTickers[addedGenomes,i] = ((GenomeMeaningPVO)currentGenome.Meaning).Tickers[i]; this.chosenTickersPortfolioWeights[addedGenomes,i] = ((GenomeMeaningPVO)currentGenome.Meaning).TickersPortfolioWeights[i]; } this.genomesCollector.Add(currentGenome.Fitness, null); this.addPVOGenomeToBestGenomes(currentGenome,((GenomeManagerForEfficientPortfolio)this.iGenomeManager).FirstQuoteDate, ((GenomeManagerForEfficientPortfolio)this.iGenomeManager).LastQuoteDate, eligibleTickersForGO, 2, this.portfolioType, GO.GenerationCounter, 0.0, 0.0); addedGenomes ++ ; } counter ++ ; } } protected override void setTickers(DateTime currentDate, bool setGenomeCounter) { DataTable setOfTickersToBeOptimized = this.getSetOfTickersToBeOptimized(currentDate); this.iGenomeManager = new GenomeManagerBiasedPVONoThresholds(setOfTickersToBeOptimized, currentDate.AddDays(-this.numDaysForOptimizationPeriod), currentDate, this.numberOfTickersToBeChosen, this.portfolioType); GeneticOptimizer GO = new GeneticOptimizer(this.iGenomeManager, this.populationSizeForGeneticOptimizer, this.generationNumberForGeneticOptimizer, this.seedForRandomGenerator); if(setGenomeCounter) this.genomeCounter = new GenomeCounter(GO); GO.MutationRate = 0.1; GO.Run(false); this.setTickers_updateTickersListAndAddGenomesForLog(GO, setOfTickersToBeOptimized.Rows.Count); } #endregion } } |