[Quantproject-developers] QuantProject/b7_Scripts/TechnicalAnalysisTesting/Oscillators/ExtremeCounte
Brought to you by:
glauco_1
Update of /cvsroot/quantproject/QuantProject/b7_Scripts/TechnicalAnalysisTesting/Oscillators/ExtremeCounterTrend In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv10183 Added Files: RunExtremeCounterTrend.cs GenomeManagerECT.cs EndOfDayTimerHandlerECT.cs Log Message: Added ExtremeCounterTrend strategy --- NEW FILE: EndOfDayTimerHandlerECT.cs --- /* QuantProject - Quantitative Finance Library EndOfDayTimerHandlerECT.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.ExtremeCounterTrend { /// <summary> /// Implements MarketOpenEventHandler and MarketCloseEventHandler /// These handlers contain the core strategy for the extreme /// counter trend strategy! /// </summary> [Serializable] public class EndOfDayTimerHandlerECT : 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 EndOfDayTimerHandlerECT(string tickerGroupID, int numberOfEligibleTickers, int numberOfTickersToBeChosen, int numDaysForOptimizationPeriod, Account account, int generationNumberForGeneticOptimizer, int populationSizeForGeneticOptimizer, string benchmark, int numDaysForReturnCalculation, int numDaysBetweenEachOptimization, 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 = numDaysBetweenEachOptimization; } #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 double marketCloseEventHandler_openPositions_getLastHalfPeriodGain(IndexBasedEndOfDayTimer timer) { double returnValue = 999.0; try { DateTime initialDateForHalfPeriod = (DateTime)timer.IndexQuotes.Rows[timer.CurrentDateArrayPosition - this.numDaysForReturnCalculation + 1]["quDate"]; DateTime finalDateForHalfPeriod = (DateTime)timer.IndexQuotes.Rows[timer.CurrentDateArrayPosition]["quDate"]; returnValue = SignedTicker.GetCloseToClosePortfolioReturn( this.chosenTickers, this.chosenTickersPortfolioWeights, initialDateForHalfPeriod,finalDateForHalfPeriod); } catch(MissingQuotesException ex) { ex = ex; } return returnValue; } private void marketCloseEventHandler_openPositions(IndexBasedEndOfDayTimer timer) { double lastHalfPeriodGain = this.marketCloseEventHandler_openPositions_getLastHalfPeriodGain(timer); if(lastHalfPeriodGain != 999.0) //last half period gain has been properly computed { if(lastHalfPeriodGain < 0.0) base.openPositions(); else { SignedTicker.ChangeSignOfEachTicker(this.chosenTickers); //short the portfolio try{ base.openPositions(); } catch(Exception ex){ ex = ex; } finally{SignedTicker.ChangeSignOfEachTicker(this.chosenTickers);} } } } 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(); this.marketCloseEventHandler_closePositions(); if(this.chosenTickers[0] != null) //tickers to buy have been chosen { if(this.account.Portfolio.Count == 0) this.marketCloseEventHandler_openPositions((IndexBasedEndOfDayTimer)sender); } } #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); 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 { this.iGenomeManager = new GenomeManagerECT(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: GenomeManagerECT.cs --- /* QuantProject - Quantitative Finance Library GenomeManagerECT.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.ExtremeCounterTrend { /// <summary> /// Implements what needed to use the Genetic Optimizer /// for finding the portfolio that best suites /// the extreme counter trend strategy /// </summary> [Serializable] public class GenomeManagerECT : GenomeManagerForEfficientPortfolio { private int numDaysForReturnCalculation; public GenomeManagerECT(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(); } protected override float[] getArrayOfRatesOfReturn(string ticker) { float[] returnValue = null; Quotes tickerQuotes = new Quotes(ticker, this.firstQuoteDate, this.lastQuoteDate); returnValue = 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; } 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; } //fitness is a sharpe-ratio based indicator for the equity line resulting //from applying the strategy public override double GetFitnessValue(Genome genome) { this.portfolioRatesOfReturn = this.getPortfolioRatesOfReturn(genome.Genes()); double[] equityLine = this.getFitnessValue_getEquityLineRates(); double sharpeRatioAll = BasicFunctions.SimpleAverage(equityLine)/ BasicFunctions.StdDev(equityLine); // double[] equityLineSecondHalf = new double[equityLine.Length/2]; // for(int i = 0; i<equityLine.Length/2; i++) // equityLineSecondHalf[i] = equityLine[i+equityLine.Length/2]; // double sharpeRatioSecondHalf = BasicFunctions.SimpleAverage(equityLineSecondHalf)/ // Math.Pow(BasicFunctions.StdDev(equityLineSecondHalf),1.2); return sharpeRatioAll;//*sharpeRatioSecondHalf; } private double[] getFitnessValue_getEquityLineRates() { double[] returnValue = new double[this.PortfolioRatesOfReturn.Length]; double gainForTheLastHalfPeriod = 0.0; for(int i = this.numDaysForReturnCalculation - 1; i<this.PortfolioRatesOfReturn.Length - this.numDaysForReturnCalculation; i += this.numDaysForReturnCalculation) { gainForTheLastHalfPeriod = 0.0; for(int j=this.numDaysForReturnCalculation - 1; j > -1; j--) { gainForTheLastHalfPeriod = (1.0+gainForTheLastHalfPeriod) * this.PortfolioRatesOfReturn[i-j]; } for(int t=1;t<this.numDaysForReturnCalculation + 1;t++) { if(gainForTheLastHalfPeriod<0.0) // if gain of first half period is negative returnValue[i+t] = this.PortfolioRatesOfReturn[i+t]; else returnValue[i+t] = - this.PortfolioRatesOfReturn[i+t]; } } return returnValue; } } } --- NEW FILE: RunExtremeCounterTrend.cs --- /* QuantProject - Quantitative Finance Library RunExtremeCounterTrend.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.ExtremeCounterTrend { /// <summary> /// Script that implements an oscillating strategy, /// for finding tickers that tend to /// earn (lose) from previous losses (gains), using efficient portfolios /// </summary> [Serializable] public class RunExtremeCounterTrend : RunEfficientPortfolio { private int numDaysForReturnCalculation; private double maxAcceptableCloseToCloseDrawdown; private int numDaysBetweenEachOptimization; public RunExtremeCounterTrend(string tickerGroupID, int numberOfEligibleTickers, int numberOfTickersToBeChosen, int numDaysForOptimizationPeriod, int generationNumberForGeneticOptimizer, int populationSizeForGeneticOptimizer, string benchmark, DateTime startDate, DateTime endDate, int numDaysForReturnCalculation, int numDaysBetweenEachOptimization, PortfolioType portfolioType, double maxAcceptableCloseToCloseDrawdown, double maxRunningHours): base(tickerGroupID, numberOfEligibleTickers, numberOfTickersToBeChosen, numDaysForOptimizationPeriod, generationNumberForGeneticOptimizer, populationSizeForGeneticOptimizer, benchmark, startDate, endDate, 0.0, portfolioType, maxRunningHours) { this.ScriptName = "ExtremeCounterTrendScriptWithSharpe"; this.numDaysForReturnCalculation = numDaysForReturnCalculation; this.maxAcceptableCloseToCloseDrawdown = maxAcceptableCloseToCloseDrawdown; this.numDaysBetweenEachOptimization = numDaysBetweenEachOptimization; } #region auxiliary overriden methods for Run protected override void run_initializeEndOfDayTimerHandler() { this.endOfDayTimerHandler = new EndOfDayTimerHandlerECT(this.tickerGroupID, this.numberOfEligibleTickers, this.numberOfTickersToBeChosen, this.numDaysForOptimizationPeriod, this.account, this.generationNumberForGeneticOptimizer, this.populationSizeForGeneticOptimizer, this.benchmark, this.numDaysForReturnCalculation, 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 = "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 } } |