[Quantproject-developers] QuantProject/b7_Scripts/TickerSelectionTesting EndOfDayTimerHandlerLastCho
Brought to you by:
glauco_1
Update of /cvsroot/quantproject/QuantProject/b7_Scripts/TickerSelectionTesting In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16221/b7_Scripts/TickerSelectionTesting Modified Files: EndOfDayTimerHandler.cs EndOfDayTimerHandlerCTC.cs EndOfDayTimerHandlerCTO.cs EndOfDayTimerHandlerCTOTest.cs GenomeManagerForEfficientCTCPortfolio.cs GenomeManagerForEfficientCTOPortfolio.cs GenomeManagerForEfficientPortfolio.cs RunEfficientCTCPortfolio.cs RunEfficientCTOPortfolio.cs RunEfficientPortfolio.cs RunTestOptimizedCTCPortfolio.cs RunTestOptimizedCTOPortfolio.cs Added Files: EndOfDayTimerHandlerLastChosenPortfolio.cs RunLastChosenPortfolioOutOfSample.cs Log Message: Updated files for the EfficientPortfolio script: - new classes for testing a given array of tickers (normally, for testing out of sample an optimization's result); - reorganized code in a more object oriented way (now code duplication has been completely erased); - now, the optimization process for the shortAndLong portfolio should be more efficient (memory is now used properly) Index: RunTestOptimizedCTOPortfolio.cs =================================================================== RCS file: /cvsroot/quantproject/QuantProject/b7_Scripts/TickerSelectionTesting/RunTestOptimizedCTOPortfolio.cs,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** RunTestOptimizedCTOPortfolio.cs 2 Jun 2005 18:00:47 -0000 1.2 --- RunTestOptimizedCTOPortfolio.cs 24 Jun 2005 22:52:25 -0000 1.3 *************** *** 52,56 **** public class RunTestOptimizedCTOPorfolio : RunEfficientCTOPorfolio { ! public RunTestOptimizedCTOPorfolio(string tickerGroupID, int numberOfEligibleTickers, int numberOfTickersToBeChosen, int numDaysForLiquidity, --- 52,56 ---- public class RunTestOptimizedCTOPorfolio : RunEfficientCTOPorfolio { ! public RunTestOptimizedCTOPorfolio(string tickerGroupID, int numberOfEligibleTickers, int numberOfTickersToBeChosen, int numDaysForLiquidity, *************** *** 58,62 **** int populationSizeForGeneticOptimizer, string benchmark, DateTime startDate, DateTime endDate, double targetReturn, ! PortfolioType portfolioType, double maxRunningHours): base(tickerGroupID, numberOfEligibleTickers, numberOfTickersToBeChosen, numDaysForLiquidity, --- 58,63 ---- int populationSizeForGeneticOptimizer, string benchmark, DateTime startDate, DateTime endDate, double targetReturn, ! PortfolioType portfolioType, double maxRunningHours, ! int numDaysBetweenEachOptimization): base(tickerGroupID, numberOfEligibleTickers, numberOfTickersToBeChosen, numDaysForLiquidity, *************** *** 64,71 **** populationSizeForGeneticOptimizer, benchmark, startDate, endDate, targetReturn, ! portfolioType, maxRunningHours) { this.ScriptName = "TestOptimizedCTOPortfolio"; ! } protected override void run_initializeEndOfDayTimerHandler() --- 65,73 ---- populationSizeForGeneticOptimizer, benchmark, startDate, endDate, targetReturn, ! portfolioType, maxRunningHours, ! numDaysBetweenEachOptimization) { this.ScriptName = "TestOptimizedCTOPortfolio"; ! } protected override void run_initializeEndOfDayTimerHandler() *************** *** 80,84 **** this.benchmark, this.targetReturn, ! this.portfolioType); } --- 82,87 ---- this.benchmark, this.targetReturn, ! this.portfolioType, ! this.numDaysBetweenEachOptimization); } *************** *** 88,92 **** --- 91,117 ---- base.Run(); ((EndOfDayTimerHandlerCTOTest)this.endOfDayTimerHandler).Reset(); + + Report report = new Report( this.account , this.historicalQuoteProvider ); + report.Create( "Test optimization of OpenClose efficient portfolio", 1 , + new EndOfDayDateTime( this.endDateTime.DateTime , + EndOfDaySpecificTime.MarketClose ) , + "^SPX" ); + report.Show(); } + + protected override void checkDateForReport(Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs) + { + if(endOfDayTimingEventArgs.EndOfDayDateTime.DateTime>=this.endDateTime.DateTime || + DateTime.Now >= this.startingTimeForScript.AddHours(this.maxRunningHours)) + //last date is reached by the timer or maxRunning hours + //are elapsed from the time script started + { + this.endOfDayTimer.Stop(); + } + + } + + + } Index: GenomeManagerForEfficientCTOPortfolio.cs =================================================================== RCS file: /cvsroot/quantproject/QuantProject/b7_Scripts/TickerSelectionTesting/GenomeManagerForEfficientCTOPortfolio.cs,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** GenomeManagerForEfficientCTOPortfolio.cs 2 Jun 2005 18:00:47 -0000 1.9 --- GenomeManagerForEfficientCTOPortfolio.cs 24 Jun 2005 22:52:25 -0000 1.10 *************** *** 98,102 **** return returnValue; } ! protected override double getFitnessValue_calculate() { --- 98,102 ---- return returnValue; } ! /* protected override double getFitnessValue_calculate() { *************** *** 104,112 **** double a, b, c; ! a = 0.002; b = 2.0; c = 3.0; ! returnValue = Math.Pow((a/this.Variance),b) * ! Math.Pow((this.rateOfReturn - this.targetPerformance), c); if(this.portfolioType == PortfolioType.OnlyShort) returnValue = - returnValue; --- 104,121 ---- double a, b, c; ! a = 0.002; b = 2.0; c = 2.0; ! //returnValue = Math.Pow((a/this.Variance),b) * ! // Math.Pow((this.rateOfReturn - this.targetPerformance), ! // c); ! //this.lowerPartialMoment = AdvancedFunctions.LowerPartialMoment(this.portfolioRatesOfReturn, ! // BasicFunctions.SimpleAverage(this.portfolioRatesOfReturn), ! // 3.0); ! this.lowerPartialMoment = AdvancedFunctions.NegativeSemiVariance(this.portfolioRatesOfReturn); ! a = 1.0; ! returnValue = Math.Pow((a/this.lowerPartialMoment),b) * ! Math.Pow(Math.Max(0.0,(this.rateOfReturn - this.targetPerformance)), c); + if(this.portfolioType == PortfolioType.OnlyShort) returnValue = - returnValue; *************** *** 117,121 **** return returnValue; } ! } --- 126,130 ---- return returnValue; } ! */ } Index: RunEfficientCTCPortfolio.cs =================================================================== RCS file: /cvsroot/quantproject/QuantProject/b7_Scripts/TickerSelectionTesting/RunEfficientCTCPortfolio.cs,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** RunEfficientCTCPortfolio.cs 2 Jun 2005 18:00:47 -0000 1.7 --- RunEfficientCTCPortfolio.cs 24 Jun 2005 22:52:25 -0000 1.8 *************** *** 84,89 **** this.maxAcceptableCloseToCloseDrawdown = maxAcceptableCloseToCloseDrawdown; } ! #region Run ! protected override void run_initializeEndOfDayTimerHandler() --- 84,89 ---- this.maxAcceptableCloseToCloseDrawdown = maxAcceptableCloseToCloseDrawdown; } ! ! #region auxiliary overriden methods for Run protected override void run_initializeEndOfDayTimerHandler() *************** *** 104,117 **** } ! public override void Run() { - //old script - //this.run_FindBestPortfolioForNextTrade(); - run_initializeHistoricalQuoteProvider(); - run_initializeEndOfDayTimer(); - run_initializeAccount(); - run_initializeEndOfDayTimerHandler(); - - //run_initializeProgressHandlers(); this.endOfDayTimer.MarketOpen += new MarketOpenEventHandler( --- 104,109 ---- } ! protected override void run_addEventHandlers() { this.endOfDayTimer.MarketOpen += new MarketOpenEventHandler( *************** *** 125,140 **** new MarketCloseEventHandler( this.checkDateForReport); - - //this.endOfDayTimer.OneHourAfterMarketClose += - //new OneHourAfterMarketCloseEventHandler( - //this.endOfDayTimerHandler.OneHourAfterMarketCloseEventHandler ); - //this.endOfDayTimer.OneHourAfterMarketClose += - //new OneHourAfterMarketCloseEventHandler( - //this.oneHourAfterMarketCloseEventHandler ); - - //this.progressBarForm.Show(); - this.endOfDayTimer.Start(); - } #endregion } --- 117,123 ---- new MarketCloseEventHandler( this.checkDateForReport); } + + #endregion } Index: RunTestOptimizedCTCPortfolio.cs =================================================================== RCS file: /cvsroot/quantproject/QuantProject/b7_Scripts/TickerSelectionTesting/RunTestOptimizedCTCPortfolio.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** RunTestOptimizedCTCPortfolio.cs 2 Jun 2005 18:00:47 -0000 1.1 --- RunTestOptimizedCTCPortfolio.cs 24 Jun 2005 22:52:25 -0000 1.2 *************** *** 101,104 **** --- 101,122 ---- base.Run(); ((EndOfDayTimerHandlerCTCTest)this.endOfDayTimerHandler).Reset(); + Report report = new Report( this.account , this.historicalQuoteProvider ); + report.Create( "Test optimization of Close to close efficient portfolio", 1 , + new EndOfDayDateTime( this.endDateTime.DateTime , + EndOfDaySpecificTime.MarketClose ) , + "^SPX" ); + report.Show(); + } + + protected override void checkDateForReport(Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs) + { + if(endOfDayTimingEventArgs.EndOfDayDateTime.DateTime>=this.endDateTime.DateTime || + DateTime.Now >= this.startingTimeForScript.AddHours(this.maxRunningHours)) + //last date is reached by the timer or maxRunning hours + //are elapsed from the time script started + { + this.endOfDayTimer.Stop(); + } + } Index: GenomeManagerForEfficientCTCPortfolio.cs =================================================================== RCS file: /cvsroot/quantproject/QuantProject/b7_Scripts/TickerSelectionTesting/GenomeManagerForEfficientCTCPortfolio.cs,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** GenomeManagerForEfficientCTCPortfolio.cs 2 Jun 2005 18:00:47 -0000 1.4 --- GenomeManagerForEfficientCTCPortfolio.cs 24 Jun 2005 22:52:25 -0000 1.5 *************** *** 98,102 **** return ratesOfReturns; } ! } --- 98,130 ---- return ratesOfReturns; } ! /* ! protected override double getFitnessValue_calculate() ! { ! double returnValue = 0; ! ! double a, b, c; ! a = 0.002; b = 2.0; c = 2.0; ! ! //returnValue = Math.Pow((a/this.Variance),b) * ! // Math.Pow((this.rateOfReturn - this.targetPerformance), ! // c); ! //this.lowerPartialMoment = AdvancedFunctions.LowerPartialMoment(this.portfolioRatesOfReturn, ! // BasicFunctions.SimpleAverage(this.portfolioRatesOfReturn), ! // 3.0); ! this.lowerPartialMoment = AdvancedFunctions.NegativeSemiVariance(this.portfolioRatesOfReturn); ! a = 1.0; ! returnValue = Math.Pow((a/this.lowerPartialMoment),b) * ! Math.Pow((this.rateOfReturn - this.targetPerformance), ! c); ! ! if(this.portfolioType == PortfolioType.OnlyShort) ! returnValue = - returnValue; ! ! if(Double.IsInfinity(returnValue) || Double.IsNaN(returnValue)) ! throw new Exception("Fitness value not computed correctly!"); ! ! return returnValue; ! } ! */ } --- NEW FILE: EndOfDayTimerHandlerLastChosenPortfolio.cs --- /* QuantProject - Quantitative Finance Library EndOfDayTimerHandlerLastChosenPortfolio.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.Data.DataProviders; using QuantProject.Data.Selectors; namespace QuantProject.Scripts.TickerSelectionTesting.EfficientPortfolios { /// <summary> /// Implements MarketOpenEventHandler, /// MarketCloseEventHandler /// These handlers simply open positions - /// for the given chosen tickers - at MarketOpen and close them /// at MarketClose /// </summary> [Serializable] public class EndOfDayTimerHandlerLastChosenPortfolio : EndOfDayTimerHandler { private EndOfDayDateTime firstDate; private EndOfDayDateTime lastDate; public EndOfDayTimerHandlerLastChosenPortfolio(string[] chosenTickers, PortfolioType portfolioType, Account account, string benchmark, EndOfDayDateTime firstDate, EndOfDayDateTime lastDate): base(chosenTickers, portfolioType, account, benchmark) { this.firstDate = firstDate; this.lastDate = lastDate; } /// <summary> /// Handles a "Market Open" event. /// </summary> /// <param name="sender"></param> /// <param name="eventArgs"></param> public override void MarketOpenEventHandler( Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { if(endOfDayTimingEventArgs.EndOfDayDateTime.CompareTo(this.firstDate) == 0) { this.openPositions(); } } public override void MarketCloseEventHandler( Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { //if(endOfDayTimingEventArgs.EndOfDayDateTime.CompareTo(this.lastDate) == 0) // this.closePositions(); if(endOfDayTimingEventArgs.EndOfDayDateTime.DateTime.CompareTo(this.firstDate.DateTime) == 0) this.closePositions(); } } } --- NEW FILE: RunLastChosenPortfolioOutOfSample.cs --- /* QuantProject - Quantitative Finance Library RunLastChosenPortfolioOutOfSample.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.IO; using System.Collections; using System.Data; using System.Windows.Forms; using QuantProject.ADT; using QuantProject.ADT.Optimizing.Genetic; using QuantProject.ADT.FileManaging; 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.Business.Financial.Accounting.Commissions; using QuantProject.Data.DataProviders; using QuantProject.Data.Selectors; using QuantProject.Scripts.TickerSelectionTesting.EfficientPortfolios; using QuantProject.Presentation.Reporting.WindowsForm; namespace QuantProject.Scripts.TickerSelectionTesting.EfficientPortfolios { /// <summary> /// Class for running a test based on last chosen tickers of a given /// RunEfficientPortfolio - normally, one with optimization purposes - /// , after it has been executed /// </summary> [Serializable] public class RunLastChosenPortfolioOutOfSample : RunEfficientPorfolio { RunEfficientPorfolio testEfficientPortfolio; public RunLastChosenPortfolioOutOfSample(RunEfficientPorfolio testEfficientPortfolio, string benchmark, DateTime startDate, DateTime endDate, double maxRunningHours): base(benchmark, startDate, endDate, testEfficientPortfolio.TypeOfPortfolio, maxRunningHours) { this.startDateTime = new EndOfDayDateTime( startDate, EndOfDaySpecificTime.MarketOpen ); this.endDateTime = new EndOfDayDateTime( endDate, EndOfDaySpecificTime.MarketClose ); this.ScriptName = "LastChosenPortfolioOutOfSample"; this.testEfficientPortfolio = testEfficientPortfolio; } #region Run protected override void run_initializeEndOfDayTimerHandler() { this.endOfDayTimerHandler = new EndOfDayTimerHandlerLastChosenPortfolio(this.testEfficientPortfolio.LastChosenTickers, this.testEfficientPortfolio.TypeOfPortfolio, this.account, this.benchmark, this.startDateTime, this.endDateTime); } protected override void run_initializeEndOfDayTimer() { this.endOfDayTimer = new HistoricalEndOfDayTimer(this.startDateTime); } protected override void run_initializeHistoricalQuoteProvider() { this.historicalQuoteProvider = this.testEfficientPortfolio.HistoricalQuoteProvider; } protected override void run_initializeAccount() { //default account with no commissions this.account = new Account( this.scriptName , this.endOfDayTimer , new HistoricalEndOfDayDataStreamer( this.endOfDayTimer , this.historicalQuoteProvider ) , new HistoricalEndOfDayOrderExecutor( this.endOfDayTimer , this.historicalQuoteProvider )); } protected override void run_addEventHandlers() { this.endOfDayTimer.MarketOpen += new MarketOpenEventHandler( this.endOfDayTimerHandler.MarketOpenEventHandler); 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 Run() { base.Run(); Report report = new Report( this.account , this.historicalQuoteProvider ); report.Create( "Run last chosen tickers out of sample", 1 , new EndOfDayDateTime( this.endDateTime.DateTime , EndOfDaySpecificTime.MarketClose ) , "^SPX" ); report.Show(); } protected override void checkDateForReport(Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs) { if(endOfDayTimingEventArgs.EndOfDayDateTime.DateTime>=this.endDateTime.DateTime || DateTime.Now >= this.startingTimeForScript.AddHours(this.maxRunningHours)) //last date is reached by the timer or maxRunning hours //are elapsed from the time script started { this.endOfDayTimer.Stop(); } } #endregion } } Index: EndOfDayTimerHandler.cs =================================================================== RCS file: /cvsroot/quantproject/QuantProject/b7_Scripts/TickerSelectionTesting/EndOfDayTimerHandler.cs,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** EndOfDayTimerHandler.cs 26 Apr 2005 19:02:11 -0000 1.12 --- EndOfDayTimerHandler.cs 24 Jun 2005 22:52:25 -0000 1.13 *************** *** 67,71 **** protected PortfolioType portfolioType; ! public int NumberOfEligibleTickers { --- 67,74 ---- protected PortfolioType portfolioType; ! public string[] LastChosenTickers ! { ! get { return this.chosenTickers; } ! } public int NumberOfEligibleTickers { *************** *** 100,103 **** --- 103,121 ---- } + public EndOfDayTimerHandler(string[] chosenTickers, + PortfolioType portfolioType, + Account account, + string benchmark) + { + + this.account = account; + this.benchmark = benchmark; + this.orders = new ArrayList(); + this.chosenTickers = chosenTickers; + this.numberOfTickersToBeChosen = chosenTickers.Length; + this.lastChosenTickers = new string[chosenTickers.Length]; + this.portfolioType = portfolioType; + } + protected virtual void addOrderForTicker(string ticker ) { *************** *** 118,121 **** --- 136,190 ---- } + protected virtual void closePosition( + string ticker ) + { + this.account.ClosePosition( ticker ); + } + + protected virtual void closePositions() + { + if(this.lastChosenTickers != null) + { + foreach( string ticker in this.lastChosenTickers) + { + for(int i = 0; i<this.account.Portfolio.Keys.Count; i++) + { + if(this.account.Portfolio[ticker]!=null) + closePosition( ticker ); + } + } + } + } + + protected virtual void addChosenTickersToOrderList() + { + int idx = 0; + foreach ( string ticker in this.chosenTickers ) + { + if(ticker != null) + { + this.addOrderForTicker( ticker ); + this.lastChosenTickers[idx] = + GenomeManagerForEfficientPortfolio.GetCleanTickerCode(ticker); + } + idx++; + } + } + protected virtual void openPositions() + { + //add cash first + if(this.orders.Count == 0 && this.account.Transactions.Count == 0) + this.account.AddCash(17000); + + this.addChosenTickersToOrderList(); + + //execute orders actually + foreach(object item in this.orders) + { + this.account.AddOrder((Order)item); + } + } + + public virtual void MarketOpenEventHandler( Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) Index: EndOfDayTimerHandlerCTOTest.cs =================================================================== RCS file: /cvsroot/quantproject/QuantProject/b7_Scripts/TickerSelectionTesting/EndOfDayTimerHandlerCTOTest.cs,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** EndOfDayTimerHandlerCTOTest.cs 2 Jun 2005 18:00:47 -0000 1.3 --- EndOfDayTimerHandlerCTOTest.cs 24 Jun 2005 22:52:25 -0000 1.4 *************** *** 50,54 **** int populationSizeForGeneticOptimizer, string benchmark, double targetReturn, ! PortfolioType portfolioType): base(tickerGroupID, numberOfEligibleTickers, numberOfTickersToBeChosen, numDaysForLiquidity, account, --- 50,54 ---- int populationSizeForGeneticOptimizer, string benchmark, double targetReturn, ! PortfolioType portfolioType, int numDaysBetweenEachOptimization): base(tickerGroupID, numberOfEligibleTickers, numberOfTickersToBeChosen, numDaysForLiquidity, account, *************** *** 56,60 **** populationSizeForGeneticOptimizer, benchmark, targetReturn, ! portfolioType) { --- 56,60 ---- populationSizeForGeneticOptimizer, benchmark, targetReturn, ! portfolioType, numDaysBetweenEachOptimization) { Index: RunEfficientPortfolio.cs =================================================================== RCS file: /cvsroot/quantproject/QuantProject/b7_Scripts/TickerSelectionTesting/RunEfficientPortfolio.cs,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** RunEfficientPortfolio.cs 2 Jun 2005 18:00:47 -0000 1.8 --- RunEfficientPortfolio.cs 24 Jun 2005 22:52:25 -0000 1.9 *************** *** 87,91 **** //if MaxNumberOfHoursForScript has elapsed and the script //is still running, it will be stopped. ! public virtual string ScriptName { --- 87,104 ---- //if MaxNumberOfHoursForScript has elapsed and the script //is still running, it will be stopped. ! ! public string[] LastChosenTickers ! { ! get { return this.endOfDayTimerHandler.LastChosenTickers; } ! } ! public PortfolioType TypeOfPortfolio ! { ! get { return this.portfolioType; } ! } ! ! public IHistoricalQuoteProvider HistoricalQuoteProvider ! { ! get { return this.historicalQuoteProvider; } ! } public virtual string ScriptName { *************** *** 99,103 **** } ! public RunEfficientPorfolio(string tickerGroupID, int numberOfEligibleTickers, int numberOfTickersToBeChosen, int numDaysForLiquidity, int generationNumberForGeneticOptimizer, --- 112,134 ---- } ! public RunEfficientPorfolio(string benchmark, ! DateTime startDate, DateTime endDate, ! PortfolioType portfolioType, ! double maxRunningHours) ! { ! ! this.startDateTime = new EndOfDayDateTime( ! startDate, EndOfDaySpecificTime.FiveMinutesBeforeMarketClose ); ! this.endDateTime = new EndOfDayDateTime( ! endDate, EndOfDaySpecificTime.OneHourAfterMarketClose ); ! this.benchmark = benchmark; ! this.ScriptName = "EfficientGeneric"; ! this.portfolioType = portfolioType; ! this.startingTimeForScript = DateTime.Now; ! this.maxRunningHours = maxRunningHours; ! //this.numIntervalDays = 3; ! } ! ! public RunEfficientPorfolio(string tickerGroupID, int numberOfEligibleTickers, int numberOfTickersToBeChosen, int numDaysForLiquidity, int generationNumberForGeneticOptimizer, *************** *** 129,133 **** } #region Run ! protected virtual void run_initializeEndOfDayTimer() { --- 160,164 ---- } #region Run ! protected virtual void run_initializeEndOfDayTimer() { *************** *** 184,188 **** string dirNameWhereToSaveReports = System.Configuration.ConfigurationSettings.AppSettings["ReportsArchive"] + "\\" + this.ScriptName + "\\"; ! string dirNameWhereToSaveAccounts = System.Configuration.ConfigurationSettings.AppSettings["AccountsArchive"] + "\\" + this.ScriptName + "\\"; //default report with numIntervalDays = 1 --- 215,219 ---- string dirNameWhereToSaveReports = System.Configuration.ConfigurationSettings.AppSettings["ReportsArchive"] + "\\" + this.ScriptName + "\\"; ! string dirNameWhereToSaveTransactions = System.Configuration.ConfigurationSettings.AppSettings["TransactionsArchive"] + "\\" + this.ScriptName + "\\"; //default report with numIntervalDays = 1 *************** *** 194,202 **** ObjectArchiver.Archive(accountReport, dirNameWhereToSaveReports + ! fileName + ".rep"); ! this.checkDateForReport_createDirIfNotPresent(dirNameWhereToSaveAccounts); ! ObjectArchiver.Archive(this.account, ! dirNameWhereToSaveAccounts + ! fileName + ".acc"); this.endOfDayTimer.Stop(); --- 225,233 ---- ObjectArchiver.Archive(accountReport, dirNameWhereToSaveReports + ! fileName + ".qPr"); ! this.checkDateForReport_createDirIfNotPresent(dirNameWhereToSaveTransactions); ! ObjectArchiver.Archive(this.account.Transactions, ! dirNameWhereToSaveTransactions + ! fileName + ".qPt"); this.endOfDayTimer.Stop(); *************** *** 204,217 **** } ! ! public virtual void Run() { run_initializeHistoricalQuoteProvider(); ! run_initializeEndOfDayTimer(); run_initializeAccount(); run_initializeEndOfDayTimerHandler(); - //run_initializeProgressHandlers(); ! this.endOfDayTimer.MarketClose += new MarketCloseEventHandler( --- 235,248 ---- } ! protected virtual void run_initialize() { run_initializeHistoricalQuoteProvider(); ! run_initializeEndOfDayTimer(); run_initializeAccount(); run_initializeEndOfDayTimerHandler(); //run_initializeProgressHandlers(); ! } ! protected virtual void run_addEventHandlers() ! { this.endOfDayTimer.MarketClose += new MarketCloseEventHandler( *************** *** 223,233 **** //this.endOfDayTimer.EVENT_NAME += // new EVENT_NAMEEventHandler( ! // this.endOfDayTimerHandler.EVENT_NAMEEventHandler); ! //this.progressBarForm.Show(); this.endOfDayTimer.Start(); - } #endregion } } --- 254,271 ---- //this.endOfDayTimer.EVENT_NAME += // new EVENT_NAMEEventHandler( ! // this.endOfDayTimerHandler.EVENT_NAMEEventHandler); ! } ! ! ! public virtual void Run() ! { ! this.run_initialize(); ! this.run_addEventHandlers(); //this.progressBarForm.Show(); this.endOfDayTimer.Start(); } + #endregion + } } Index: EndOfDayTimerHandlerCTC.cs =================================================================== RCS file: /cvsroot/quantproject/QuantProject/b7_Scripts/TickerSelectionTesting/EndOfDayTimerHandlerCTC.cs,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** EndOfDayTimerHandlerCTC.cs 2 Jun 2005 18:00:47 -0000 1.8 --- EndOfDayTimerHandlerCTC.cs 24 Jun 2005 22:52:25 -0000 1.9 *************** *** 71,75 **** this.numDaysOfPortfolioLife = numDaysOfPortfolioLife; this.numDaysForReturnCalculation = numDaysForReturnCalculation; ! this.daysCounter = 0; this.maxAcceptableCloseToCloseDrawdown = maxAcceptableCloseToCloseDrawdown; this.stopLossConditionReached = false; --- 71,75 ---- this.numDaysOfPortfolioLife = numDaysOfPortfolioLife; this.numDaysForReturnCalculation = numDaysForReturnCalculation; ! this.daysCounter = -1; this.maxAcceptableCloseToCloseDrawdown = maxAcceptableCloseToCloseDrawdown; this.stopLossConditionReached = false; *************** *** 118,122 **** this.generationNumberForGeneticOptimizer); //GO.KeepOnRunningUntilConvergenceIsReached = true; - GO.GenerationNumber = this.generationNumberForGeneticOptimizer; GO.Run(false); this.chosenTickers = (string[])GO.BestGenome.Meaning; --- 118,121 ---- *************** *** 134,145 **** Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { ! if(this.daysCounter == 0 || this.daysCounter == this.numDaysOfPortfolioLife - 1) ! //at next close it will be time to open a new portfolio { this.setTickers(endOfDayTimingEventArgs.EndOfDayDateTime.DateTime); ! //sets tickers to be chosen at next close this.orders.Clear(); } - this.updateStopLossCondition(); } #endregion --- 133,146 ---- Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { ! this.updateStopLossCondition(); ! if(this.daysCounter == -1 || this.daysCounter == this.numDaysOfPortfolioLife - 1 || ! this.stopLossConditionReached ) ! //at the beginning, after num days of porfolio life has elasped, ! //or when the stop loss condition is reached { this.setTickers(endOfDayTimingEventArgs.EndOfDayDateTime.DateTime); ! //it sets tickers to be chosen at next close this.orders.Clear(); } } #endregion *************** *** 147,200 **** #region MarketCloseEventHandler ! protected void marketCloseEventHandler_orderChosenTickers_addToOrderList() ! { ! int idx = 0; ! foreach ( string ticker in this.chosenTickers ) ! { ! this.lastChosenTickers[idx] = ! GenomeManagerForEfficientPortfolio.GetCleanTickerCode(ticker); ! if(ticker != null) ! this.addOrderForTicker( ticker ); ! idx++; ! } ! } ! protected void marketCloseEventHandler_orderChosenTickers() ! { ! this.marketCloseEventHandler_orderChosenTickers_addToOrderList(); ! } ! ! ! protected void marketCloseEventHandler_openPositions() ! { ! if(this.orders.Count == 0 && this.account.Transactions.Count == 0) ! this.account.AddCash(17000); ! ! this.marketCloseEventHandler_orderChosenTickers(); ! ! foreach(object item in this.orders) ! { ! this.account.AddOrder((Order)item); ! } ! } ! ! protected void marketCloseEventHandler_closePosition( ! string ticker ) ! { ! this.account.ClosePosition( ticker ); ! } ! protected void marketCloseEventHandler_closePositions() ! { ! if(this.lastChosenTickers != null) ! { ! foreach( string ticker in this.lastChosenTickers) ! { ! for(int i = 0; i<this.account.Portfolio.Keys.Count; i++) ! { ! if(this.account.Portfolio[ticker]!=null) ! marketCloseEventHandler_closePosition( ticker ); ! } ! } ! } ! } protected void updateStopLossCondition() --- 148,152 ---- #region MarketCloseEventHandler ! protected void updateStopLossCondition() *************** *** 216,228 **** Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { ! this.daysCounter++; ! if(this.daysCounter == this.numDaysOfPortfolioLife || this.stopLossConditionReached) ! //it's time to change portfolio { ! this.marketCloseEventHandler_closePositions(); ! this.marketCloseEventHandler_openPositions(); this.daysCounter = 0; } } --- 168,186 ---- Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { ! if(this.daysCounter == -1 || ! this.daysCounter == this.numDaysOfPortfolioLife || this.stopLossConditionReached) ! //it is the first day or num days of portfolio life or ! //max acceptable close to close draw down ! //has been reached { ! this.closePositions(); ! this.openPositions(); this.daysCounter = 0; } + else + { + this.daysCounter++; + } } Index: RunEfficientCTOPortfolio.cs =================================================================== RCS file: /cvsroot/quantproject/QuantProject/b7_Scripts/TickerSelectionTesting/RunEfficientCTOPortfolio.cs,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -d -r1.19 -r1.20 *** RunEfficientCTOPortfolio.cs 2 Jun 2005 18:00:47 -0000 1.19 --- RunEfficientCTOPortfolio.cs 24 Jun 2005 22:52:25 -0000 1.20 *************** *** 53,86 **** /// - choose the most efficient portfolio among these tickers /// </summary> ! [Serializable] public class RunEfficientCTOPorfolio : RunEfficientPorfolio ! { ! public RunEfficientCTOPorfolio(string tickerGroupID, int numberOfEligibleTickers, ! int numberOfTickersToBeChosen, int numDaysForLiquidity, ! int generationNumberForGeneticOptimizer, ! int populationSizeForGeneticOptimizer, string benchmark, ! DateTime startDate, DateTime endDate, double targetReturn, ! PortfolioType portfolioType, double maxRunningHours): ! base(tickerGroupID, numberOfEligibleTickers, ! numberOfTickersToBeChosen, numDaysForLiquidity, ! generationNumberForGeneticOptimizer, ! populationSizeForGeneticOptimizer, benchmark, ! startDate, endDate, targetReturn, ! portfolioType, maxRunningHours) ! { this.ScriptName = "OpenCloseScripts"; ! } ! #region Run ! /* protected override void run_initializeAccount() { this.account = new Account( this.ScriptName , this.endOfDayTimer , new HistoricalEndOfDayDataStreamer( this.endOfDayTimer , ! this.historicalQuoteProvider ) , new HistoricalEndOfDayOrderExecutor( this.endOfDayTimer , ! this.historicalQuoteProvider ), new IBCommissionManager()); } --- 53,88 ---- /// - choose the most efficient portfolio among these tickers /// </summary> ! [Serializable] public class RunEfficientCTOPorfolio : RunEfficientPorfolio ! { ! protected int numDaysBetweenEachOptimization; public RunEfficientCTOPorfolio(string tickerGroupID, int numberOfEligibleTickers, ! int numberOfTickersToBeChosen, int numDaysForLiquidity, ! int generationNumberForGeneticOptimizer, ! int populationSizeForGeneticOptimizer, string benchmark, ! DateTime startDate, DateTime endDate, double targetReturn, ! PortfolioType portfolioType, double maxRunningHours, ! int numDaysBetweenEachOptimization): ! base(tickerGroupID, numberOfEligibleTickers, ! numberOfTickersToBeChosen, numDaysForLiquidity, ! generationNumberForGeneticOptimizer, ! populationSizeForGeneticOptimizer, benchmark, ! startDate, endDate, targetReturn, ! portfolioType, maxRunningHours) ! { this.ScriptName = "OpenCloseScripts"; ! this.numDaysBetweenEachOptimization = numDaysBetweenEachOptimization; ! } ! #region auxiliary overriden methods for Run ! /* delete remark delimitations for having ib commission protected override void run_initializeAccount() { this.account = new Account( this.ScriptName , this.endOfDayTimer , new HistoricalEndOfDayDataStreamer( this.endOfDayTimer , ! this.historicalQuoteProvider ) , new HistoricalEndOfDayOrderExecutor( this.endOfDayTimer , ! this.historicalQuoteProvider ), new IBCommissionManager()); } *************** *** 90,120 **** { this.endOfDayTimerHandler = new EndOfDayTimerHandlerCTO(this.tickerGroupID, ! this.numberOfEligibleTickers, ! this.numberOfTickersToBeChosen, ! this.numDaysForLiquidity, ! this.account, ! this.generationNumberForGeneticOptimizer, ! this.populationSizeForGeneticOptimizer, ! this.benchmark, ! this.targetReturn, ! this.portfolioType); ! ! } protected override void run_initializeHistoricalQuoteProvider() { ! this.historicalQuoteProvider = ! new HistoricalRawQuoteProvider(); ! } ! ! public override void Run() { - run_initializeHistoricalQuoteProvider(); - run_initializeEndOfDayTimer(); - run_initializeAccount(); - run_initializeEndOfDayTimerHandler(); - this.endOfDayTimer.MarketOpen += new MarketOpenEventHandler( --- 92,113 ---- { this.endOfDayTimerHandler = new EndOfDayTimerHandlerCTO(this.tickerGroupID, ! this.numberOfEligibleTickers, ! this.numberOfTickersToBeChosen, ! this.numDaysForLiquidity, ! this.account, ! this.generationNumberForGeneticOptimizer, ! this.populationSizeForGeneticOptimizer, ! this.benchmark, ! this.targetReturn, ! this.portfolioType, this.numDaysBetweenEachOptimization); } protected override void run_initializeHistoricalQuoteProvider() { ! this.historicalQuoteProvider = new HistoricalRawQuoteProvider(); } ! ! protected override void run_addEventHandlers() { this.endOfDayTimer.MarketOpen += new MarketOpenEventHandler( *************** *** 132,140 **** new OneHourAfterMarketCloseEventHandler( this.endOfDayTimerHandler.OneHourAfterMarketCloseEventHandler ); - - this.endOfDayTimer.Start(); - } #endregion } } --- 125,137 ---- new OneHourAfterMarketCloseEventHandler( this.endOfDayTimerHandler.OneHourAfterMarketCloseEventHandler ); } #endregion + + //necessary far calling RunEfficientPortfolio.Run() + //in classes that inherit from this class + public override void Run() + { + base.Run(); + } } } Index: GenomeManagerForEfficientPortfolio.cs =================================================================== RCS file: /cvsroot/quantproject/QuantProject/b7_Scripts/TickerSelectionTesting/GenomeManagerForEfficientPortfolio.cs,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** GenomeManagerForEfficientPortfolio.cs 2 Jun 2005 18:00:47 -0000 1.9 --- GenomeManagerForEfficientPortfolio.cs 24 Jun 2005 22:52:25 -0000 1.10 *************** *** 48,53 **** --- 48,55 ---- protected double targetPerformance; protected double variance; + protected double lowerPartialMoment; protected double rateOfReturn; protected PortfolioType portfolioType; + protected double[] portfolioRatesOfReturn; static public string GetCleanTickerCode(string tickerModifiedCode) *************** *** 189,198 **** //OLD IMPLEMENTATION double portfolioRateOfReturn = this.getPortfolioRateOfReturn(genome.Genes()); //OLD IMPLEMENTATION double portfolioVariance = this.getPortfolioVariance(genome.Genes()); ! double[] portfolioRatesOfReturn = this.getPortfolioRatesOfReturn(genome.Genes()); double averagePortfolioRateOfReturn = ! BasicFunctions.SimpleAverage(portfolioRatesOfReturn); double portfolioVariance = ! BasicFunctions.Variance(portfolioRatesOfReturn); if(!Double.IsInfinity(portfolioVariance) && --- 191,200 ---- //OLD IMPLEMENTATION double portfolioRateOfReturn = this.getPortfolioRateOfReturn(genome.Genes()); //OLD IMPLEMENTATION double portfolioVariance = this.getPortfolioVariance(genome.Genes()); ! this.portfolioRatesOfReturn = this.getPortfolioRatesOfReturn(genome.Genes()); double averagePortfolioRateOfReturn = ! BasicFunctions.SimpleAverage(this.portfolioRatesOfReturn); double portfolioVariance = ! BasicFunctions.Variance(this.portfolioRatesOfReturn); if(!Double.IsInfinity(portfolioVariance) && *************** *** 215,219 **** public Genome[] GetChilds(Genome parent1, Genome parent2) { ! return GenomeManagement.MixGenesWithoutDuplicates(parent1, parent2); } --- 217,223 ---- public Genome[] GetChilds(Genome parent1, Genome parent2) { ! return ! GenomeManagement.MixGenesWithoutDuplicates(parent1, parent2, ! this.originalNumOfTickers); } *************** *** 225,229 **** genome.MaxValueForGenes + 1); while(genome.HasGene(returnValue) || ! genome.HasGene(returnValue + this.originalNumOfTickers)) //the portfolio can't have a long position and a short position // for the same ticker --- 229,234 ---- genome.MaxValueForGenes + 1); while(genome.HasGene(returnValue) || ! genome.HasGene(returnValue + this.originalNumOfTickers) || ! genome.HasGene(returnValue - this.originalNumOfTickers) ) //the portfolio can't have a long position and a short position // for the same ticker *************** *** 245,250 **** int genePositionToBeMutated = GenomeManagement.RandomGenerator.Next(genome.Size); while(genome.HasGene(newValueForGene) || ! genome.HasGene(newValueForGene + this.originalNumOfTickers)) ! //the portfolio can't have a long position and a short position // for the same ticker { --- 250,257 ---- int genePositionToBeMutated = GenomeManagement.RandomGenerator.Next(genome.Size); while(genome.HasGene(newValueForGene) || ! genome.HasGene(newValueForGene + this.originalNumOfTickers) || ! genome.HasGene(newValueForGene - this.originalNumOfTickers) ) ! //the efficient portfolio, in this implementation, ! // can't have a long position and a short position // for the same ticker { Index: EndOfDayTimerHandlerCTO.cs =================================================================== RCS file: /cvsroot/quantproject/QuantProject/b7_Scripts/TickerSelectionTesting/EndOfDayTimerHandlerCTO.cs,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** EndOfDayTimerHandlerCTO.cs 2 Jun 2005 18:00:47 -0000 1.12 --- EndOfDayTimerHandlerCTO.cs 24 Jun 2005 22:52:25 -0000 1.13 *************** *** 44,48 **** public class EndOfDayTimerHandlerCTO : EndOfDayTimerHandler { ! public EndOfDayTimerHandlerCTO(string tickerGroupID, int numberOfEligibleTickers, int numberOfTickersToBeChosen, int numDaysForLiquidity, Account account, --- 44,49 ---- public class EndOfDayTimerHandlerCTO : EndOfDayTimerHandler { ! protected int numDaysBetweenEachOptimization; ! private int numDaysElapsedSinceLastOptimization; public EndOfDayTimerHandlerCTO(string tickerGroupID, int numberOfEligibleTickers, int numberOfTickersToBeChosen, int numDaysForLiquidity, Account account, *************** *** 50,54 **** int populationSizeForGeneticOptimizer, string benchmark, double targetReturn, ! PortfolioType portfolioType): base(tickerGroupID, numberOfEligibleTickers, numberOfTickersToBeChosen, numDaysForLiquidity, account, --- 51,55 ---- int populationSizeForGeneticOptimizer, string benchmark, double targetReturn, ! PortfolioType portfolioType, int numDaysBetweenEachOptimization): base(tickerGroupID, numberOfEligibleTickers, numberOfTickersToBeChosen, numDaysForLiquidity, account, *************** *** 58,86 **** portfolioType) { ! } ! #region MarketOpenEventHandler ! ! protected void marketOpenEventHandler_orderChosenTickers_addToOrderList() ! { ! int idx = 0; ! foreach ( string ticker in this.chosenTickers ) ! { ! if(ticker != null) ! { ! this.addOrderForTicker( ticker ); ! this.lastChosenTickers[idx] = ! GenomeManagerForEfficientPortfolio.GetCleanTickerCode(ticker); ! } ! idx++; ! } ! } ! ! protected void marketOpenEventHandler_orderChosenTickers() ! { ! this.marketOpenEventHandler_orderChosenTickers_addToOrderList(); ! } ! /// <summary> /// Handles a "Market Open" event. --- 59,67 ---- portfolioType) { ! this.numDaysBetweenEachOptimization = numDaysBetweenEachOptimization; ! this.numDaysElapsedSinceLastOptimization = 0; } ! /// <summary> /// Handles a "Market Open" event. *************** *** 91,136 **** Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { ! if(this.orders.Count == 0 && this.account.Transactions.Count == 0) ! this.account.AddCash(17000); ! ! this.marketOpenEventHandler_orderChosenTickers(); ! ! foreach(object item in this.orders) ! { ! this.account.AddOrder((Order)item); ! } ! } ! #endregion ! ! #region MarketCloseEventHandler ! ! protected void marketCloseEventHandler_closePosition( ! string ticker ) ! { ! this.account.ClosePosition( ticker ); ! } ! protected void marketCloseEventHandler_closePositions() ! { ! if(this.lastChosenTickers != null) ! { ! foreach( string ticker in this.lastChosenTickers) ! { ! for(int i = 0; i<this.account.Portfolio.Keys.Count; i++) ! { ! if(this.account.Portfolio[ticker]!=null) ! marketCloseEventHandler_closePosition( ticker ); ! } ! } ! } } ! public override void MarketCloseEventHandler( Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { ! ! this.marketCloseEventHandler_closePositions(); } ! #endregion #region OneHourAfterMarketCloseEventHandler --- 72,86 ---- Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { ! this.openPositions(); } ! ! public override void MarketCloseEventHandler( Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { ! this.closePositions(); } ! #region OneHourAfterMarketCloseEventHandler *************** *** 166,170 **** // currentDate, this.numberOfEligibleTickers/4); //return winners.GetTableOfSelectedTickers(); ! return quotedAtEachMarketDayFromEligible.GetTableOfSelectedTickers(); } --- 116,126 ---- // currentDate, this.numberOfEligibleTickers/4); //return winners.GetTableOfSelectedTickers(); ! SelectorByOpenCloseCorrelationToBenchmark lessCorrelated = ! new SelectorByOpenCloseCorrelationToBenchmark(quotedAtEachMarketDayFromEligible.GetTableOfSelectedTickers(), ! this.benchmark, true, ! currentDate.AddDays(-this.numDaysForLiquidity), ! currentDate, this.numberOfEligibleTickers/2); ! //return quotedAtEachMarketDayFromEligible.GetTableOfSelectedTickers(); ! return lessCorrelated.GetTableOfSelectedTickers(); } *************** *** 216,223 **** Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { //this.oneHourAfterMarketCloseEventHandler_updatePrices(); ! this.setTickers(endOfDayTimingEventArgs.EndOfDayDateTime.DateTime); ! //sets tickers to be chosen next Market Open event ! this.orders.Clear(); } --- 172,186 ---- Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { + this.orders.Clear(); + this.numDaysElapsedSinceLastOptimization++; //this.oneHourAfterMarketCloseEventHandler_updatePrices(); ! if(this.numDaysElapsedSinceLastOptimization == ! this.numDaysBetweenEachOptimization) ! { ! this.setTickers(endOfDayTimingEventArgs.EndOfDayDateTime.DateTime); ! //sets tickers to be chosen next Market Open event ! this.numDaysElapsedSinceLastOptimization = 0; ! } ! } |