[Quantproject-developers] QuantProject/b7_Scripts/TechnicalAnalysisTesting/Oscillators/FixedPeriodOs
Brought to you by:
glauco_1
Update of /cvsroot/quantproject/QuantProject/b7_Scripts/TechnicalAnalysisTesting/Oscillators/FixedPeriodOscillators In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv8867 Added Files: RunFPOscillatorCTC.cs GenomeManagerForFPOscillatorCTC.cs EndOfDayTimerHandlerFPOscillatorCTC.cs Log Message: Added FixedPeriodOscillator strategy, based on technical analysis concepts. --- NEW FILE: EndOfDayTimerHandlerFPOscillatorCTC.cs --- /* QuantProject - Quantitative Finance Library EndOfDayTimerHandlerFPOscillatorCTC.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.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; namespace QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedPeriodOscillators { /// <summary> /// Implements MarketOpenEventHandler and MarketCloseEventHandler /// These handlers contain the core strategy for the oscillator /// close to close strategy! /// </summary> [Serializable] public class EndOfDayTimerHandlerFPOscillatorCTC : EndOfDayTimerHandler { private int numDaysForReturnCalculation; private double maxAcceptableCloseToCloseDrawdown; private bool stopLossConditionReached; private double currentAccountValue; private double previousAccountValue; private int numDaysBetweenEachOptimization; private int numDaysElapsedSinceLastOptimization; private int daysCounterWithPositions; private int daysCounterWithRightPositions; private int daysCounterWithReversalPositions; private bool isReversalPeriodOn = false; // private bool isTheFirstClose = false; private DateTime lastCloseDate; private IGenomeManager iGenomeManager; public EndOfDayTimerHandlerFPOscillatorCTC(string tickerGroupID, int numberOfEligibleTickers, int numberOfTickersToBeChosen, int numDaysForOptimizationPeriod, Account account, int generationNumberForGeneticOptimizer, int populationSizeForGeneticOptimizer, string benchmark, int numDaysForReturnCalculation, PortfolioType portfolioType, double maxAcceptableCloseToCloseDrawdown): base(tickerGroupID, numberOfEligibleTickers, numberOfTickersToBeChosen, numDaysForOptimizationPeriod, account, generationNumberForGeneticOptimizer, populationSizeForGeneticOptimizer, benchmark, 0.0, portfolioType) { this.numDaysForReturnCalculation = numDaysForReturnCalculation; this.daysCounterWithRightPositions = 0; this.daysCounterWithReversalPositions = 0; this.isReversalPeriodOn = false; this.maxAcceptableCloseToCloseDrawdown = maxAcceptableCloseToCloseDrawdown; this.stopLossConditionReached = false; this.currentAccountValue = 0.0; this.previousAccountValue = 0.0; this.numDaysBetweenEachOptimization = 2* numDaysForReturnCalculation; this.numDaysBetweenEachOptimization = numDaysForReturnCalculation; } #region MarketCloseEventHandler protected void marketCloseEventHandler_updateStopLossCondition() { this.previousAccountValue = this.currentAccountValue; this.currentAccountValue = this.account.GetMarketValue(); if((this.currentAccountValue - this.previousAccountValue) /this.previousAccountValue < -this.maxAcceptableCloseToCloseDrawdown) { this.stopLossConditionReached = true; } else { this.stopLossConditionReached = false; } } private void marketCloseEventHandler_reverseSignOfTickers(string[] signedTickers) { for(int i = 0; i<signedTickers.Length; i++) if(signedTickers[i] != null) signedTickers[i] = SignedTicker.GetOppositeSignedTicker(signedTickers[i]); } private void marketCloseEventHandler_updateCounters(bool isTheFirstClose) { if(this.account.Portfolio.Count > 0 && isTheFirstClose == false) { if(this.isReversalPeriodOn) this.daysCounterWithReversalPositions++ ; else this.daysCounterWithRightPositions++ ; } } private bool marketCloseEventHandler_openPositionsIfTuned_isTuned(IndexBasedEndOfDayTimer timer) { bool returnValue = false; try { double gainForTheLastHalfPeriod; DateTime initialDateForHalfPeriod = (DateTime)timer.IndexQuotes.Rows[timer.CurrentDateArrayPosition - this.numDaysForReturnCalculation + 1]["quDate"]; DateTime finalDateForHalfPeriod = (DateTime)timer.IndexQuotes.Rows[timer.CurrentDateArrayPosition]["quDate"]; gainForTheLastHalfPeriod = SignedTicker.GetCloseToClosePortfolioReturn( this.chosenTickers, this.chosenTickersPortfolioWeights, initialDateForHalfPeriod,finalDateForHalfPeriod); if(gainForTheLastHalfPeriod < 0.0) //in the last periods the combination has lost, so //it should gain the next days returnValue = true; return returnValue; } catch(MissingQuotesException ex) { ex = ex; return returnValue; } } private void marketCloseEventHandler_openPositionsIfTuned(IndexBasedEndOfDayTimer timer) { if(this.marketCloseEventHandler_openPositionsIfTuned_isTuned(timer)) base.openPositions(); } private void marketCloseEventHandler_closePositions() { this.daysCounterWithPositions++; if(this.daysCounterWithPositions == this.numDaysForReturnCalculation || this.stopLossConditionReached) { //Close if halfPeriod has elapsed or stop loss condition reached base.closePositions(); this.daysCounterWithPositions = 0; } } public override void MarketCloseEventHandler( Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { this.marketCloseEventHandler_updateStopLossCondition(); if(this.account.Portfolio.Count == 0 && this.chosenTickers[0] != null) //portfolio is empty and tickers to buy have been chosen this.marketCloseEventHandler_openPositionsIfTuned((IndexBasedEndOfDayTimer)sender); else this.marketCloseEventHandler_closePositions(); //OLD IMPLEMENTATION: always on the market // //update isTheFirstClose and optimize after adding cash // //(this first optimization could be done also after market close) // if (this.account.Transactions.Count == 0) // { // this.isTheFirstClose = true; // this.marketCloseEventHandler_optimize(endOfDayTimingEventArgs.EndOfDayDateTime.DateTime); // } // else // { // this.isTheFirstClose = false; // } // this.marketCloseEventHandler_updateCounters(this.isTheFirstClose); // this.marketCloseEventHandler_updateStopLossCondition(); // // if(this.stopLossConditionReached) // { // this.orders.Clear(); // this.closePositions(); // this.daysCounterWithReversalPositions = 0; // this.daysCounterWithRightPositions = 0; // this.marketCloseEventHandler_optimize(this.lastCloseDate); // this.openPositions(); // } // else // { // if(this.account.Portfolio.Count == 0) // { // this.orders.Clear(); // this.openPositions(); // } // // if((this.isTheFirstClose == false && this.isReversalPeriodOn == false && // this.daysCounterWithRightPositions == this.numDaysForReturnCalculation)) // { // this.orders.Clear(); // this.closePositions(); // this.daysCounterWithRightPositions = 0; // this.marketCloseEventHandler_reverseSignOfTickers(this.chosenTickers); // this.openPositions(); // this.isReversalPeriodOn = true; // } // // if((this.isReversalPeriodOn == true && // this.daysCounterWithReversalPositions == this.numDaysForReturnCalculation)) // { // this.orders.Clear(); // this.closePositions(); // this.daysCounterWithReversalPositions = 0; // this.isReversalPeriodOn = false; // //code for only one optimization //// this.marketCloseEventHandler_reverseSignOfTickers(this.chosenTickers); //// this.openPositions(); // // // //normal strategy // this.marketCloseEventHandler_optimize(this.lastCloseDate); // this.openPositions(); // } // // } //END OF OLD IMPLEMENTATION } #endregion #region OneHourAfterMarketCloseEventHandler protected DataTable getSetOfTickersToBeOptimized(DateTime currentDate) { SelectorByGroup temporizedGroup = new SelectorByGroup(this.tickerGroupID, currentDate); SelectorByQuotationAtEachMarketDay quotedAtEachMarketFromTemporized = new SelectorByQuotationAtEachMarketDay(temporizedGroup.GetTableOfSelectedTickers(), false, currentDate.AddDays(-this.numDaysForOptimizationPeriod), currentDate, this.numberOfEligibleTickers, this.benchmark); // SelectorByCloseToCloseVolatility lessVolatile = new SelectorByCloseToCloseVolatility( // quotedAtEachMarketFromTemporized.GetTableOfSelectedTickers(),true, // currentDate.AddDays(-15), currentDate, // this.numberOfEligibleTickers); // // return lessVolatile.GetTableOfSelectedTickers(); return quotedAtEachMarketFromTemporized.GetTableOfSelectedTickers(); } protected virtual 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 { //double targetReturnForEachPeriodOfPortfolioLife = // Math.Pow(1.60,(double)(1.0/(360.0/this.numDaysOfPortfolioLife))) - 1.0; //the target has to be such that annual system return is minimum 50% //(with no commissions and bid-ask spreads) // IGenomeManager genManOscillatorCTC = // new GenomeManagerForEfficientCTCPortfolio(setOfTickersToBeOptimized, // currentDate.AddDays(-this.numDaysForOptimizationPeriod), // currentDate, this.numberOfTickersToBeChosen, // this.numDaysForReturnCalculation, 0.0, // this.portfolioType); this.iGenomeManager = new GenomeManagerForFPOscillatorCTC(setOfTickersToBeOptimized, currentDate.AddDays(-this.numDaysForOptimizationPeriod), currentDate, this.numberOfTickersToBeChosen, this.numDaysForReturnCalculation, this.portfolioType); GeneticOptimizer GO = new GeneticOptimizer(this.iGenomeManager, this.populationSizeForGeneticOptimizer, this.generationNumberForGeneticOptimizer, ConstantsProvider.SeedForRandomGenerator); if(setGenomeCounter) this.genomeCounter = new GenomeCounter(GO); GO.Run(false); this.addGenomeToBestGenomes(GO.BestGenome,((GenomeManagerForEfficientPortfolio)this.iGenomeManager).FirstQuoteDate, ((GenomeManagerForEfficientPortfolio)this.iGenomeManager).LastQuoteDate); this.chosenTickers = ((GenomeMeaning)GO.BestGenome.Meaning).Tickers; this.chosenTickersPortfolioWeights = ((GenomeMeaning)GO.BestGenome.Meaning).TickersPortfolioWeights; } //else it will be buyed again the previous optimized portfolio //that's it the actual chosenTickers member } /// <summary> /// Handles a "One hour after market close" event. /// </summary> /// <param name="sender"></param> /// <param name="eventArgs"></param> public override void OneHourAfterMarketCloseEventHandler( Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { this.lastCloseDate = endOfDayTimingEventArgs.EndOfDayDateTime.DateTime; ConstantsProvider.SeedForRandomGenerator++; this.numDaysElapsedSinceLastOptimization++; this.orders.Clear(); if((this.numDaysElapsedSinceLastOptimization - 1 == this.numDaysBetweenEachOptimization)) //|| this.isTheFirstClose ) //num days without optimization has elapsed or //it is the first close (OLD IMPLEMENTATION) { this.setTickers(endOfDayTimingEventArgs.EndOfDayDateTime.DateTime, false); //sets tickers to be chosen next Market Close event this.numDaysElapsedSinceLastOptimization = 0; } } #endregion } } --- NEW FILE: RunFPOscillatorCTC.cs --- /* QuantProject - Quantitative Finance Library RunFPOscillatorCTC.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.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.FixedPeriodOscillators { /// <summary> /// Script that implements an oscillating strategy, /// for all market days (fixed period), using efficient portfolios /// </summary> [Serializable] public class RunFPOscillatorCTC : RunEfficientPortfolio { private int numDaysForReturnCalculation; private double maxAcceptableCloseToCloseDrawdown; private int numDaysBetweenEachOptimization; public RunFPOscillatorCTC(string tickerGroupID, int numberOfEligibleTickers, int numberOfTickersToBeChosen, int numDaysForOptimizationPeriod, int generationNumberForGeneticOptimizer, int populationSizeForGeneticOptimizer, string benchmark, DateTime startDate, DateTime endDate, int numDaysForReturnCalculation, PortfolioType portfolioType, double maxAcceptableCloseToCloseDrawdown, double maxRunningHours): base(tickerGroupID, numberOfEligibleTickers, numberOfTickersToBeChosen, numDaysForOptimizationPeriod, generationNumberForGeneticOptimizer, populationSizeForGeneticOptimizer, benchmark, startDate, endDate, 0.0, portfolioType, maxRunningHours) { this.ScriptName = "FixedPeriodOscillatorCTCScriptWithSharpe"; this.numDaysForReturnCalculation = numDaysForReturnCalculation; this.maxAcceptableCloseToCloseDrawdown = maxAcceptableCloseToCloseDrawdown; this.numDaysBetweenEachOptimization = numDaysForReturnCalculation; } #region auxiliary overriden methods for Run protected override void run_initializeEndOfDayTimerHandler() { this.endOfDayTimerHandler = new EndOfDayTimerHandlerFPOscillatorCTC(this.tickerGroupID, this.numberOfEligibleTickers, this.numberOfTickersToBeChosen, this.numDaysForOptimizationPeriod, this.account, this.generationNumberForGeneticOptimizer, this.populationSizeForGeneticOptimizer, this.benchmark, this.numDaysForReturnCalculation, 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 = "From"+this.numberOfEligibleTickers + "OptDays" + this.numDaysForOptimizationPeriod + "Portfolio" + this.numberOfTickersToBeChosen + "GenNum" + this.generationNumberForGeneticOptimizer + "PopSize" + this.populationSizeForGeneticOptimizer + "HalfPeriodDays" + Convert.ToString(this.numDaysForReturnCalculation) + 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 + "\\"; //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.checkDateForReport_createDirIfNotPresent(dirNameWhereToSaveTransactions); // ObjectArchiver.Archive(this.account.Transactions, // dirNameWhereToSaveTransactions + // fileName + ".qPt"); // this.checkDateForReport_createDirIfNotPresent(dirNameWhereToSaveBestGenomes); OptimizationOutput optimizationOutput = new OptimizationOutput(); foreach(GenomeRepresentation genomeRepresentation in this.endOfDayTimerHandler.BestGenomes) optimizationOutput.Add(genomeRepresentation); ObjectArchiver.Archive(optimizationOutput, dirNameWhereToSaveBestGenomes + fileName + ".bgn"); this.endOfDayTimer.Stop(); } #endregion } } --- NEW FILE: GenomeManagerForFPOscillatorCTC.cs --- /* QuantProject - Quantitative Finance Library GenomeManagerForFPOscillatorCTC.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.Statistics; using QuantProject.ADT.Optimizing.Genetic; using QuantProject.Data; using QuantProject.Data.DataTables; using QuantProject.Scripts.TickerSelectionTesting.EfficientPortfolios; namespace QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedPeriodOscillators { /// <summary> /// Implements what needed to use the Genetic Optimizer /// for finding the portfolio that best suites /// the fixed period Oscillator strategy /// </summary> [Serializable] public class GenomeManagerForFPOscillatorCTC : GenomeManagerForEfficientPortfolio { private int numDaysForReturnCalculation; public GenomeManagerForFPOscillatorCTC(DataTable setOfInitialTickers, DateTime firstQuoteDate, DateTime lastQuoteDate, int numberOfTickersInPortfolio, int numDaysForReturnCalculation, PortfolioType portfolioType) : base(setOfInitialTickers, firstQuoteDate, lastQuoteDate, numberOfTickersInPortfolio, 0.0, portfolioType) { this.numDaysForReturnCalculation = numDaysForReturnCalculation; this.retrieveData(); } private float[] getArrayOfRatesOfReturn_getAdjustedArray(Quotes sourceQuotes, int numDaysForHalfPeriod, ref DateTime firstQuoteDate) { float[] returnValue = ExtendedDataTable.GetArrayOfFloatFromColumn(sourceQuotes, Quotes.AdjustedCloseToCloseRatio); for(int i = 0;i<returnValue.Length;i++) returnValue[i] = returnValue[i]-1; //in order to be alligned at the following market day, //the array has to be long n, where n is such that //n%(2 * hp) + 1 = 2 * hp (hp = half period) //if some rates are deleted, first quote day has to be updated while( (returnValue.Length + 1) % (2*numDaysForHalfPeriod) != 0) { float[] newReturnValue = new float[returnValue.Length - 1]; for(int k = 0;k<returnValue.Length - 1;k++) newReturnValue[k] = returnValue[k + 1]; returnValue = newReturnValue; firstQuoteDate = firstQuoteDate.AddDays(1); firstQuoteDate = sourceQuotes.GetQuoteDateOrFollowing(firstQuoteDate); } return returnValue; } protected override float[] getArrayOfRatesOfReturn(string ticker) { float[] returnValue = null; Quotes tickerQuotes = new Quotes(ticker, this.firstQuoteDate, this.lastQuoteDate); returnValue = this.getArrayOfRatesOfReturn_getAdjustedArray(tickerQuotes, this.numDaysForReturnCalculation, ref this.firstQuoteDate); this.numberOfExaminedReturns = returnValue.Length; return returnValue; } // //implementation with fitness as average of modified sh for single tickers // private double getFitnessValue_getModifiedSharpeRatioForTicker(int[] genes, // int tickerPositionInGenes) // { // bool longReturns = false; // if(genes[tickerPositionInGenes] > 0) // //genes[tickerPositionInGenes], the code for ticker, points to a ticker for which long returns are to be examined // longReturns = true; // int position = this.getPortfolioRatesOfReturn_getRateOfTickerToBeAddedToTheArray_getPositionInArray(genes[tickerPositionInGenes]); // this.setOfCandidates[position].LongRatesOfReturn = longReturns; // float[] arrayOfRatesOfReturn = this.setOfCandidates[position].ArrayOfRatesOfReturn; // float[] strategyReturns = new float[arrayOfRatesOfReturn.Length]; // float sign = 1.0F; // for(int i=0; i<arrayOfRatesOfReturn.Length; i++) // { // if(i > 0 && (i % this.numDaysForReturnCalculation == 0) ) // sign = -sign; // // strategyReturns[i] = sign * arrayOfRatesOfReturn[i]; // } // double stdDev = BasicFunctions.StdDev(strategyReturns); // double powerForStdDev = 2.0; // // return BasicFunctions.SimpleAverage(strategyReturns)/ // Math.Pow(stdDev, powerForStdDev); // } // //// new implementation: fitness is the averaged sum of the "modified" sharpeRatios //// for each single ticker // public override double GetFitnessValue(Genome genome) // { // double returnValue = 0.0; // for(int i = 0; i<genome.Size; i++) // { // returnValue += this.getFitnessValue_getModifiedSharpeRatioForTicker( genome.Genes(),i ); // } // return returnValue/genome.Size; // } 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); } GenomeMeaning meaning = new GenomeMeaning(arrayOfTickers); return meaning; } //OLD IMPLEMENTATION - linear combination public override double GetFitnessValue(Genome genome) { double returnValue = 0.0; this.portfolioRatesOfReturn = this.getPortfolioRatesOfReturn(genome.Genes()); double[] oscillatorPortfolioRatesOfReturn = this.getFitnessValue_getOscillatorRates(); double averageOscillatorPortfolioRateOfReturn = BasicFunctions.SimpleAverage(oscillatorPortfolioRatesOfReturn); double oscillatorPortfolioStdDev = BasicFunctions.StdDev(oscillatorPortfolioRatesOfReturn); returnValue = averageOscillatorPortfolioRateOfReturn / Math.Pow(oscillatorPortfolioStdDev,1.2); return returnValue; } private double[] getFitnessValue_getOscillatorRates() { double[] returnValue = new double[this.PortfolioRatesOfReturn.Length]; double sign = 1.0; for(int i = 0;i<this.PortfolioRatesOfReturn.Length; i++) { if(i > 0 && (i % this.numDaysForReturnCalculation == 0) ) sign = -sign; returnValue[i] = sign*this.PortfolioRatesOfReturn[i]; } return returnValue; } //new implementation: changed how fitness is computed //now it is the sharpe ratio for the equity line resulting //from applying the strategy // public override double GetFitnessValue(Genome genome) // { // double returnValue = 0.0; // this.portfolioRatesOfReturn = this.getPortfolioRatesOfReturn(genome.Genes()); // // double[] equityLine = this.getFitnessValue_getEquityLineRates(); // // double averageEquityLineRateOfReturn = // BasicFunctions.SimpleAverage(equityLine); // // double equityLineStdDev = // BasicFunctions.StdDev(equityLine); // // returnValue = averageEquityLineRateOfReturn / // Math.Pow(equityLineStdDev,2.0); // // return returnValue; // } // // private double[] getFitnessValue_getEquityLineRates() // { // double[] returnValue = new double[this.PortfolioRatesOfReturn.Length]; // double sign = 1.0; // for(int i = this.numDaysForReturnCalculation - 1; // i<this.PortfolioRatesOfReturn.Length; // i++) // { // // if gain of last half period is negative, // // then add to the array the returns of the second half // } // // return returnValue; // } } } |