[Quantproject-developers] QuantProject/b7_Scripts/TechnicalAnalysisTesting/Oscillators/FixedLevelOs
Brought to you by:
glauco_1
|
From: Marco M. <mi...@us...> - 2008-03-09 22:49:28
|
Update of /cvsroot/quantproject/QuantProject/b7_Scripts/TechnicalAnalysisTesting/Oscillators/FixedLevelOscillators/PortfolioValueOscillator In directory sc8-pr-cvs16.sourceforge.net:/tmp/cvs-serv6639/Oscillators/FixedLevelOscillators/PortfolioValueOscillator Added Files: PVOGenomeManager.cs PVOLogItem.cs PVOMain.cs PVOPositions.cs PVOPositionsStatus.cs PVOStrategy.cs Log Message: Added a new implementation for the PVO strategy (now common objects recently added at business layer by Glauco are used). At the moment, these files perform a PVO strategy using close to close returns, on a multiday - minimum 1 day - basis. Take profit and stop loss levels can be set. --- NEW FILE: PVOStrategy.cs --- /* QuantProject - Quantitative Finance Library PVOStrategy.cs Copyright (C) 2008 Marco Milletti This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ using System; using System.Data; using System.Collections; using QuantProject.ADT; using QuantProject.ADT.Messaging; 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.Business.Strategies.OutOfSample; using QuantProject.Business.Strategies.Logging; using QuantProject.Business.Strategies.ReturnsManagement; using QuantProject.Business.Strategies.ReturnsManagement.Time; using QuantProject.Business.DataProviders; using QuantProject.Business.Strategies.TickersRelationships; using QuantProject.Business.Strategies.Eligibles; using QuantProject.Business.Strategies.Optimizing.Decoding; using QuantProject.Data; using QuantProject.Data.DataProviders; using QuantProject.Data.Selectors; using QuantProject.Data.DataTables; using QuantProject.ADT.Optimizing.Genetic; using QuantProject.Scripts.TickerSelectionTesting.EfficientPortfolios; using QuantProject.Scripts.WalkForwardTesting.LinearCombination; namespace QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator { /// <summary> /// Implements MarketOpenEventHandler and MarketCloseEventHandler /// These handlers contain the core strategy for the Portfolio Value /// Oscillator /// </summary> [Serializable] public class PVOStrategy : IEndOfDayStrategyForBacktester { public event NewLogItemEventHandler NewLogItem; public event NewMessageEventHandler NewMessage; //initialized by the constructor protected int numberOfTickersToBeChosen; protected int inSampleDays; protected int numDaysBetweenEachOptimization; protected IInSampleChooser inSampleChooser; protected IEligiblesSelector eligiblesSelector; protected Benchmark benchmark; protected HistoricalQuoteProvider historicalQuoteProvider; protected double maxAcceptableCloseToCloseDrawdown; protected double minimumAcceptableGain; protected int numDaysForOscillatingPeriod; //initialized after constructor's call protected int numDaysElapsedSinceLastOptimization; protected ReturnsManager returnsManager; protected TestingPositions[] chosenPVOPositions; //chosen in sample: these are the eligible positions for out //of sample testing protected PVOPositions pvoPositionsForOutOfSample; protected DateTime lastCloseDate; protected bool portfolioHasBeenOverbought; protected bool portfolioHasBeenOversold; protected Account account; public Account Account { set { this.account = value; } } protected bool stopLossConditionReached; protected bool takeProfitConditionReached; protected double currentAccountValue; protected double previousAccountValue; private string description_GetDescriptionForChooser() { if(this.inSampleChooser == null) return "ConstantChooser"; else return this.inSampleChooser.Description; } public string Description { get { string description = "PVO_" + "nmbrTckrs_" + this.numberOfTickersToBeChosen.ToString() + "_inSmplDays_" + this.inSampleDays.ToString() + "_" + this.eligiblesSelector.Description + "_" + this.description_GetDescriptionForChooser(); return description; } } public bool StopBacktestIfMaxRunningHoursHasBeenReached { get { return true; } } private void pvoStrategy(IEligiblesSelector eligiblesSelector, int inSampleDays, int numDaysForOscillatingPeriod, int numberOfTickersToBeChosen, Benchmark benchmark, int numDaysBetweenEachOptimization, HistoricalQuoteProvider historicalQuoteProvider, double maxAcceptableCloseToCloseDrawdown, double minimumAcceptableGain) { this.eligiblesSelector = eligiblesSelector; this.inSampleDays = inSampleDays; this.numDaysForOscillatingPeriod = numDaysForOscillatingPeriod; this.numberOfTickersToBeChosen = numberOfTickersToBeChosen; this.benchmark = benchmark; this.numDaysBetweenEachOptimization = numDaysBetweenEachOptimization; this.historicalQuoteProvider = historicalQuoteProvider; this.maxAcceptableCloseToCloseDrawdown = maxAcceptableCloseToCloseDrawdown; this.minimumAcceptableGain = minimumAcceptableGain; this.stopLossConditionReached = false; this.currentAccountValue = 0.0; this.previousAccountValue = 0.0; this.portfolioHasBeenOverbought = false; this.portfolioHasBeenOversold = false; } public PVOStrategy(IEligiblesSelector eligiblesSelector, IInSampleChooser inSampleChooser, int inSampleDays, int numDaysForOscillatingPeriod, int numberOfTickersToBeChosen, Benchmark benchmark, int numDaysBetweenEachOptimization, HistoricalQuoteProvider historicalQuoteProvider, double maxAcceptableCloseToCloseDrawdown, double minimumAcceptableGain) { this.pvoStrategy(eligiblesSelector, inSampleDays , numDaysForOscillatingPeriod , numberOfTickersToBeChosen , benchmark , numDaysBetweenEachOptimization , historicalQuoteProvider , maxAcceptableCloseToCloseDrawdown , minimumAcceptableGain ); this.inSampleChooser = inSampleChooser; } public PVOStrategy(IEligiblesSelector eligiblesSelector, TestingPositions[] chosenPVOPositions, int inSampleDays, int numDaysForOscillatingPeriod, int numberOfTickersToBeChosen, Benchmark benchmark, int numDaysBetweenEachOptimization, HistoricalQuoteProvider historicalQuoteProvider, double maxAcceptableCloseToCloseDrawdown, double minimumAcceptableGain) { this.pvoStrategy(eligiblesSelector, inSampleDays , numDaysForOscillatingPeriod , numberOfTickersToBeChosen , benchmark , numDaysBetweenEachOptimization , historicalQuoteProvider , maxAcceptableCloseToCloseDrawdown , minimumAcceptableGain ); this.chosenPVOPositions = chosenPVOPositions; } public virtual void MarketOpenEventHandler( Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { ; } public void FiveMinutesBeforeMarketCloseEventHandler( Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { } private EndOfDayDateTime now() { return this.account.EndOfDayTimer.GetCurrentTime(); } #region MarketCloseEventHandler //forOutOfSampleTesting protected virtual EndOfDayDateTime getBeginOfOscillatingPeriod(IndexBasedEndOfDayTimer timer) { return new EndOfDayDateTime( (DateTime)timer.IndexQuotes.Rows[timer.CurrentDateArrayPosition-this.numDaysForOscillatingPeriod]["quDate"], EndOfDaySpecificTime.MarketClose ); } private void marketCloseEventHandler_reverseIfNeeded_reverse(PVOPositionsStatus currentStatus) { if(currentStatus == PVOPositionsStatus.Overbought) { this.portfolioHasBeenOversold = false; this.portfolioHasBeenOverbought = true; } else if(currentStatus == PVOPositionsStatus.Oversold) { this.portfolioHasBeenOversold = true; this.portfolioHasBeenOverbought = false; } AccountManager.ReversePositions(this.account); this.previousAccountValue = this.account.GetMarketValue(); } private void marketCloseEventHandler_reverseIfNeeded(IndexBasedEndOfDayTimer timer) { EndOfDayDateTime today = timer.GetCurrentTime(); EndOfDayDateTime beginOfOscillatingPeriod = this.getBeginOfOscillatingPeriod(timer); PVOPositionsStatus pvoPositionsStatus = this.pvoPositionsForOutOfSample.GetStatus(beginOfOscillatingPeriod, today , this.benchmark.Ticker, this.historicalQuoteProvider); if(pvoPositionsStatus == PVOPositionsStatus.Overbought && this.portfolioHasBeenOversold) //open positions derive from an overSold period but now //the overbought threshold has been reached this.marketCloseEventHandler_reverseIfNeeded_reverse(pvoPositionsStatus); if(pvoPositionsStatus == PVOPositionsStatus.Oversold && this.portfolioHasBeenOverbought) //open positions derive from an overBought period but now //the overSold threshold has been reached this.marketCloseEventHandler_reverseIfNeeded_reverse(pvoPositionsStatus); } private PVOPositionsStatus marketCloseEventHandler_openPositions_getStatus(IndexBasedEndOfDayTimer timer) { EndOfDayDateTime today = timer.GetCurrentTime(); EndOfDayDateTime beginOfOscillatingPeriod = this.getBeginOfOscillatingPeriod(timer); PVOPositionsStatus currentStatus = PVOPositionsStatus.InTheMiddle; for(int i = 0; i<this.chosenPVOPositions.Length; i++) { if(this.chosenPVOPositions[i] != null) currentStatus = ((PVOPositions)this.chosenPVOPositions[i]).GetStatus(beginOfOscillatingPeriod, today, this.benchmark.Ticker, this.historicalQuoteProvider); if(currentStatus == PVOPositionsStatus.Oversold || currentStatus == PVOPositionsStatus.Overbought ) { this.pvoPositionsForOutOfSample = (PVOPositions)this.chosenPVOPositions[i]; i = this.chosenPVOPositions.Length;//exit from for } } return currentStatus; } protected void marketCloseEventHandler_openPositions(IndexBasedEndOfDayTimer timer) { PVOPositionsStatus pvoPositionsStatus = PVOPositionsStatus.InTheMiddle; if(timer.CurrentDateArrayPosition >= this.numDaysForOscillatingPeriod) pvoPositionsStatus = this.marketCloseEventHandler_openPositions_getStatus(timer); switch (pvoPositionsStatus){ case PVOPositionsStatus.Overbought: { #region manage Overbought case this.pvoPositionsForOutOfSample.WeightedPositions.Reverse(); try{ AccountManager.OpenPositions( this.pvoPositionsForOutOfSample.WeightedPositions, this.account ); this.portfolioHasBeenOverbought = true; this.portfolioHasBeenOversold = false; this.previousAccountValue = this.account.GetMarketValue(); } catch(Exception ex){ ex = ex; } finally{ this.pvoPositionsForOutOfSample.WeightedPositions.Reverse(); } #endregion break; } case PVOPositionsStatus.Oversold: { #region manage Oversold case AccountManager.OpenPositions( this.pvoPositionsForOutOfSample.WeightedPositions, this.account ); this.portfolioHasBeenOverbought = false; this.portfolioHasBeenOversold = true; this.previousAccountValue = this.account.GetMarketValue(); #endregion break; } case PVOPositionsStatus.InTheMiddle://that is { //pvoPositionsForOutOfSample has not been set this.previousAccountValue = this.account.GetMarketValue(); break; } default: { //it should never been reached this.previousAccountValue = this.account.GetMarketValue(); break; } } } protected virtual void marketCloseEventHandler_closePositionsIfNeeded() { if(this.stopLossConditionReached || this.takeProfitConditionReached || this.numDaysElapsedSinceLastOptimization + 1 == this.numDaysBetweenEachOptimization ) { AccountManager.ClosePositions(this.account); this.portfolioHasBeenOverbought = false; this.portfolioHasBeenOversold = false; } } protected virtual void marketCloseEventHandler_updateStopLossAndTakeProfitConditions() { //this.previousAccountValue has been set at opening positions this.stopLossConditionReached = false; this.takeProfitConditionReached = false; this.currentAccountValue = this.account.GetMarketValue(); double portfolioGainOrLoss = (this.currentAccountValue - this.previousAccountValue) /this.previousAccountValue; if(!double.IsInfinity(portfolioGainOrLoss) && portfolioGainOrLoss <= -this.maxAcceptableCloseToCloseDrawdown ) { this.stopLossConditionReached = true; this.takeProfitConditionReached = false; } else if (!double.IsInfinity(portfolioGainOrLoss) && portfolioGainOrLoss >= this.minimumAcceptableGain ) { this.stopLossConditionReached = false; this.takeProfitConditionReached = true; } } public virtual void MarketCloseEventHandler( Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { try{ this.marketCloseEventHandler_updateStopLossAndTakeProfitConditions(); this.marketCloseEventHandler_closePositionsIfNeeded(); if( this.chosenPVOPositions != null ) //PVOPositions have been chosen by the chooser { if(this.account.Portfolio.Count == 0) this.marketCloseEventHandler_openPositions((IndexBasedEndOfDayTimer)sender); //positions are opened only if thresholds are reached else//there are some opened positions this.marketCloseEventHandler_reverseIfNeeded((IndexBasedEndOfDayTimer)sender); } } catch(TickerNotExchangedException ex) {ex=ex;} } #endregion #region OneHourAfterMarketCloseEventHandler protected virtual void updateReturnsManager(EndOfDayDateTime firstEndOfDayDateTime, EndOfDayDateTime lastEndOfDayDateTime) { this.returnsManager = new ReturnsManager(new CloseToCloseIntervals(firstEndOfDayDateTime, lastEndOfDayDateTime, this.benchmark.Ticker, this.numDaysForOscillatingPeriod), this.historicalQuoteProvider); } private PVOLogItem getLogItem( EligibleTickers eligibleTickers ) { PVOLogItem logItem = new PVOLogItem( this.now() ); logItem.BestPVOPositionsInSample = this.chosenPVOPositions; logItem.NumberOfEligibleTickers = eligibleTickers.Count; logItem.FitnessOfFirst = this.chosenPVOPositions[0].FitnessInSample; logItem.FitnessOfLast = this.chosenPVOPositions[this.chosenPVOPositions.Length - 1].FitnessInSample; logItem.GenerationOfFirst = ((IGeneticallyOptimizable)this.chosenPVOPositions[0]).Generation; logItem.GenerationOfLast = ((IGeneticallyOptimizable)this.chosenPVOPositions[this.chosenPVOPositions.Length - 1]).Generation; logItem.ThresholdsOfFirst = ((PVOPositions)this.chosenPVOPositions[0]).OversoldThreshold.ToString() + ";" + ((PVOPositions)this.chosenPVOPositions[0]).OverboughtThreshold.ToString(); logItem.ThresholdsOfLast = ((PVOPositions)this.chosenPVOPositions[this.chosenPVOPositions.Length - 1]).OversoldThreshold.ToString() + ";" + ((PVOPositions)this.chosenPVOPositions[this.chosenPVOPositions.Length - 1]).OverboughtThreshold.ToString(); logItem.TickersOfFirst = this.chosenPVOPositions[0].HashCodeForTickerComposition; logItem.TickersOfLast = this.chosenPVOPositions[this.chosenPVOPositions.Length - 1].HashCodeForTickerComposition; return logItem; } private void raiseNewLogItem( EligibleTickers eligibleTickers ) { PVOLogItem logItem = this.getLogItem( eligibleTickers ); NewLogItemEventArgs newLogItemEventArgs = new NewLogItemEventArgs( logItem ); this.NewLogItem( this , newLogItemEventArgs ); } 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 ); } private void logOptimizationInfo( EligibleTickers eligibleTickers ) { this.raiseNewLogItem( eligibleTickers ); this.notifyMessage( eligibleTickers ); } protected virtual void updateTestingPositions(DateTime currentDate) { EndOfDayHistory endOfDayHistory = this.benchmark.GetEndOfDayHistory( new EndOfDayDateTime(currentDate.AddDays(-this.inSampleDays), EndOfDaySpecificTime.MarketClose), new EndOfDayDateTime(currentDate, EndOfDaySpecificTime.MarketClose)); EligibleTickers eligibles = this.eligiblesSelector.GetEligibleTickers(endOfDayHistory); this.updateReturnsManager(endOfDayHistory.FirstEndOfDayDateTime, endOfDayHistory.LastEndOfDayDateTime); if(this.inSampleChooser != null) this.chosenPVOPositions = (TestingPositions[])inSampleChooser.AnalyzeInSample(eligibles, this.returnsManager ); this.logOptimizationInfo(eligibles); } /// <summary> /// Handles a "One hour after market close" event. /// </summary> /// <param name="sender"></param> /// <param name="eventArgs"></param> public virtual void OneHourAfterMarketCloseEventHandler( Object sender , EndOfDayTimingEventArgs endOfDayTimingEventArgs ) { this.lastCloseDate = endOfDayTimingEventArgs.EndOfDayDateTime.DateTime; this.numDaysElapsedSinceLastOptimization++; if((this.numDaysElapsedSinceLastOptimization == this.numDaysBetweenEachOptimization)) //num days without optimization has elapsed { this.updateTestingPositions(endOfDayTimingEventArgs.EndOfDayDateTime.DateTime); //sets tickers to be chosen next Market Close event this.numDaysElapsedSinceLastOptimization = 0; } } #endregion } } --- NEW FILE: PVOLogItem.cs --- /* QuantProject - Quantitative Finance Library PVOLogItem.cs Copyright (C) 2008 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 QuantProject.Business.DataProviders; using QuantProject.Business.Strategies; using QuantProject.Business.Strategies.Eligibles; using QuantProject.Business.Strategies.InSample; using QuantProject.Business.Strategies.OutOfSample; using QuantProject.Business.Strategies.Logging; using QuantProject.Business.Strategies.ReturnsManagement.Time; using QuantProject.Business.Strategies.ReturnsManagement.Time.IntervalsSelectors; using QuantProject.Business.Timing; using QuantProject.Scripts.General.Reporting; namespace QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator { /// <summary> /// LogItem for the PVO strategy /// portfolio value oscillator strategy /// </summary> [Serializable] public class PVOLogItem : LogItem { // static public Random rand = new Random(4676); private TestingPositions[] bestPVOPositionsInSample; private int numberOfEligibleTickers; private double fitnessOfFirstPVOPositionsInSample; private double fitnessOfLastPVOPositionsInSample; private int generationOfFirstPVOPositionsInSample; private int generationOfLastPVOPositionsInSample; private string thresholdsOfFirst; private string thresholdsOfLast; private string tickersOfFirst; private string tickersOfLast; public TestingPositions[] BestPVOPositionsInSample { get { if ( this.bestPVOPositionsInSample == null ) throw new Exception( "This property has not " + "been assigned yet! If you are loading the LogItem from " + "a log, this property was not set before logging the LogItem." ); return this.bestPVOPositionsInSample; } set { this.bestPVOPositionsInSample = value; } } public int NumberOfEligibleTickers { get { if ( this.numberOfEligibleTickers == int.MinValue ) throw new Exception( "This property has not " + "been assigned yet! If you are loading the LogItem from " + "a log, this property was not set before logging the LogItem." ); return this.numberOfEligibleTickers; } set { this.numberOfEligibleTickers = value; } } public double FitnessOfFirst { get { if ( this.fitnessOfFirstPVOPositionsInSample == double.MinValue ) throw new Exception( "This property has not " + "been assigned yet! If you are loading the LogItem from " + "a log, this property was not set before logging the LogItem." ); return this.fitnessOfFirstPVOPositionsInSample; } set { this.fitnessOfFirstPVOPositionsInSample = value; } } public double FitnessOfLast { get { if ( this.fitnessOfLastPVOPositionsInSample == double.MinValue ) throw new Exception( "This property has not " + "been assigned yet! If you are loading the LogItem from " + "a log, this property was not set before logging the LogItem." ); return this.fitnessOfLastPVOPositionsInSample; } set { this.fitnessOfLastPVOPositionsInSample = value; } } public int GenerationOfFirst { get{return this.generationOfFirstPVOPositionsInSample;} set{this.generationOfFirstPVOPositionsInSample = value;} } public int GenerationOfLast { get{return this.generationOfLastPVOPositionsInSample;} set{this.generationOfLastPVOPositionsInSample = value;} } public string ThresholdsOfFirst { get{return this.thresholdsOfFirst;} set{this.thresholdsOfFirst = value;} } public string ThresholdsOfLast { get{return this.thresholdsOfLast;} set{this.thresholdsOfLast = value;} } public string TickersOfFirst { get{return this.tickersOfFirst;} set{this.tickersOfFirst = value;} } public string TickersOfLast { get{return this.tickersOfLast;} set{this.tickersOfLast = value;} } public PVOLogItem(EndOfDayDateTime endOfDayDateTime ) : base( endOfDayDateTime ) { this.numberOfEligibleTickers = int.MinValue; this.fitnessOfFirstPVOPositionsInSample = double.MinValue; this.fitnessOfLastPVOPositionsInSample = double.MinValue; } public override void Run() { //general int inSampleDays = 120; DateTime firstDateTime = this.SimulatedCreationTime.DateTime.AddDays(-inSampleDays); DateTime lastDateTime = this.SimulatedCreationTime.DateTime; double maxRunningHours = 1; Benchmark benchmark = new Benchmark( "^GSPC" ); // definition for the Fitness Evaluator (for // objects that use it) int numDaysForOscillatingPeriodForChooser = ((PVOPositions)this.BestPVOPositionsInSample[0]).NumDaysForOscillatingPeriod; int numberOfPortfolioPositions = this.BestPVOPositionsInSample[0].WeightedPositions.Count; //cash and portfolio type double cashToStart = 30000; double maxAcceptableCloseToCloseDrawdown = 0.02; double minimumAcceptableGain = 0.007; HistoricalQuoteProvider historicalQuoteProviderForBackTester, historicalQuoteProviderForInSampleChooser, historicalQuoteProviderForStrategy; historicalQuoteProviderForBackTester = new HistoricalAdjustedQuoteProvider(); historicalQuoteProviderForInSampleChooser = historicalQuoteProviderForBackTester; historicalQuoteProviderForStrategy = historicalQuoteProviderForInSampleChooser; IEligiblesSelector eligiblesSelector = new DummyEligibleSelector(); //strategyParameters int numDaysForOscillatingPeriodForOutOfSample = numDaysForOscillatingPeriodForChooser; TestingPositions[] positionsToTest = new TestingPositions[1]; // int idx = PVOLogItem.rand.Next(bestPVOPositionsInSample.Length); positionsToTest[0] = this.bestPVOPositionsInSample[0]; PVOStrategy strategy = new PVOStrategy(eligiblesSelector, positionsToTest, inSampleDays, numDaysForOscillatingPeriodForOutOfSample, numberOfPortfolioPositions , benchmark , int.MaxValue , historicalQuoteProviderForStrategy , maxAcceptableCloseToCloseDrawdown , minimumAcceptableGain ); EndOfDayStrategyBackTester endOfDayStrategyBackTester = new EndOfDayStrategyBackTester( "PVO" , strategy , historicalQuoteProviderForBackTester , firstDateTime , lastDateTime , benchmark , cashToStart , maxRunningHours ); // TO DO check if you can do this assign in the EndOfDayStrategyBackTester // constructor strategy.Account = endOfDayStrategyBackTester.Account; endOfDayStrategyBackTester.Run(); BackTesterReportViewer.ShowReport( lastDateTime , endOfDayStrategyBackTester ); } } } --- NEW FILE: PVOPositionsStatus.cs --- /* QuantProject - Quantitative Finance Library PVOPositionsStatus.cs Copyright (C) 2008 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; namespace QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator { /// <summary> /// Specifies in which status a given PVOPositions /// is /// </summary> [Serializable] public enum PVOPositionsStatus { Oversold, InTheMiddle, Overbought, TooDistantFromThresholds } } --- NEW FILE: PVOMain.cs --- /* QuantProject - Quantitative Finance Library PVOMain.cs Copyright (C) 2008 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.IO; using QuantProject.ADT; using QuantProject.ADT.FileManaging; using QuantProject.Business.DataProviders; using QuantProject.Business.Strategies; using QuantProject.Business.Strategies.Eligibles; using QuantProject.Business.Strategies.EquityEvaluation; using QuantProject.Business.Strategies.Logging; using QuantProject.Business.Strategies.Optimizing.Decoding; using QuantProject.Business.Strategies.Optimizing.FitnessEvaluation; using QuantProject.Business.Strategies.ReturnsManagement; using QuantProject.Business.Strategies.ReturnsManagement.Time; using QuantProject.Business.Strategies.ReturnsManagement.Time.IntervalsSelectors; using QuantProject.Business.Timing; using QuantProject.Presentation; using QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator.InSampleChoosers; using QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator.Decoding; using QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator.FitnessEvaluators; using QuantProject.Scripts.General.Logging; using QuantProject.Scripts.General.Reporting; namespace QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator { /// <summary> /// Entry point for the PVO strategy. If any strategy /// parameter had to be changed, this is the place where it should /// be done /// </summary> public class PVOMain { private string strategyIdentifier; private string fileNameWithoutExt; private string dirNameWhereToSaveResults; public PVOMain() { this.strategyIdentifier = "PVO"; } private void setFileNamesAndDirectory(EndOfDayStrategyBackTester endOfDayStrategyBackTester) { if(this.fileNameWithoutExt == null) { this.fileNameWithoutExt = this.strategyIdentifier + "_" + DateTime.Now.Hour.ToString().PadLeft(2,'0') + "_" + DateTime.Now.Minute.ToString().PadLeft(2,'0') + "_" + DateTime.Now.Second.ToString().PadLeft(2,'0'); this.dirNameWhereToSaveResults = System.Configuration.ConfigurationSettings.AppSettings["LogArchive"] + "\\" + fileNameWithoutExt + "\\"; if( !Directory.Exists(dirNameWhereToSaveResults) ) Directory.CreateDirectory(dirNameWhereToSaveResults); } } #region Run private MessageManager setMessageManager( IEligiblesSelector eligiblesSelector , IInSampleChooser inSampleChooser , IEndOfDayStrategy endOfDayStrategy , EndOfDayStrategyBackTester endOfDayStrategyBackTester ) { this.setFileNamesAndDirectory(endOfDayStrategyBackTester); string fullPathFileNameForMessagesLog = dirNameWhereToSaveResults + this.fileNameWithoutExt + "LogMessages.txt"; MessageManager messageManager = new MessageManager( fullPathFileNameForMessagesLog ); messageManager.Monitor( eligiblesSelector ); messageManager.Monitor( inSampleChooser ); // messageManager.Monitor( endOfDayStrategy ); messageManager.Monitor( endOfDayStrategyBackTester ); return messageManager; } // TO DO check if you can add this to QuantProject.Presentation.Reporting.WindowsForm.Report // as a public method or as a new constructor // private void showReport( // DateTime lastDateTimeRequestedForTheScript , // EndOfDayStrategyBackTester endOfDayStrategyBackTester ) // { //// DateTime lastReportDateTime = ExtendedDateTime.Min( //// lastDateTimeRequestedForTheScript , //// endOfDayStrategyBackTester.EndOfDayTimer.GetCurrentTime().DateTime ); // DateTime lastReportDateTime = // endOfDayStrategyBackTester.ActualLastDateTime; // Report report = new Report( // endOfDayStrategyBackTester.AccountReport , // true ); // report.Create( endOfDayStrategyBackTester.DescriptionForLogFileName , 1 , // new EndOfDayDateTime( lastReportDateTime , // EndOfDaySpecificTime.OneHourAfterMarketClose ) , // endOfDayStrategyBackTester.Benchmark.Ticker ); // report.Show(); // } //Saves (in silent mode): //- a log file where the In Sample Analysis are // stored; //- a report; //- a txt file with a full description of the // strategy's features private void saveScriptResults( EndOfDayStrategyBackTester endOfDayStrategyBackTester ) { this.setFileNamesAndDirectory(endOfDayStrategyBackTester); string fullPathFileNameForLog = dirNameWhereToSaveResults + this.fileNameWithoutExt + ".qpL"; string fullPathFileNameForReport = dirNameWhereToSaveResults + this.fileNameWithoutExt + ".qpR"; string fullPathFileNameForParametersLog = dirNameWhereToSaveResults + this.fileNameWithoutExt + "_Parameters.txt"; ObjectArchiver.Archive(endOfDayStrategyBackTester.Log, fullPathFileNameForLog); ObjectArchiver.Archive(endOfDayStrategyBackTester.AccountReport, fullPathFileNameForReport); StreamWriter w = File.AppendText(fullPathFileNameForParametersLog); w.WriteLine ("\n---\r\n"); w.WriteLine ( endOfDayStrategyBackTester.Description ); w.WriteLine ("\n---\r\n"); w.Flush(); w.Close(); } public void Run() { //general DateTime firstDateTime = new DateTime( 2000 , 6 , 1 ); DateTime lastDateTime = new DateTime( 2000 , 7 , 31 ); double maxRunningHours = 5; Benchmark benchmark = new Benchmark( "^GSPC" ); // definition for the Fitness Evaluator (for // objects that use it) IEquityEvaluator equityEvaluator = new SharpeRatio(); //cash and portfolio type double cashToStart = 30000; int numberOfPortfolioPositions = 4; // parameters for the in sample Chooser double crossoverRate = 0.85; double mutationRate = 0.02; double elitismRate = 0.001; int populationSizeForGeneticOptimizer = 500; int generationNumberForGeneticOptimizer = 10; int numberOfBestTestingPositionsToBeReturnedInSample = 5; int seedForRandomGenerator = QuantProject.ADT.ConstantsProvider.SeedForRandomGenerator; int numDaysBetweenEachOptimization = 15; int minLevelForOversoldThreshold = 50; int maxLevelForOversoldThreshold = 100; int minLevelForOverboughtThreshold = 50; int maxLevelForOverboughtThreshold = 100; int divisorForThresholdComputation = 10000; int numDaysForOscillatingPeriodForChooser = 1; //for genetic optimization bool symmetricalThresholds = true; bool overboughtMoreThanOversoldForFixedPortfolio = false; double maxAcceptableCloseToCloseDrawdown = 0.03; double minimumAcceptableGain = 0.008; IDecoderForTestingPositions decoderForTestingPositions = new BasicDecoderForPVOPositions(symmetricalThresholds, divisorForThresholdComputation , numDaysForOscillatingPeriodForChooser); IFitnessEvaluator fitnessEvaluator = new PVOFitnessEvaluator( equityEvaluator ); HistoricalQuoteProvider historicalQuoteProviderForBackTester, historicalQuoteProviderForInSampleChooser, historicalQuoteProviderForStrategy; historicalQuoteProviderForBackTester = new HistoricalAdjustedQuoteProvider(); historicalQuoteProviderForInSampleChooser = historicalQuoteProviderForBackTester; historicalQuoteProviderForStrategy = historicalQuoteProviderForInSampleChooser; IInSampleChooser inSampleChooser = new PVOGeneticChooser(numDaysForOscillatingPeriodForChooser , numberOfPortfolioPositions , numberOfBestTestingPositionsToBeReturnedInSample, benchmark, decoderForTestingPositions , fitnessEvaluator , historicalQuoteProviderForInSampleChooser , crossoverRate , mutationRate , elitismRate , populationSizeForGeneticOptimizer , generationNumberForGeneticOptimizer , seedForRandomGenerator , minLevelForOversoldThreshold , maxLevelForOversoldThreshold , minLevelForOverboughtThreshold , maxLevelForOverboughtThreshold , divisorForThresholdComputation , symmetricalThresholds , overboughtMoreThanOversoldForFixedPortfolio ); //parameters for eligiblesSelector bool temporizedGroup = true; double minRawOpenPrice = 25; double maxRawOpenPrice = 500; int numDaysForAverageOpenRawPrice = 20; string tickersGroupId = "SP500"; int maxNumberOfEligiblesToBeChosen = 100; IEligiblesSelector eligiblesSelector = new ByPriceMostLiquidAlwaysQuoted( tickersGroupId , temporizedGroup, maxNumberOfEligiblesToBeChosen, numDaysForAverageOpenRawPrice , minRawOpenPrice , maxRawOpenPrice ); //strategyParameters int inSampleDays = 120; int numDaysForOscillatingPeriodForOutOfSampleChoosing = numDaysForOscillatingPeriodForChooser; PVOStrategy strategy = new PVOStrategy(eligiblesSelector, inSampleChooser, inSampleDays, numDaysForOscillatingPeriodForOutOfSampleChoosing, numberOfPortfolioPositions , benchmark , numDaysBetweenEachOptimization , historicalQuoteProviderForStrategy , maxAcceptableCloseToCloseDrawdown , minimumAcceptableGain ); EndOfDayStrategyBackTester endOfDayStrategyBackTester = new EndOfDayStrategyBackTester( this.strategyIdentifier , strategy , historicalQuoteProviderForBackTester , firstDateTime , lastDateTime , benchmark , cashToStart , maxRunningHours ); // TO DO check if you can do this assign in the EndOfDayStrategyBackTester // constructor strategy.Account = endOfDayStrategyBackTester.Account; MessageManager messageManager = this.setMessageManager( eligiblesSelector , inSampleChooser , strategy , endOfDayStrategyBackTester ); endOfDayStrategyBackTester.Run(); this.saveScriptResults(endOfDayStrategyBackTester); } #endregion Run public void Run1() { BackTestLog backTestLog = LogArchiver.Load( System.Configuration.ConfigurationSettings.AppSettings["LogArchive"] ); LogViewer logViewer = new LogViewer( backTestLog ); logViewer.Show(); } } } --- NEW FILE: PVOPositions.cs --- /* QuantProject - Quantitative Finance Library PVOPositions.cs Copyright (C) 2008 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 QuantProject.Business.Strategies; using QuantProject.Business.Strategies.OutOfSample; using QuantProject.Business.Strategies.ReturnsManagement; using QuantProject.Business.Strategies.ReturnsManagement.Time; using QuantProject.Business.Timing; using QuantProject.Business.DataProviders; namespace QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator { /// <summary> /// This is the class representing a TestingPositions for the /// portfolio value oscillator strategy /// </summary> [Serializable] public class PVOPositions : TestingPositions, IGeneticallyOptimizable { private double oversoldThreshold; private double overboughtThreshold; private int numDaysForOscillatingPeriod; private int generation; private static ReturnsManager returnsManager; public double OversoldThreshold { get{return this.oversoldThreshold;} set{this.oversoldThreshold = value;} } public double OverboughtThreshold { get{return this.overboughtThreshold;} set{this.overboughtThreshold = value;} } public int NumDaysForOscillatingPeriod { get{return this.numDaysForOscillatingPeriod;} } //explicit interface implementation //the property can be used only by a interface //instance or through a cast to the interface int IGeneticallyOptimizable.Generation { get{return this.generation;} set{this.generation = value;} } public PVOPositions Copy() { return new PVOPositions(this.WeightedPositions,this.OversoldThreshold, this.overboughtThreshold, this.numDaysForOscillatingPeriod); } public PVOPositions(WeightedPositions weightedPositions, double oversoldThreshold, double overboughtThreshold, int numDaysForOscillatingPeriod) : base(weightedPositions) { this.oversoldThreshold = oversoldThreshold; this.overboughtThreshold = overboughtThreshold; this.numDaysForOscillatingPeriod = numDaysForOscillatingPeriod; this.generation = -1; } private void setReturnsManager(EndOfDayDateTime beginOfPeriod, EndOfDayDateTime endOfPeriod, string benchmark, HistoricalQuoteProvider quoteProvider) { if(PVOPositions.returnsManager == null || PVOPositions.returnsManager.ReturnIntervals[0].Begin != beginOfPeriod || PVOPositions.returnsManager.ReturnIntervals[0].End != endOfPeriod) //if a returnsManager has not been set yet or a different one has to be set //for a different returnInterval PVOPositions.returnsManager = new ReturnsManager(new ReturnIntervals( new ReturnInterval( beginOfPeriod, endOfPeriod ) ) , quoteProvider ); } private double getOscillatingPeriodReturn(EndOfDayDateTime beginOfPeriod, EndOfDayDateTime endOfPeriod, string benchmark, HistoricalQuoteProvider quoteProvider) { this.setReturnsManager(beginOfPeriod, endOfPeriod, benchmark, quoteProvider); return this.WeightedPositions.GetReturn(0, PVOPositions.returnsManager); } public PVOPositionsStatus GetStatus(EndOfDayDateTime beginOfPeriod, EndOfDayDateTime endOfPeriod, string benchmark, HistoricalQuoteProvider quoteProvider, double maxCoefficientOfCrossingThresholds) { PVOPositionsStatus returnValue; double oscillatingPeriodReturn = double.NaN; oscillatingPeriodReturn = this.getOscillatingPeriodReturn(beginOfPeriod, endOfPeriod, benchmark, quoteProvider); if(oscillatingPeriodReturn >= this.overboughtThreshold && oscillatingPeriodReturn <= maxCoefficientOfCrossingThresholds*this.overboughtThreshold) returnValue = PVOPositionsStatus.Overbought; else if(oscillatingPeriodReturn <= -this.oversoldThreshold && Math.Abs(oscillatingPeriodReturn)<=maxCoefficientOfCrossingThresholds*this.oversoldThreshold) returnValue = PVOPositionsStatus.Oversold; else if ( Math.Abs(oscillatingPeriodReturn) > maxCoefficientOfCrossingThresholds*this.oversoldThreshold || oscillatingPeriodReturn > maxCoefficientOfCrossingThresholds*this.overboughtThreshold ) returnValue = PVOPositionsStatus.TooDistantFromThresholds; else returnValue = PVOPositionsStatus.InTheMiddle; return returnValue; } public PVOPositionsStatus GetStatus(EndOfDayDateTime beginOfPeriod, EndOfDayDateTime endOfPeriod, string benchmark, HistoricalQuoteProvider quoteProvider) { return this.GetStatus(beginOfPeriod, endOfPeriod , benchmark, quoteProvider, 10000.0); //a very high maxCoefficientOfCrossingThresholds is given: //so the status TooDistantFromThresholds should never been reached } public bool AreAllTickersMovingTogetherUpOrDown(EndOfDayDateTime beginOfPeriod, EndOfDayDateTime endOfPeriod, string benchmark, HistoricalQuoteProvider quoteProvider) { bool returnValue = true; SignedTickers signedTickers = this.WeightedPositions.SignedTickers; float returnOfCurrentTicker, returnOfNextTicker; this.setReturnsManager(beginOfPeriod, endOfPeriod, benchmark, quoteProvider); for( int i = 0; signedTickers.Count > 1 && i < signedTickers.Count - 1 && returnValue == true; i++ ) { returnOfCurrentTicker = PVOPositions.returnsManager.GetReturn(signedTickers[ i ].Ticker, 0); returnOfNextTicker = PVOPositions.returnsManager.GetReturn(signedTickers[ i+1 ].Ticker, 0); if( (returnOfCurrentTicker > 0 && returnOfNextTicker < 0) || (returnOfCurrentTicker < 0 && returnOfNextTicker > 0) ) returnValue = false; } return returnValue; } } } --- NEW FILE: PVOGenomeManager.cs --- /* QuantProject - Quantitative Finance Library PVOGenomeManager.cs Copyright (C) 2008 Marco Milletti This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ using System; using System.Data; using System.Collections; using QuantProject.ADT; using QuantProject.ADT.Statistics; using QuantProject.ADT.Optimizing.Genetic; using QuantProject.Data; using QuantProject.Data.DataTables; using QuantProject.Business.DataProviders; using QuantProject.Business.Timing; using QuantProject.Business.Strategies; using QuantProject.Business.Strategies.ReturnsManagement; using QuantProject.Business.Strategies.ReturnsManagement.Time; using QuantProject.Business.Strategies.TickersRelationships; using QuantProject.Business.Strategies.Eligibles; using QuantProject.Business.Strategies.Optimizing.FitnessEvaluation; using QuantProject.Business.Strategies.Optimizing.Decoding; using QuantProject.Business.Strategies.Optimizing.GenomeManagers; using QuantProject.Scripts.TickerSelectionTesting.EfficientPortfolios; namespace QuantProject.Scripts.TechnicalAnalysisTesting.Oscillators.FixedLevelOscillators.PortfolioValueOscillator { /// <summary> /// Implements what needed to use the Genetic Optimizer /// for finding the portfolio that best suites /// the Portfolio Value Oscillator strategy /// </summary> [Serializable] public class PVOGenomeManager : BasicGenomeManager { protected int minLevelForOversoldThreshold; protected int maxLevelForOversoldThreshold; protected int minLevelForOverboughtThreshold; protected int maxLevelForOverboughtThreshold; protected int divisorForThresholdComputation; protected bool symmetricalThresholds; protected bool overboughtMoreThanOversoldForFixedPortfolio; protected int numOfGenesDedicatedToThresholds; protected int numDaysForOscillatingPeriod; protected CorrelationProvider correlationProvider;//used for experimental //tests using 2 tickers and PearsonCorrelationCoefficient as fitness private void genomeManagerPVO_checkParametersForThresholdsComputation() { if(this.maxLevelForOverboughtThreshold < this.minLevelForOverboughtThreshold || this.maxLevelForOversoldThreshold < this.minLevelForOversoldThreshold || this.divisorForThresholdComputation < this.maxLevelForOverboughtThreshold || this.divisorForThresholdComputation < this.maxLevelForOversoldThreshold || (this.symmetricalThresholds && (this.minLevelForOversoldThreshold != this.minLevelForOverboughtThreshold || this.maxLevelForOversoldThreshold != this.maxLevelForOverboughtThreshold) ) || (this.overboughtMoreThanOversoldForFixedPortfolio && (this.minLevelForOverboughtThreshold > Convert.ToInt32(Convert.ToDouble(this.minLevelForOversoldThreshold)* Convert.ToDouble(this.divisorForThresholdComputation) / (Convert.ToDouble(this.divisorForThresholdComputation) - Convert.ToDouble(this.minLevelForOversoldThreshold) ) ) || this.maxLevelForOverboughtThreshold < Convert.ToInt32(Convert.ToDouble(this.maxLevelForOversoldThreshold) * Convert.ToDouble(this.divisorForThresholdComputation) / (Convert.ToDouble(this.divisorForThresholdComputation) - Convert.ToDouble(this.maxLevelForOversoldThreshold) ) ) ) ) ) throw new Exception("Bad parameters for thresholds computation!"); } public PVOGenomeManager(EligibleTickers eligibleTickers, int numberOfTickersInPortfolio, int numDaysForOscillatingPeriod, int minLevelForOversoldThreshold, int maxLevelForOversoldThreshold, int minLevelForOverboughtThreshold, int maxLevelForOverboughtThreshold, int divisorForThresholdComputation, IDecoderForTestingPositions decoderForTestingPositions, IFitnessEvaluator fitnessEvaluator, bool symmetricalThresholds, bool overboughtMoreThanOversoldForFixedPortfolio, GenomeManagerType genomeManagerType, ReturnsManager returnsManager, int seedForRandomGenerator) : base(eligibleTickers, numberOfTickersInPortfolio, decoderForTestingPositions, fitnessEvaluator, genomeManagerType, returnsManager, seedForRandomGenerator) { this.numDaysForOscillatingPeriod = numDaysForOscillatingPeriod; this.divisorForThresholdComputation = divisorForThresholdComputation; this.decoderForTestingPositions = decoderForTestingPositions; this.minLevelForOversoldThreshold = minLevelForOversoldThreshold; this.maxLevelForOversoldThreshold = maxLevelForOversoldThreshold; this.minLevelForOverboughtThreshold = minLevelForOverboughtThreshold; this.maxLevelForOverboughtThreshold = maxLevelForOverboughtThreshold; this.symmetricalThresholds = symmetricalThresholds; this.overboughtMoreThanOversoldForFixedPortfolio = overboughtMoreThanOversoldForFixedPortfolio; if(this.symmetricalThresholds)//value for thresholds must be unique numOfGenesDedicatedToThresholds = 1; else numOfGenesDedicatedToThresholds = 2; this.genomeManagerPVO_checkParametersForThresholdsComputation(); } public override int GenomeSize { get{return this.genomeSize + this.numOfGenesDedicatedToThresholds;} } #region Get Min and Max Value private int getMinValueForGenes_getMinValueForTicker() { int returnValue; switch (this.genomeManagerType) { case GenomeManagerType.OnlyLong : returnValue = 0; break; default://For ShortAndLong or OnlyShort portfolios returnValue = - this.eligibleTickers.Count; break; } return returnValue; } public override int GetMinValueForGenes(int genePosition) { int returnValue; switch (genePosition) { case 0 ://gene for oversold threshold returnValue = this.minLevelForOversoldThreshold; break; case 1 ://gene for overbought threshold if(this.numOfGenesDedicatedToThresholds == 2) returnValue = this.minLevelForOverboughtThreshold; else returnValue = this.getMinValueForGenes_getMinValueForTicker(); break; default://gene for ticker returnValue = this.getMinValueForGenes_getMinValueForTicker(); break; } return returnValue; } private int getMaxValueForGenes_getMaxValueForTicker() { int returnValue; switch (this.genomeManagerType) { case GenomeManagerType.OnlyShort : returnValue = - 1; break; default ://For ShortAndLong or OnlyLong portfolios returnValue = this.eligibleTickers.Count - 1; break; } return returnValue; } public override int GetMaxValueForGenes(int genePosition) { int returnValue; switch (genePosition) { case 0 ://gene for oversold threshold returnValue = this.maxLevelForOversoldThreshold; break; case 1 ://gene for overbought threshold if(this.numOfGenesDedicatedToThresholds == 2) returnValue = this.maxLevelForOverboughtThreshold; else returnValue = this.getMaxValueForGenes_getMaxValueForTicker(); break; default://gene for ticker returnValue = this.getMaxValueForGenes_getMaxValueForTicker(); break; } return returnValue; } #endregion public override Genome[] GetChilds(Genome parent1, Genome parent2) { //in this simple implementation //child have the tickers of one parent //and the thresholds of the other Genome[] childs = new Genome[2]; childs[0] = parent1.Clone(); childs[1] = parent2.Clone(); //exchange of genes coding thresholds if(this.symmetricalThresholds)//unique value for thresholds { childs[0].SetGeneValue(parent2.GetGeneValue(0),0); childs[1].SetGeneValue(parent1.GetGeneValue(0),0); } else//two different values for thresholds { childs[0].SetGeneValue(parent2.GetGeneValue(0),0); childs[1].SetGeneValue(parent1.GetGeneValue(0),0); childs[0].SetGeneValue(parent2.GetGeneValue(1),1); childs[1].SetGeneValue(parent1.GetGeneValue(1),1); } return childs; } public override int GetNewGeneValue(Genome genome, int genePosition) { // in this implementation only new gene values pointing to tickers // must be different from the others already stored int minValueForGene = genome.GetMinValueForGenes(genePosition); int maxValueForGene = genome.GetMaxValueForGenes(genePosition); int returnValue = GenomeManagement.RandomGenerator.Next(minValueForGene, maxValueForGene + 1); if(this.numOfGenesDedicatedToThresholds == 2 && this.overboughtMoreThanOversoldForFixedPortfolio && genePosition == 1) //genePosition points to overbought threshold, //dipendent from the oversold one such that the portfolio tends to be fix returnValue = Convert.ToInt32(Convert.ToDouble(genome.GetGeneValue(0)) * Convert.ToDouble(this.divisorForThresholdComputation) / (Convert.ToDouble(this.divisorForThresholdComputation) - Convert.ToDouble(genome.GetGeneValue(0)))); while(genePosition > this.numOfGenesDedicatedToThresholds - 1 && GenomeManipulator.IsTickerContainedInGenome(returnValue, genome, this.numOfGenesDedicatedToThresholds, genome.Size - 1)) //while in the given position has to be stored //a new gene pointing to a ticker and //the proposed returnValue points to a ticker //already stored in the given genome returnValue = GenomeManagement.RandomGenerator.Next(minValueForGene, maxValueForGene + 1); return returnValue; } public override void Mutate(Genome genome) { // in this implementation only one gene is mutated int genePositionToBeMutated = GenomeManagement.RandomGenerator.Next(genome.Size); int minValueForGene = genome.GetMinValueForGenes(genePositionToBeMutated); int maxValueForGene = genome.GetMaxValueForGenes(genePositionToBeMutated); int newValueForGene = GenomeManagement.RandomGenerator.Next(minValueForGene, maxValueForGene +1); while(genePositionToBeMutated > this.numOfGenesDedicatedToThresholds - 1 && GenomeManipulator.IsTickerContainedInGenome(newValueForGene, genome, this.numOfGenesDedicatedToThresholds, genome.Size - 1)) //while in the proposed genePositionToBeMutated has to be stored //a new gene pointing to a ticker and //the proposed newValueForGene points to a ticker //already stored in the given genome newValueForGene = GenomeManagement.RandomGenerator.Next(minValueForGene, maxValueForGene +1); //TODO add if when it is mutated a threshold //(just a single threshold or the pair of thresholds) if(genePositionToBeMutated > this.numOfGenesDedicatedToThresholds - 1) GenomeManagement.MutateOneGene(genome, genePositionToBeMutated, newValueForGene); } } } |