[Quantproject-developers] QuantProject/b7_Scripts/TechnicalAnalysisTesting/Oscillators/FixedLevelOs
Brought to you by:
glauco_1
|
From: Marco M. <mi...@us...> - 2007-02-27 22:52:45
|
Update of /cvsroot/quantproject/QuantProject/b7_Scripts/TechnicalAnalysisTesting/Oscillators/FixedLevelOscillators/PortfolioValueOscillator/WeightedPVO In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv6633/WeightedPVO Added Files: RunWeightedPVO.cs GenomeManagerWeightedPVO.cs EndOfDayTimerHandlerWeightedPVO.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: EndOfDayTimerHandlerWeightedPVO.cs --- /* QuantProject - Quantitative Finance Library EndOfDayTimerHandlerWeightedPVO.cs Copyright (C) 2006 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.WeightedPVO { /// <summary> /// Implements MarketOpenEventHandler and MarketCloseEventHandler /// These handlers contain the core strategy for the Portfolio Value /// Oscillator using weights for tickers /// </summary> [Serializable] public class EndOfDayTimerHandlerWeightedPVO : EndOfDayTimerHandlerPVO { public EndOfDayTimerHandlerWeightedPVO(string tickerGroupID, int numberOfEligibleTickers, int numberOfTickersToBeChosen, int numDaysForOptimizationPeriod, Account account, int generationNumberForGeneticOptimizer, int populationSizeForGeneticOptimizer, string benchmark, int numDaysForOscillatingPeriod, int minLevelForOversoldThreshold, int maxLevelForOversoldThreshold, int minLevelForOverboughtThreshold, int maxLevelForOverboughtThreshold, int divisorForThresholdComputation, bool symmetricalThresholds, bool overboughtMoreThanOversoldForFixedPortfolio, int numDaysBetweenEachOptimization, PortfolioType portfolioType, double maxAcceptableCloseToCloseDrawdown): base(tickerGroupID, numberOfEligibleTickers, numberOfTickersToBeChosen, numDaysForOptimizationPeriod, account, generationNumberForGeneticOptimizer, populationSizeForGeneticOptimizer, benchmark, numDaysForOscillatingPeriod, minLevelForOversoldThreshold, maxLevelForOversoldThreshold, minLevelForOverboughtThreshold, maxLevelForOverboughtThreshold, divisorForThresholdComputation, symmetricalThresholds, overboughtMoreThanOversoldForFixedPortfolio, numDaysBetweenEachOptimization, portfolioType, maxAcceptableCloseToCloseDrawdown) { } protected override DataTable getSetOfTickersToBeOptimized(DateTime currentDate) { SelectorByGroup temporizedGroup = new SelectorByGroup(this.tickerGroupID, currentDate); DataTable tickersFromGroup = temporizedGroup.GetTableOfSelectedTickers(); int numOfTickersInGroupAtCurrentDate = tickersFromGroup.Rows.Count; SelectorByAverageRawOpenPrice byPrice = new SelectorByAverageRawOpenPrice(tickersFromGroup,false,currentDate.AddDays(-30), currentDate, numOfTickersInGroupAtCurrentDate, 20,500, 0.0001,100); SelectorByLiquidity mostLiquidSelector = new SelectorByLiquidity(byPrice.GetTableOfSelectedTickers(), false,currentDate.AddDays(-this.numDaysForOptimizationPeriod), currentDate, this.numberOfEligibleTickers); // SelectorByCloseToCloseCorrelationToBenchmark byCorrelationToBenchmark = // new SelectorByCloseToCloseCorrelationToBenchmark(mostLiquidSelector.GetTableOfSelectedTickers(), // "^GSPC",false, // currentDate.AddDays(-this.numDaysForOptimizationPeriod), currentDate, // this.numberOfEligibleTickers/2,false); // SelectorByQuotationAtEachMarketDay quotedAtEachMarketDayFromLastSelection = new SelectorByQuotationAtEachMarketDay(mostLiquidSelector.GetTableOfSelectedTickers(), false, currentDate.AddDays(-this.numDaysForOptimizationPeriod), currentDate, this.numberOfEligibleTickers, this.benchmark); return quotedAtEachMarketDayFromLastSelection.GetTableOfSelectedTickers(); } protected override void setTickers(DateTime currentDate, bool setGenomeCounter) { DataTable setOfTickersToBeOptimized = this.getSetOfTickersToBeOptimized(currentDate); if(setOfTickersToBeOptimized.Rows.Count > this.chosenTickers.Length*2) //the optimization process is meaningful only if the initial set of tickers is //larger than the number of tickers to be chosen { this.iGenomeManager = new GenomeManagerWeightedPVO(setOfTickersToBeOptimized, currentDate.AddDays(-this.numDaysForOptimizationPeriod), currentDate, this.numberOfTickersToBeChosen, this.numDaysForOscillatingPeriod, this.minLevelForOversoldThreshold, this.maxLevelForOversoldThreshold, this.minLevelForOverboughtThreshold, this.maxLevelForOverboughtThreshold, this.divisorForThresholdComputation, this.symmetricalThresholds, this.overboughtMoreThanOversoldForFixedPortfolio, this.portfolioType); GeneticOptimizer GO = new GeneticOptimizer(this.iGenomeManager, this.populationSizeForGeneticOptimizer, this.generationNumberForGeneticOptimizer, this.seedForRandomGenerator); if(setGenomeCounter) this.genomeCounter = new GenomeCounter(GO); GO.MutationRate = 0.2; GO.Run(false); this.chosenTickers = ((GenomeMeaningPVO)GO.BestGenome.Meaning).Tickers; this.chosenTickersPortfolioWeights = ((GenomeMeaningPVO)GO.BestGenome.Meaning).TickersPortfolioWeights; this.currentOversoldThreshold = ((GenomeMeaningPVO)GO.BestGenome.Meaning).OversoldThreshold; this.currentOverboughtThreshold = ((GenomeMeaningPVO)GO.BestGenome.Meaning).OverboughtThreshold; this.addPVOGenomeToBestGenomes(GO.BestGenome,((GenomeManagerForEfficientPortfolio)this.iGenomeManager).FirstQuoteDate, ((GenomeManagerForEfficientPortfolio)this.iGenomeManager).LastQuoteDate, setOfTickersToBeOptimized.Rows.Count, this.numDaysForOscillatingPeriod, this.portfolioType, GO.GenerationCounter, this.currentOversoldThreshold, this.currentOverboughtThreshold); } //else it will be buyed again the previous optimized portfolio //that's it the actual chosenTickers member } } } --- NEW FILE: RunWeightedPVO.cs --- /* QuantProject - Quantitative Finance Library RunWeightedPVO.cs Copyright (C) 2006 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; namespace QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator.WeightedPVO { /// <summary> /// Script that implements an oscillating strategy using weights for tickers, /// based on the classical technical indicator /// RelativeStrengthIndex - RSI /// </summary> [Serializable] public class RunWeightedPVO : RunEfficientPortfolio { protected int minLevelForOversoldThreshold; protected int maxLevelForOversoldThreshold; protected int minLevelForOverboughtThreshold; protected int maxLevelForOverboughtThreshold; protected int divisorForThresholdComputation; //to be used by the optimizer protected int numDaysBetweenEachOptimization; protected double maxAcceptableCloseToCloseDrawdown; protected int numDaysForOscillatingPeriod; protected bool symmetricalThresholds = false; protected bool overboughtMoreThanOversoldForFixedPortfolio = false; public RunWeightedPVO(string tickerGroupID, int maxNumOfEligibleTickersForOptimization, int numberOfTickersToBeChosen, int numDaysForOptimizationPeriod, int generationNumberForGeneticOptimizer, int populationSizeForGeneticOptimizer, string benchmark, DateTime startDate, DateTime endDate, int numDaysForOscillatingPeriod, int minLevelForOversoldThreshold, int maxLevelForOversoldThreshold, int minLevelForOverboughtThreshold, int maxLevelForOverboughtThreshold, int divisorForThresholdComputation, bool symmetricalThresholds, bool overboughtMoreThanOversoldForFixedPortfolio, int numDaysBetweenEachOptimization, PortfolioType inSamplePortfolioType, double maxAcceptableCloseToCloseDrawdown, double maxRunningHours): base(tickerGroupID, maxNumOfEligibleTickersForOptimization, numberOfTickersToBeChosen, numDaysForOptimizationPeriod, generationNumberForGeneticOptimizer, populationSizeForGeneticOptimizer, benchmark, startDate, endDate, 0.0, inSamplePortfolioType, maxRunningHours) { this.ScriptName = "PVO_SR_WithWeights_PriceSel"; this.minLevelForOversoldThreshold = minLevelForOversoldThreshold; this.maxLevelForOversoldThreshold = maxLevelForOversoldThreshold; this.minLevelForOverboughtThreshold = minLevelForOverboughtThreshold; this.maxLevelForOverboughtThreshold = maxLevelForOverboughtThreshold; this.divisorForThresholdComputation = divisorForThresholdComputation; this.symmetricalThresholds = symmetricalThresholds; this.overboughtMoreThanOversoldForFixedPortfolio = overboughtMoreThanOversoldForFixedPortfolio; this.maxAcceptableCloseToCloseDrawdown = maxAcceptableCloseToCloseDrawdown; this.numDaysForOscillatingPeriod = numDaysForOscillatingPeriod; this.numDaysBetweenEachOptimization = numDaysBetweenEachOptimization; } #region auxiliary overriden methods for Run protected override void run_initializeEndOfDayTimerHandler() { this.endOfDayTimerHandler = new EndOfDayTimerHandlerWeightedPVO(this.tickerGroupID, this.numberOfEligibleTickers, this.numberOfTickersToBeChosen, this.numDaysForOptimizationPeriod, this.account, this.generationNumberForGeneticOptimizer, this.populationSizeForGeneticOptimizer, this.benchmark, this.numDaysForOscillatingPeriod, this.minLevelForOversoldThreshold, this.maxLevelForOversoldThreshold, this.minLevelForOverboughtThreshold, this.maxLevelForOverboughtThreshold, this.divisorForThresholdComputation, this.symmetricalThresholds, this.overboughtMoreThanOversoldForFixedPortfolio, this.numDaysBetweenEachOptimization, this.portfolioType, this.maxAcceptableCloseToCloseDrawdown); } protected override void run_initializeHistoricalQuoteProvider() { this.historicalQuoteProvider = new HistoricalAdjustedQuoteProvider(); } protected override void run_addEventHandlers() { this.endOfDayTimer.MarketClose += new MarketCloseEventHandler( this.endOfDayTimerHandler.MarketCloseEventHandler); this.endOfDayTimer.MarketClose += new MarketCloseEventHandler( this.checkDateForReport); this.endOfDayTimer.OneHourAfterMarketClose += new OneHourAfterMarketCloseEventHandler( this.endOfDayTimerHandler.OneHourAfterMarketCloseEventHandler); } public override void SaveScriptResults() { string fileName = DateTime.Now.Hour.ToString().PadLeft(2,'0') + "_" + DateTime.Now.Minute.ToString().PadLeft(2,'0') + "_" + this.scriptName + "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: GenomeManagerWeightedPVO.cs --- /* QuantProject - Quantitative Finance Library GenomeManagerWeightedPVO.cs Copyright (C) 2003 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; using QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator; namespace QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator.WeightedPVO { /// <summary> /// Implements what needed to use the Genetic Optimizer /// for finding the portfolio that best suites /// the Portfolio Value Oscillator strategy /// </summary> [Serializable] public class GenomeManagerWeightedPVO : GenomeManagerForEfficientPortfolio { protected int minLevelForOversoldThreshold; protected int maxLevelForOversoldThreshold; protected int minLevelForOverboughtThreshold; protected int maxLevelForOverboughtThreshold; protected int divisorForThresholdComputation; protected bool symmetricalThresholds = false; protected bool overboughtMoreThanOversoldForFixedPortfolio = false; protected int numOfGenesDedicatedToThresholds; protected double currentOversoldThreshold = 0.0; protected double currentOverboughtThreshold = 0.0; protected int numDaysForOscillatingPeriod; protected int[] genePositionsPointingToTickers; protected double[] portfolioValues;//the values for each unit, invested //at the beginning of the optimization period, //throughout the period itself protected bool genePositionPointsToATicker(int genePosition) { return ( genePosition >= this.numOfGenesDedicatedToThresholds && ( (this.numOfGenesDedicatedToThresholds == 1 && genePosition%2 == 0) || (this.numOfGenesDedicatedToThresholds == 2 && genePosition%2 != 0) ) ); } protected bool genePositionPointsToAWeight(int genePosition) { return ( genePosition >= this.numOfGenesDedicatedToThresholds && ( (this.numOfGenesDedicatedToThresholds == 1 && genePosition%2 != 0) || (this.numOfGenesDedicatedToThresholds == 2 && genePosition%2 == 0) ) ); } protected bool genePositionPointsToATreshold(int genePosition) { return ( genePosition < this.numOfGenesDedicatedToThresholds ); } public int[] GetGenePositionsPointingToTickers(Genome genome) { int i = 0; for(int genePosition = this.numOfGenesDedicatedToThresholds; genePosition < genome.Size; genePosition++) { if(this.genePositionPointsToATicker(genePosition) ) { this.genePositionsPointingToTickers[i] = genePosition; i++; } } return this.genePositionsPointingToTickers; } private void genomeManagerWeightedPVO_checkParametersForThresholdsComputation() { if(this.maxLevelForOverboughtThreshold < this.minLevelForOverboughtThreshold || this.maxLevelForOversoldThreshold < this.minLevelForOversoldThreshold || this.divisorForThresholdComputation < this.maxLevelForOverboughtThreshold || this.divisorForThresholdComputation < this.maxLevelForOversoldThreshold || (this.symmetricalThresholds && (this.minLevelForOversoldThreshold != this.minLevelForOverboughtThreshold || this.maxLevelForOversoldThreshold != this.maxLevelForOverboughtThreshold) ) || (this.overboughtMoreThanOversoldForFixedPortfolio && (this.minLevelForOverboughtThreshold > Convert.ToInt32(Convert.ToDouble(this.minLevelForOversoldThreshold)* Convert.ToDouble(this.divisorForThresholdComputation) / (Convert.ToDouble(this.divisorForThresholdComputation) - Convert.ToDouble(this.minLevelForOversoldThreshold) ) ) || this.maxLevelForOverboughtThreshold < Convert.ToInt32(Convert.ToDouble(this.maxLevelForOversoldThreshold) * Convert.ToDouble(this.divisorForThresholdComputation) / (Convert.ToDouble(this.divisorForThresholdComputation) - Convert.ToDouble(this.maxLevelForOversoldThreshold) ) ) ) ) ) throw new Exception("Bad parameters for thresholds computation!"); } public GenomeManagerWeightedPVO(DataTable setOfInitialTickers, DateTime firstQuoteDate, DateTime lastQuoteDate, int numberOfTickersInPortfolio, int numDaysForOscillatingPeriod, int minLevelForOversoldThreshold, int maxLevelForOversoldThreshold, int minLevelForOverboughtThreshold, int maxLevelForOverboughtThreshold, int divisorForThresholdComputation, bool symmetricalThresholds, bool overboughtMoreThanOversoldForFixedPortfolio, PortfolioType inSamplePortfolioType) : base(setOfInitialTickers, firstQuoteDate, lastQuoteDate, numberOfTickersInPortfolio, 0.0, inSamplePortfolioType) { this.numDaysForOscillatingPeriod = numDaysForOscillatingPeriod; this.divisorForThresholdComputation = divisorForThresholdComputation; this.minLevelForOversoldThreshold = minLevelForOversoldThreshold; this.maxLevelForOversoldThreshold = maxLevelForOversoldThreshold; this.minLevelForOverboughtThreshold = minLevelForOverboughtThreshold; this.maxLevelForOverboughtThreshold = maxLevelForOverboughtThreshold; this.symmetricalThresholds = symmetricalThresholds; this.overboughtMoreThanOversoldForFixedPortfolio = overboughtMoreThanOversoldForFixedPortfolio; if(this.symmetricalThresholds)//value for thresholds must be unique numOfGenesDedicatedToThresholds = 1; else numOfGenesDedicatedToThresholds = 2; this.genePositionsPointingToTickers = new int[(this.GenomeSize - this.numOfGenesDedicatedToThresholds)/2]; this.genomeManagerWeightedPVO_checkParametersForThresholdsComputation(); this.retrieveData(); } public override int GenomeSize { get{return this.genomeSize * 2 + this.numOfGenesDedicatedToThresholds;} } #region Get Min and Max Value private int getMinValueForGenes_getMinValueForTicker() { 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 GetMinValueForGenes(int genePosition) { int returnValue; switch (genePosition) { case 0 ://gene for oversold threshold returnValue = this.minLevelForOversoldThreshold; break; case 1 ://gene for overbought threshold if thresholds are asymmetrical if(this.numOfGenesDedicatedToThresholds == 2) returnValue = this.minLevelForOverboughtThreshold; else returnValue = this.getMinValueForGenes_getMinValueForTicker(); break; default://gene for ticker or weight returnValue = this.getMinValueForGenes_getMinValueForTicker(); break; } return returnValue; } private int getMaxValueForGenes_getMaxValueForTicker() { int returnValue; switch (this.portfolioType) { case PortfolioType.OnlyShort : returnValue = - 1; break; default ://For ShortAndLong or OnlyLong portfolios returnValue = this.originalNumOfTickers - 1; break; } return returnValue; } public override int GetMaxValueForGenes(int genePosition) { int returnValue; switch (genePosition) { case 0 ://gene for oversold threshold returnValue = this.maxLevelForOversoldThreshold; break; case 1 ://gene for overbought threshold when thresholds are asymmetrical if(this.numOfGenesDedicatedToThresholds == 2) returnValue = this.maxLevelForOverboughtThreshold; else returnValue = this.getMaxValueForGenes_getMaxValueForTicker(); break; default://gene for ticker returnValue = this.getMaxValueForGenes_getMaxValueForTicker(); 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; } //starting from this.numDaysForOscillatingPeriod day, //it computes for each day ahead the value of the //portfolio opened numDaysForOscillatingPeriod days ago private double[] getPortfolioMovingValues() { double[] returnValue = new double[this.portfolioRatesOfReturn.Length]; double[] valuesInOscillatingPeriod = new double[this.numDaysForOscillatingPeriod]; valuesInOscillatingPeriod[0] = 1.0; for(int i = this.numDaysForOscillatingPeriod; i<returnValue.Length; i++) { for(int j = 1; j < this.numDaysForOscillatingPeriod; j++) valuesInOscillatingPeriod[j] = valuesInOscillatingPeriod[j - 1] + valuesInOscillatingPeriod[j - 1] * this.portfolioRatesOfReturn[i-this.numDaysForOscillatingPeriod+j]; returnValue[i-1] = valuesInOscillatingPeriod[this.numDaysForOscillatingPeriod -1]; } return returnValue; } private void getFitnessValue_setCurrentThresholds(Genome genome) { this.currentOversoldThreshold = Convert.ToDouble(genome.Genes()[0])/ Convert.ToDouble(this.divisorForThresholdComputation); if(this.symmetricalThresholds) this.currentOverboughtThreshold = this.currentOversoldThreshold; else this.currentOverboughtThreshold = Convert.ToDouble(genome.Genes()[1])/ Convert.ToDouble(this.divisorForThresholdComputation); } private int getFitnessValue_getDaysOnTheMarket(double[] equityLine) { int returnValue = 0; foreach(double equityReturn in equityLine) if(equityReturn != 0.0) //the applied strategy gets positions on the market returnValue++; return returnValue; } //fitness is a sharpe-ratio based indicator for the equity line resulting //from applying the strategy public override double GetFitnessValue(Genome genome) { double returnValue = -1.0; this.portfolioRatesOfReturn = this.getPortfolioRatesOfReturn(genome.Genes()); this.portfolioValues = this.getPortfolioMovingValues(); this.getFitnessValue_setCurrentThresholds(genome); double[] equityLine = this.getFitnessValue_getEquityLineRates(); double fitness = Double.NaN; if(this.getFitnessValue_getDaysOnTheMarket(equityLine) > equityLine.Length / 2) //if the genome represents a portfolio that stays on the market //at least half of the theoretical days fitness = AdvancedFunctions.GetSharpeRatio(equityLine); if(!double.IsNaN(fitness) && !double.IsInfinity(fitness)) returnValue = fitness; return returnValue; } private double[] getFitnessValue_getEquityLineRates() { double[] returnValue = new double[this.PortfolioRatesOfReturn.Length]; double coefficient = 0.0; for(int i = 0; i<this.PortfolioRatesOfReturn.Length - 1;i++) { if(this.portfolioValues[i] >= 1.0 + this.currentOverboughtThreshold) //portfolio is overbought coefficient = -1.0; else if(this.portfolioValues[i] <= 1.0 - this.currentOversoldThreshold && this.portfolioValues[i] > 0.0) //portfolio is oversold coefficient = 1.0; returnValue[i + 1] = coefficient * this.PortfolioRatesOfReturn[i + 1]; } return returnValue; } protected override double getTickerWeight(int[] genes, int tickerPositionInGenes) { int numOfGenesDedicatedToWeights = this.genePositionsPointingToTickers.Length; double minimumWeight = (1.0 - ConstantsProvider.AmountOfVariableWeightToBeAssignedToTickers)/ numOfGenesDedicatedToWeights; double totalOfValuesForWeightsInGenes = 0.0; for(int j = this.numOfGenesDedicatedToThresholds; j<genes.Length; j++) { if(this.numOfGenesDedicatedToThresholds == 2 && j%2==0) //ticker weight is contained in genes at even position when //thresholds are asymmetrical totalOfValuesForWeightsInGenes += Math.Abs(genes[j]) + 1.0; //0 has to be avoided ! else if (this.numOfGenesDedicatedToThresholds == 1 && j%2!=0) //ticker weight is contained in genes at odd position when //thresholds are symmetrical totalOfValuesForWeightsInGenes += Math.Abs(genes[j]) + 1.0; //0 has to be avoided ! } double freeWeight = (Math.Abs(genes[tickerPositionInGenes-1]) + 1.0)/totalOfValuesForWeightsInGenes; return minimumWeight + freeWeight * (1.0 - minimumWeight * numOfGenesDedicatedToWeights); } protected override double[] getPortfolioRatesOfReturn(int[] genes) { double[] returnValue = new double[this.numberOfExaminedReturns]; for(int i = 0; i<returnValue.Length; i++) { for(int genePosition=this.numOfGenesDedicatedToThresholds; genePosition<genes.Length; genePosition++)//the first numOfGenesDedicatedToThresholds are for thresholds { if( this.genePositionPointsToATicker(genePosition) ) returnValue[i] += this.getPortfolioRatesOfReturn_getRateOfTickerToBeAddedToTheArray(genes,genePosition,i); } } return returnValue; } public override object Decode(Genome genome) { string[] arrayOfTickers = new string[this.genePositionsPointingToTickers.Length]; double[] arrayOfTickerWeights = new double[this.genePositionsPointingToTickers.Length]; int geneForTicker; GenomeMeaningPVO meaning; int i = 0;//for the arrayOfTickers and the arrayOfWeights for(int genePosition = this.numOfGenesDedicatedToThresholds; genePosition < genome.Genes().Length; genePosition++) { if( this.genePositionPointsToATicker(genePosition) ) { geneForTicker = (int)genome.Genes().GetValue(genePosition); arrayOfTickers[i] = this.decode_getTickerCodeForLongOrShortTrade(geneForTicker); arrayOfTickerWeights[i] = this.getTickerWeight(genome.Genes(), genePosition); i++; } }// end of for cycle inside genome if(this.symmetricalThresholds) meaning = new GenomeMeaningPVO( arrayOfTickers, arrayOfTickerWeights, Convert.ToDouble(genome.Genes()[0])/Convert.ToDouble(this.divisorForThresholdComputation), Convert.ToDouble(genome.Genes()[0])/Convert.ToDouble(this.divisorForThresholdComputation), this.numDaysForOscillatingPeriod); else meaning = new GenomeMeaningPVO( arrayOfTickers, arrayOfTickerWeights, Convert.ToDouble(genome.Genes()[0])/Convert.ToDouble(this.divisorForThresholdComputation), Convert.ToDouble(genome.Genes()[1])/Convert.ToDouble(this.divisorForThresholdComputation), this.numDaysForOscillatingPeriod); return meaning; } public override Genome[] GetChilds(Genome parent1, Genome parent2) { //in this simple implementation //child have the tickers of one parent //and the thresholds of the other Genome[] childs = new Genome[2]; childs[0] = parent1.Clone(); childs[1] = parent2.Clone(); //exchange of genes coding thresholds if(this.symmetricalThresholds)//unique value for thresholds { childs[0].SetGeneValue(parent2.GetGeneValue(0),0); childs[1].SetGeneValue(parent1.GetGeneValue(0),0); } else//two different values for thresholds { childs[0].SetGeneValue(parent2.GetGeneValue(0),0); childs[1].SetGeneValue(parent1.GetGeneValue(0),0); childs[0].SetGeneValue(parent2.GetGeneValue(1),1); childs[1].SetGeneValue(parent1.GetGeneValue(1),1); } return childs; } private int getNewGeneValue_getGeneValue(Genome genome, int genePosition) { int returnValue; int minValueForGene = genome.GetMinValueForGenes(genePosition); int maxValueForGene = genome.GetMaxValueForGenes(genePosition); if(this.numOfGenesDedicatedToThresholds == 2 && this.overboughtMoreThanOversoldForFixedPortfolio && genePosition == 1) //genePosition points to overbought threshold, //dipendent from the oversold one such that the portfolio tends to be fix returnValue = Convert.ToInt32( Convert.ToDouble( genome.GetGeneValue(0) ) * Convert.ToDouble(this.divisorForThresholdComputation) / ( Convert.ToDouble(this.divisorForThresholdComputation) - Convert.ToDouble( genome.GetGeneValue(0) ) ) ); else returnValue = GenomeManagement.RandomGenerator.Next(minValueForGene, maxValueForGene + 1); return returnValue; } public override int GetNewGeneValue(Genome genome, int genePosition) { // in this implementation only new gene values pointing to tickers // must be different from the others already stored int returnValue = this.getNewGeneValue_getGeneValue(genome,genePosition); while( this.genePositionPointsToATicker(genePosition) && GenomeManipulator.IsTickerContainedInGenome(returnValue, genome, this.GetGenePositionsPointingToTickers(genome) ) ) //while in the given position has to be stored //a new gene pointing to a ticker and //the proposed returnValue points to a ticker //already stored in the given genome, at the given genePositionsPointingToTickers returnValue = this.getNewGeneValue_getGeneValue(genome,genePosition); return returnValue; } //OLD VERSION // public override void Mutate(Genome genome, double mutationRate) // { // // in this implementation only one gene is mutated // int genePositionToBeMutated = GenomeManagement.RandomGenerator.Next(genome.Size); // int minValueForGene = genome.GetMinValueForGenes(genePositionToBeMutated); // int maxValueForGene = genome.GetMaxValueForGenes(genePositionToBeMutated); // int newValueForGene = GenomeManagement.RandomGenerator.Next(minValueForGene, // maxValueForGene +1); // // if( this.genePositionPointsToATicker(genePositionToBeMutated) ) // { // while(GenomeManipulator.IsTickerContainedInGenome(newValueForGene, // genome, this.genePositionsPointingToTickers) ) // //while the proposed newValueForGene points to a ticker // //already stored in the given genome, at the given genePositionsPointingToTickers // newValueForGene = GenomeManagement.RandomGenerator.Next(minValueForGene, // maxValueForGene +1); // GenomeManagement.MutateOneGene(genome, mutationRate, // genePositionToBeMutated, newValueForGene); // } // else if( this.genePositionPointsToAWeight(genePositionToBeMutated) ) // { // double partOfGeneToSubtractOrAdd = 0.25; // int geneValue = Math.Abs(genome.GetGeneValue(genePositionToBeMutated)); // int subtractOrAdd = GenomeManagement.RandomGenerator.Next(2); // if(subtractOrAdd == 1)//subtract a part of the gene value from the gene value itself // newValueForGene = geneValue - Convert.ToInt32(partOfGeneToSubtractOrAdd*geneValue); // else // newValueForGene = Math.Min(genome.GetMaxValueForGenes(genePositionToBeMutated), // geneValue + Convert.ToInt32(partOfGeneToSubtractOrAdd*geneValue)); // // GenomeManagement.MutateOneGene(genome, mutationRate, // genePositionToBeMutated, newValueForGene); // } // else if ( this.numOfGenesDedicatedToThresholds == 2 && // this.overboughtMoreThanOversoldForFixedPortfolio && // genePositionToBeMutated == 0 ) // // genePositionToBeMutated points to the oversold threshold and the // //the overbought one is determined // { // if (GenomeManagement.RandomGenerator.Next(0,101) < (int)(mutationRate*100)) // { // genome.SetGeneValue(newValueForGene, genePositionToBeMutated); // genome.SetGeneValue(Convert.ToInt32(Convert.ToDouble(newValueForGene) * Convert.ToDouble(this.divisorForThresholdComputation) / // (Convert.ToDouble(this.divisorForThresholdComputation) - Convert.ToDouble(newValueForGene))), 1); // } // } // else if ( this.numOfGenesDedicatedToThresholds == 2 && // this.overboughtMoreThanOversoldForFixedPortfolio && // genePositionToBeMutated == 1 ) // // genePositionToBeMutated points to the overbought threshold and, as the // //the overbought one is determined, the oversold one depends from the overbought // { // if (GenomeManagement.RandomGenerator.Next(0,101) < (int)(mutationRate*100)) // { // genome.SetGeneValue(newValueForGene, genePositionToBeMutated); // genome.SetGeneValue(Convert.ToInt32(Convert.ToDouble(newValueForGene) * Convert.ToDouble(this.divisorForThresholdComputation) / // (Convert.ToDouble(this.divisorForThresholdComputation) + Convert.ToDouble(newValueForGene))), 0); // } // } // } private int mutate_MutateOnlyOneWeight_getNewWeight(Genome genome, int genePositionToBeMutated) { int returnValue; double partOfGeneToSubtractOrAdd = 0.25; int geneValue = Math.Abs( genome.GetGeneValue(genePositionToBeMutated) ); int subtractOrAdd = GenomeManagement.RandomGenerator.Next(2); if(subtractOrAdd == 1)//subtract a part of the gene value from the gene value itself returnValue = geneValue - Convert.ToInt32(partOfGeneToSubtractOrAdd*geneValue); else returnValue = Math.Min(genome.GetMaxValueForGenes(genePositionToBeMutated), geneValue + Convert.ToInt32(partOfGeneToSubtractOrAdd*geneValue)); return returnValue; } private void mutate_MutateOnlyOneWeight(Genome genome) { int genePositionToBeMutated = GenomeManagement.RandomGenerator.Next(genome.Size); while( this.genePositionPointsToAWeight(genePositionToBeMutated) == false ) //while the proposed genePositionToBeMutated doesn't point to a weight genePositionToBeMutated = GenomeManagement.RandomGenerator.Next(genome.Size); int newValueForGene = this.mutate_MutateOnlyOneWeight_getNewWeight(genome, genePositionToBeMutated); GenomeManagement.MutateOneGene(genome, genePositionToBeMutated, newValueForGene); } private void mutate_MutateAllGenes(Genome genome) { for(int genePositionToBeMutated = 0; genePositionToBeMutated < genome.Genes().Length; genePositionToBeMutated ++) { int newValueForGene = this.GetNewGeneValue(genome, genePositionToBeMutated); genome.SetGeneValue(newValueForGene, genePositionToBeMutated); } } public override void Mutate(Genome genome) { int mutateOnlyOneWeight = GenomeManagement.RandomGenerator.Next(2); if(mutateOnlyOneWeight == 1) this.mutate_MutateOnlyOneWeight(genome); else//mutate all genome's genes this.mutate_MutateAllGenes(genome); } } } |