[Quantproject-developers] QuantProject/b7_Scripts/WalkForwardTesting/FixedLengthTwoPhases FixedLen
Brought to you by:
glauco_1
|
From: Glauco S. <gla...@us...> - 2008-08-16 19:36:11
|
Update of /cvsroot/quantproject/QuantProject/b7_Scripts/WalkForwardTesting/FixedLengthTwoPhases In directory sc8-pr-cvs16.sourceforge.net:/tmp/cvs-serv787/b7_Scripts/WalkForwardTesting/FixedLengthTwoPhases Modified Files: FixedLengthTwoPhasesStrategy.cs Log Message: This class now extends the SymmetricEndOfDayStrategyForBacktester class Index: FixedLengthTwoPhasesStrategy.cs =================================================================== RCS file: /cvsroot/quantproject/QuantProject/b7_Scripts/WalkForwardTesting/FixedLengthTwoPhases/FixedLengthTwoPhasesStrategy.cs,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** FixedLengthTwoPhasesStrategy.cs 11 May 2008 19:00:50 -0000 1.7 --- FixedLengthTwoPhasesStrategy.cs 16 Aug 2008 19:35:59 -0000 1.8 *************** *** 44,101 **** /// first phase, then goes with the opposite for the second phase /// </summary> ! public class FixedLengthTwoPhasesStrategy : IEndOfDayStrategyForBacktester { ! public event NewLogItemEventHandler NewLogItem; ! public event NewMessageEventHandler NewMessage; ! ! private int numberOfPortfolioPositions; ! private int numDaysBeetweenEachOtpimization; ! private int numDaysForInSampleOptimization; ! private Benchmark benchmark; ! private IIntervalsSelector intervalsSelector; ! private IEligiblesSelector eligiblesSelector; ! private IInSampleChooser inSampleChooser; ! ! private DateTime lastOptimizationDateTime; ! private ReturnIntervals returnIntervals; ! private IHistoricalQuoteProvider historicalQuoteProvider; ! ! private Account account; ! // private bool arePositionsToBeClosed; ! // private bool arePositionsToBeOpened; ! private WeightedPositions bestWeightedPositionsInSample; ! ! public Account Account ! { ! get { return this.account; } ! set { this.account = value; } ! } ! ! ! public bool StopBacktestIfMaxRunningHoursHasBeenReached ! { ! get ! { ! return this.isInsampleOptimizationNeeded(); ! } ! } ! public string Description ! { ! get ! { ! string descriptionForLogFileName = ! "Strtgy_fltp_" + ! "nmDysBtwnOptmztns_" + ! this.numDaysBeetweenEachOtpimization.ToString() + "_" + ! this.eligiblesSelector.Description + "_" + ! this.inSampleChooser.Description + ! "_oS_longOnly"; ! return descriptionForLogFileName; ! } ! } public FixedLengthTwoPhasesStrategy( int numberOfPortfolioPositions , ! int numDaysBeetweenEachOtpimization , int numDaysForInSampleOptimization , Benchmark benchmark , --- 44,64 ---- /// first phase, then goes with the opposite for the second phase /// </summary> ! public class FixedLengthTwoPhasesStrategy : ! SymmetricEndOfDayStrategyForBacktester { ! // private int numberOfPortfolioPositions; ! // private Benchmark benchmark; ! // private IIntervalsSelector intervalsSelector; ! // ! // private IHistoricalQuoteProvider historicalQuoteProvider; ! // ! // private Account account; ! // private WeightedPositions bestWeightedPositionsInSample; ! ! private RankBasedOutOfSampleChooser outOfSampleChooser; public FixedLengthTwoPhasesStrategy( int numberOfPortfolioPositions , ! int numDaysBetweenEachOtpimization , int numDaysForInSampleOptimization , Benchmark benchmark , *************** *** 103,134 **** IEligiblesSelector eligiblesSelector , IInSampleChooser inSampleChooser , ! IHistoricalQuoteProvider historicalQuoteProvider ! ) { ! this.numberOfPortfolioPositions = numberOfPortfolioPositions; ! this.numDaysBeetweenEachOtpimization = numDaysBeetweenEachOtpimization; ! this.numDaysForInSampleOptimization = numDaysForInSampleOptimization; ! this.benchmark = benchmark; ! this.intervalsSelector = intervalsSelector; ! this.eligiblesSelector = eligiblesSelector; ! this.inSampleChooser = inSampleChooser; ! this.historicalQuoteProvider = historicalQuoteProvider; ! this.returnIntervals = ! new ReturnIntervals( this.intervalsSelector ); - // this.arePositionsToBeClosed = false; - // this.arePositionsToBeOpened = false; } ! #region MarketOpenEventHandler ! private bool marketOpenEventHandler_arePositionsToBeClosed() { bool arePositionsToBeClosed = ( ! ( this.account.Portfolio.Count > 0 ) && ( this.now().IsEqualTo( this.lastIntervalAppended().Begin ) ) ); return arePositionsToBeClosed; } ! #region marketOpenEventHandler_arePositionsToBeOpened private bool lastAppendedIntervalIsALongPeriod() { --- 66,108 ---- IEligiblesSelector eligiblesSelector , IInSampleChooser inSampleChooser , ! IHistoricalQuoteProvider historicalQuoteProvider , ! RankBasedOutOfSampleChooser outOfSampleChooser ! ) : ! base( ! numDaysBetweenEachOtpimization , ! numDaysForInSampleOptimization , ! intervalsSelector , ! intervalsSelector , ! eligiblesSelector , ! inSampleChooser , ! historicalQuoteProvider ) { ! this.outOfSampleChooser = outOfSampleChooser; ! // this.numberOfPortfolioPositions = numberOfPortfolioPositions; ! // this.numDaysBetweenEachOtpimization = numDaysBetweenEachOtpimization; ! // this.numDaysForInSampleOptimization = numDaysForInSampleOptimization; ! // this.benchmark = benchmark; ! // this.intervalsSelector = intervalsSelector; ! // this.eligiblesSelector = eligiblesSelector; ! // this.inSampleChooser = inSampleChooser; ! // this.historicalQuoteProvider = historicalQuoteProvider; ! // this.returnIntervals = ! // new ReturnIntervals( this.intervalsSelector ); } ! ! protected override bool arePositionsToBeClosed() { bool arePositionsToBeClosed = ( ! ( this.Account.Portfolio.Count > 0 ) && ( this.now().IsEqualTo( this.lastIntervalAppended().Begin ) ) ); return arePositionsToBeClosed; } ! ! #region arePositionsToBeOpened ! ! #region currentTimeBeginsALongPeriod private bool lastAppendedIntervalIsALongPeriod() { *************** *** 146,344 **** return ( beginsTheLastInterval && lastIntervalIsALongPeriod ); } ! private bool marketOpenEventHandler_arePositionsToBeOpened() { bool arePositionsToBeOpened = ( ! ( this.bestWeightedPositionsInSample != null ) && ( this.currentTimeBeginsALongPeriod() ) ); return arePositionsToBeOpened; } ! #endregion marketOpenEventHandler_arePositionsToBeOpened ! public void MarketOpenEventHandler( ! Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) ! { ! this.updateReturnIntervals(); ! if ( this.marketOpenEventHandler_arePositionsToBeClosed() ) ! AccountManager.ClosePositions( this.account ); ! if ( this.marketOpenEventHandler_arePositionsToBeOpened() ) ! AccountManager.OpenPositions( this.bestWeightedPositionsInSample , ! this.account ); ! } ! #endregion MarketOpenEventHandler ! public void FiveMinutesBeforeMarketCloseEventHandler( ! Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) ! { ! } ! #region MarketCloseEventHandler ! private bool marketCloseEventHandler_arePositionsToBeClosed() ! { ! return marketOpenEventHandler_arePositionsToBeClosed(); ! } ! private bool marketCloseEventHandler_arePositionsToBeOpened() ! { ! // this strategy goes long only ! return false; ! } ! public void MarketCloseEventHandler( ! Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) ! { ! this.updateReturnIntervals(); ! if ( this.marketCloseEventHandler_arePositionsToBeClosed() ) ! AccountManager.ClosePositions( this.account ); ! if ( this.marketCloseEventHandler_arePositionsToBeOpened() ) ! { ! this.bestWeightedPositionsInSample.Reverse(); ! AccountManager.OpenPositions( ! this.bestWeightedPositionsInSample , ! this.account ); ! this.bestWeightedPositionsInSample.Reverse(); ! } ! } ! #endregion MarketCloseEventHandler ! #region OneHourAfterMarketCloseEventHandler ! private bool optimalWeightedPositionsAreToBeUpdated() ! { ! TimeSpan timeSpanSinceLastOptimization = ! this.now().DateTime - this.lastOptimizationDateTime; ! bool areToBeUpdated = ( timeSpanSinceLastOptimization.Days >= ! this.numDaysBeetweenEachOtpimization ); ! return areToBeUpdated; ! } ! #region getInSampleReturnIntervals ! private EndOfDayDateTime getInSampleReturnIntervals_getFirstDate() ! { ! DateTime firstDateTime = this.now().DateTime.AddDays( ! -this.numDaysForInSampleOptimization ); ! EndOfDayDateTime firstDate = new EndOfDayDateTime( ! firstDateTime , EndOfDaySpecificTime.MarketOpen ); ! return firstDate; ! } ! private ReturnIntervals getInSampleReturnIntervals() ! { ! EndOfDayDateTime firstDate = ! this.getInSampleReturnIntervals_getFirstDate(); ! EndOfDayDateTime lastDate = ! new EndOfDayDateTime( this.now().DateTime , ! EndOfDaySpecificTime.MarketClose ); ! ReturnIntervals inSampleReturnIntervals = ! new ReturnIntervals( this.intervalsSelector ); ! inSampleReturnIntervals.AppendFirstInterval( firstDate ); ! if ( inSampleReturnIntervals.LastEndOfDayDateTime.IsLessThan( ! lastDate ) ) ! inSampleReturnIntervals.AppendIntervalsButDontGoBeyondLastDate( ! lastDate ); ! return inSampleReturnIntervals; ! } ! #endregion getInSampleReturnIntervals ! private void notifyMessage( EligibleTickers eligibleTickers ) { ! string message = "Number of Eligible tickers: " + ! eligibleTickers.Count; ! NewMessageEventArgs newMessageEventArgs = ! new NewMessageEventArgs( message ); ! if ( this.NewMessage != null ) ! this.NewMessage( this , newMessageEventArgs ); } ! #region logOptimizationInfo ! private void outputMessage( string message ) { ! MessageManager.DisplayMessage( message , ! "FixedLengthUpDown.Txt" ); } ! private FixedLengthTwoPhasesLogItem getLogItem( EligibleTickers eligibleTickers ) { ! FixedLengthTwoPhasesLogItem logItem = ! new FixedLengthTwoPhasesLogItem( this.now() ); ! logItem.BestWeightedPositionsInSample = ! this.bestWeightedPositionsInSample; ! logItem.NumberOfEligibleTickers = ! eligibleTickers.Count; return logItem; } - private void raiseNewLogItem( EligibleTickers eligibleTickers ) - { - FixedLengthTwoPhasesLogItem logItem = - this.getLogItem( eligibleTickers ); - NewLogItemEventArgs newLogItemEventArgs = - new NewLogItemEventArgs( logItem ); - this.NewLogItem( this , newLogItemEventArgs ); - } - private void logOptimizationInfo( EligibleTickers eligibleTickers ) - { - this.raiseNewLogItem( eligibleTickers ); - } - #endregion logOptimizationInfo - private void updateOptimalWeightedPositions_actually() - { - ReturnIntervals inSampleReturnIntervals = - this.getInSampleReturnIntervals(); - EligibleTickers eligibleTickers = - this.eligiblesSelector.GetEligibleTickers( - inSampleReturnIntervals.BordersHistory ); - ReturnsManager returnsManager = new ReturnsManager( - inSampleReturnIntervals , this.historicalQuoteProvider ); - this.bestWeightedPositionsInSample = - (WeightedPositions)this.inSampleChooser.AnalyzeInSample( - eligibleTickers , returnsManager ); ! this.notifyMessage( eligibleTickers ); ! this.logOptimizationInfo( eligibleTickers ); ! } ! private void updateOptimalWeightedPositions() ! { ! this.updateOptimalWeightedPositions_actually(); ! this.lastOptimizationDateTime = this.now().DateTime; ! FixedLengthTwoPhasesLogItem logItem = ! new FixedLengthTwoPhasesLogItem( this.now() ); ! logItem.BestWeightedPositionsInSample = this.bestWeightedPositionsInSample; ! // this.wFLagWeightedPositionsChooser.WFLagChosenPositions , ! // this.wFLagWeightedPositionsChooser.GenerationWhenChosenPositionsWereFound , ! // this.now().DateTime ); ! // this.NewChosenPositions( ! // this , new WFLagNewChosenPositionsEventArgs( ! // wFLagLogItem ) ); ! } ! public void OneHourAfterMarketCloseEventHandler( ! Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) ! { ! if ( this.optimalWeightedPositionsAreToBeUpdated() ) ! this.updateOptimalWeightedPositions(); ! } ! #endregion OneHourAfterMarketCloseEventHandler ! public bool isInsampleOptimizationNeeded() ! { ! DateTime dateTimeForNextOptimization = ! this.lastOptimizationDateTime.AddDays( ! this.numDaysBeetweenEachOtpimization ); ! bool returnValue = ! ( ( ( this.account.Portfolio.Count == 0 ) ! && ( ( this.lastOptimizationDateTime == DateTime.MinValue ) ) ) || ! ( this.now().DateTime >= dateTimeForNextOptimization ) ); ! return returnValue; ! } ! private void updateReturnIntervals() ! { ! EndOfDayDateTime currentEndOfDayDateTime = ! this.account.EndOfDayTimer.GetCurrentTime(); ! if ( this.returnIntervals.Count == 0 ) ! // no interval has been added yet ! this.returnIntervals.AppendFirstInterval( ! currentEndOfDayDateTime ); ! else ! // at least one interval has already been added ! if ( this.returnIntervals.LastEndOfDayDateTime.IsLessThanOrEqualTo( ! currentEndOfDayDateTime ) ) ! this.returnIntervals.AppendIntervalsToGoJustBeyond( ! currentEndOfDayDateTime ); ! } ! private EndOfDayDateTime now() ! { ! return this.account.EndOfDayTimer.GetCurrentTime(); ! } ! private ReturnInterval lastIntervalAppended() ! { ! ReturnInterval lastInterval = ! this.returnIntervals[ this.returnIntervals.Count - 1 ]; ! return lastInterval; ! } } } --- 120,363 ---- return ( beginsTheLastInterval && lastIntervalIsALongPeriod ); } ! #endregion currentTimeBeginsALongPeriod ! ! protected override bool arePositionsToBeOpened() { bool arePositionsToBeOpened = ( ! ( this.bestTestingPositionsInSample != null ) && ( this.currentTimeBeginsALongPeriod() ) ); return arePositionsToBeOpened; } ! #endregion arePositionsToBeOpened ! ! protected override WeightedPositions getPositionsToBeOpened() { ! WeightedPositions weightedPositions = ! this.outOfSampleChooser.GetPositionsToBeOpened( ! this.bestTestingPositionsInSample ); ! return weightedPositions; } ! ! protected override string getTextIdentifier() { ! return "FLTP"; } ! ! protected override LogItem getLogItem( EligibleTickers eligibleTickers ) { ! FLTPLogItem logItem = ! new FLTPLogItem( ! this.now() , ! this.bestTestingPositionsInSample , ! this.numDaysForInSampleOptimization , ! eligibleTickers.Count ); return logItem; } ! // #region MarketOpenEventHandler ! // private bool marketOpenEventHandler_arePositionsToBeClosed() ! // { ! // bool arePositionsToBeClosed = ( ! // ( this.account.Portfolio.Count > 0 ) && ! // ( this.now().IsEqualTo( ! // this.lastIntervalAppended().Begin ) ) ); ! // return arePositionsToBeClosed; ! // } ! // #region marketOpenEventHandler_arePositionsToBeOpened ! // private bool marketOpenEventHandler_arePositionsToBeOpened() ! // { ! // bool arePositionsToBeOpened = ( ! // ( this.bestWeightedPositionsInSample != null ) && ! // ( this.currentTimeBeginsALongPeriod() ) ); ! // return arePositionsToBeOpened; ! // } ! // #endregion marketOpenEventHandler_arePositionsToBeOpened ! // public void MarketOpenEventHandler( ! // Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) ! // { ! // this.updateReturnIntervals(); ! // if ( this.marketOpenEventHandler_arePositionsToBeClosed() ) ! // AccountManager.ClosePositions( this.account ); ! // if ( this.marketOpenEventHandler_arePositionsToBeOpened() ) ! // AccountManager.OpenPositions( this.bestWeightedPositionsInSample , ! // this.account ); ! // } ! // #endregion MarketOpenEventHandler ! ! ! // #region MarketCloseEventHandler ! // private bool marketCloseEventHandler_arePositionsToBeClosed() ! // { ! // return marketOpenEventHandler_arePositionsToBeClosed(); ! // } ! // private bool marketCloseEventHandler_arePositionsToBeOpened() ! // { ! // // this strategy goes long only ! // return false; ! // } ! // public void MarketCloseEventHandler( ! // Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) ! // { ! // this.updateReturnIntervals(); ! // if ( this.marketCloseEventHandler_arePositionsToBeClosed() ) ! // AccountManager.ClosePositions( this.account ); ! // if ( this.marketCloseEventHandler_arePositionsToBeOpened() ) ! // { ! // this.bestWeightedPositionsInSample.Reverse(); ! // AccountManager.OpenPositions( ! // this.bestWeightedPositionsInSample , ! // this.account ); ! // this.bestWeightedPositionsInSample.Reverse(); ! // } ! // } ! // #endregion MarketCloseEventHandler ! ! // #region OneHourAfterMarketCloseEventHandler ! // private bool optimalWeightedPositionsAreToBeUpdated() ! // { ! // TimeSpan timeSpanSinceLastOptimization = ! // this.now().DateTime - this.lastOptimizationDateTime; ! // bool areToBeUpdated = ( timeSpanSinceLastOptimization.Days >= ! // this.numDaysBetweenEachOtpimization ); ! // return areToBeUpdated; ! // } ! // #region getInSampleReturnIntervals ! // private EndOfDayDateTime getInSampleReturnIntervals_getFirstDate() ! // { ! // DateTime firstDateTime = this.now().DateTime.AddDays( ! // -this.numDaysForInSampleOptimization ); ! // EndOfDayDateTime firstDate = new EndOfDayDateTime( ! // firstDateTime , EndOfDaySpecificTime.MarketOpen ); ! // return firstDate; ! // } ! // private ReturnIntervals getInSampleReturnIntervals() ! // { ! // EndOfDayDateTime firstDate = ! // this.getInSampleReturnIntervals_getFirstDate(); ! // EndOfDayDateTime lastDate = ! // new EndOfDayDateTime( this.now().DateTime , ! // EndOfDaySpecificTime.MarketClose ); ! // ReturnIntervals inSampleReturnIntervals = ! // new ReturnIntervals( this.intervalsSelector ); ! // inSampleReturnIntervals.AppendFirstInterval( firstDate ); ! // if ( inSampleReturnIntervals.LastEndOfDayDateTime.IsLessThan( ! // lastDate ) ) ! // inSampleReturnIntervals.AppendIntervalsButDontGoBeyondLastDate( ! // lastDate ); ! // return inSampleReturnIntervals; ! // } ! // #endregion getInSampleReturnIntervals ! // private void notifyMessage( EligibleTickers eligibleTickers ) ! // { ! // string message = "Number of Eligible tickers: " + ! // eligibleTickers.Count; ! // NewMessageEventArgs newMessageEventArgs = ! // new NewMessageEventArgs( message ); ! // if ( this.NewMessage != null ) ! // this.NewMessage( this , newMessageEventArgs ); ! // } ! // #region logOptimizationInfo ! // private void outputMessage( string message ) ! // { ! // MessageManager.DisplayMessage( message , ! // "FixedLengthUpDown.Txt" ); ! // } ! // private FixedLengthTwoPhasesLogItem getLogItem( EligibleTickers eligibleTickers ) ! // { ! // FixedLengthTwoPhasesLogItem logItem = ! // new FixedLengthTwoPhasesLogItem( this.now() ); ! // logItem.BestWeightedPositionsInSample = ! // this.bestWeightedPositionsInSample; ! // logItem.NumberOfEligibleTickers = ! // eligibleTickers.Count; ! // return logItem; ! // } ! // private void raiseNewLogItem( EligibleTickers eligibleTickers ) ! // { ! // FixedLengthTwoPhasesLogItem logItem = ! // this.getLogItem( eligibleTickers ); ! // NewLogItemEventArgs newLogItemEventArgs = ! // new NewLogItemEventArgs( logItem ); ! // this.NewLogItem( this , newLogItemEventArgs ); ! // } ! // private void logOptimizationInfo( EligibleTickers eligibleTickers ) ! // { ! // this.raiseNewLogItem( eligibleTickers ); ! // } ! // #endregion logOptimizationInfo ! // private void updateOptimalWeightedPositions_actually() ! // { ! // ReturnIntervals inSampleReturnIntervals = ! // this.getInSampleReturnIntervals(); ! // EligibleTickers eligibleTickers = ! // this.eligiblesSelector.GetEligibleTickers( ! // inSampleReturnIntervals.BordersHistory ); ! // ReturnsManager returnsManager = new ReturnsManager( ! // inSampleReturnIntervals , this.historicalQuoteProvider ); ! // this.bestWeightedPositionsInSample = ! // (WeightedPositions)this.inSampleChooser.AnalyzeInSample( ! // eligibleTickers , returnsManager ); ! // ! // this.notifyMessage( eligibleTickers ); ! // this.logOptimizationInfo( eligibleTickers ); ! // } ! // private void updateOptimalWeightedPositions() ! // { ! // this.updateOptimalWeightedPositions_actually(); ! // this.lastOptimizationDateTime = this.now().DateTime; ! // FixedLengthTwoPhasesLogItem logItem = ! // new FixedLengthTwoPhasesLogItem( this.now() ); ! // logItem.BestWeightedPositionsInSample = this.bestWeightedPositionsInSample; ! //// this.wFLagWeightedPositionsChooser.WFLagChosenPositions , ! //// this.wFLagWeightedPositionsChooser.GenerationWhenChosenPositionsWereFound , ! //// this.now().DateTime ); ! //// this.NewChosenPositions( ! //// this , new WFLagNewChosenPositionsEventArgs( ! //// wFLagLogItem ) ); ! // } ! // public void OneHourAfterMarketCloseEventHandler( ! // Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) ! // { ! // if ( this.optimalWeightedPositionsAreToBeUpdated() ) ! // this.updateOptimalWeightedPositions(); ! // } ! // #endregion OneHourAfterMarketCloseEventHandler ! ! // public bool isInsampleOptimizationNeeded() ! // { ! // DateTime dateTimeForNextOptimization = ! // this.lastOptimizationDateTime.AddDays( ! // this.numDaysBetweenEachOtpimization ); ! // bool returnValue = ! // ( ( ( this.account.Portfolio.Count == 0 ) ! // && ( ( this.lastOptimizationDateTime == DateTime.MinValue ) ) ) || ! // ( this.now().DateTime >= dateTimeForNextOptimization ) ); ! // return returnValue; ! // } ! // private void updateReturnIntervals() ! // { ! // EndOfDayDateTime currentEndOfDayDateTime = ! // this.account.EndOfDayTimer.GetCurrentTime(); ! // if ( this.returnIntervals.Count == 0 ) ! // // no interval has been added yet ! // this.returnIntervals.AppendFirstInterval( ! // currentEndOfDayDateTime ); ! // else ! // // at least one interval has already been added ! // if ( this.returnIntervals.LastEndOfDayDateTime.IsLessThanOrEqualTo( ! // currentEndOfDayDateTime ) ) ! // this.returnIntervals.AppendIntervalsToGoJustBeyond( ! // currentEndOfDayDateTime ); ! // } ! // private EndOfDayDateTime now() ! // { ! // return this.account.EndOfDayTimer.GetCurrentTime(); ! // } ! // private ReturnInterval lastIntervalAppended() ! // { ! // ReturnInterval lastInterval = ! // this.returnIntervals[ this.returnIntervals.Count - 1 ]; ! // return lastInterval; ! // } } } |