public void InitializeValuesFrom(ParameterDefinitions other) { foreach (ParameterDefinition pdNew in this) { ParameterDefinition pdOld = other.Find(pdNew); if (pdOld == null) { continue; } SetParameterDefinition spdOld = pdOld as SetParameterDefinition; SetParameterDefinition spdNew = pdNew as SetParameterDefinition; if (spdOld == null || spdNew == null) { continue; } spdNew.InitializeFrom(spdOld); } }
public override void Optimize() { bool fFirstRun = (_form == null); _rgParameterDefinitions = new ParameterDefinitions(this.Strategy, fFirstRun); if (fFirstRun) { _form = new StochasticsOptionsDialog(); } _form.InitializeParameters(_rgParameterDefinitions); DateTime dateStartLast = _dateStartLast; _dateStartLast = Strategy.BackTestFrom; if (!_form.WalkForward || Strategy.BackTestFrom <= dateStartLast) { if (_form.ShowDialog(Form.ActiveForm) != DialogResult.OK) { return; } } #if !NT7 _nPopulationSize = _form.PopulationSize; _cMaxGenerations = _form.MaxGenerations; _fitnessGainMax = _form.FitnessGain; _nPopulationSize = 10; //_form.PercentAnnealing; _nMinimumPerformce = _form.MinimumPerformance; #endif int cParams = _rgParameterDefinitions.Count; _rgParameterRunCounts = new int [cParams] []; _rgParameterRunTotals = new double [cParams] []; _rgParameterRunAverage = new double [cParams] []; decimal cCombinationsActual = _rgParameterDefinitions.CountCombinations; long cCombinations = (long)Math.Min(cCombinationsActual, (decimal)long.MaxValue); for (int ipd = 0; ipd < _rgParameterDefinitions.Count; ipd++) { ParameterDefinition pd = _rgParameterDefinitions [ipd]; int cValues = pd.CountValues; _rgParameterRunCounts [ipd] = new int [cValues]; _rgParameterRunTotals [ipd] = new double [cValues]; _rgParameterRunAverage [ipd] = new double [cValues]; } Dictionary <ParameterSet, bool> setChildren = new Dictionary <ParameterSet, bool> (); List <ParameterSet> rgChildren = new List <ParameterSet> (); int fitnessGainMin = 1; int cAnnealing = _nPopulationSize * _percentAnnealing / 100; // create an initial generation of aliens int cIterations = 0; while (rgChildren.Count < _nPopulationSize) { ParameterSet child = CreateAlien(); if (setChildren.ContainsKey(child)) { continue; } setChildren.Add(child, true); rgChildren.Add(child); } DateTime timeStart = DateTime.Now; ParameterSet bestChild = null; int iGeneration = 0; try { Strategy.Print( string.Format( "{0}: PH Stochastic Optimizer Start @ {1}, combinations: {2:N0}", Strategy.Instrument.FullName, timeStart, cCombinationsActual ) ); double diffMax = 0; double diffCurr = 0; int fitnessGain = fitnessGainMin; ParameterSet bestPrev = null; for (iGeneration = 0; iGeneration < _cMaxGenerations; iGeneration++) { // score the new generation ScoreGeneration(rgChildren); rgChildren.Sort(); if (bestChild == null) { bestChild = rgChildren [0]; } else if (bestChild.Performance < rgChildren [0].Performance) { bestChild = rgChildren [0]; } if (bestPrev != null) { if (double.IsNaN(bestPrev.Performance) || bestChild.Performance > bestPrev.Performance) { if (fitnessGain < FitnessGainMax) { fitnessGain++; } } else if (fitnessGain > fitnessGainMin) { fitnessGain--; } } bestPrev = bestChild; cIterations += rgChildren.Count; TimeSpan diff = DateTime.Now - timeStart; double iterPerSec = cIterations / diff.TotalSeconds; Strategy.Print(string.Format( "{0}: gen {1}/{2}, {3:N1} ips, max PERF: {4:N2}, gain={5}\t{6}", Strategy.Instrument.FullName, iGeneration + 1, _cMaxGenerations, iterPerSec, bestChild.Performance, fitnessGain, bestChild == null ? "" : _rgParameterDefinitions.ToString(bestChild))); if (bestChild != null && bestChild.Performance > this._nMinimumPerformce) { Strategy.Print(string.Format("{0}: Minimum performance reached.", Strategy.Instrument.FullName)); return; } if (iGeneration == _cMaxGenerations - 1) { break; } // initialize a new generation rgChildren.Clear(); int cCollisions = _nPopulationSize; while (cCollisions > 0 && rgChildren.Count < _nPopulationSize) { int iParam = _rand.Next(cParams); int cValues = _rgParameterDefinitions [iParam].CountValues; int [] rgParams = new int [cParams]; for (int iParamFuzz = 0; iParamFuzz < cParams; iParamFuzz++) { rgParams [iParamFuzz] = bestChild.GetParam(iParamFuzz); } rgParams [iParam] = MutateParam(fitnessGain, cValues, rgParams [iParam]); ParameterSet child = new ParameterSet(rgParams); if (setChildren.ContainsKey(child)) { cCollisions--; } else { setChildren.Add(child, true); rgChildren.Add(child); } } double loopFitnessGain = fitnessGain; if (rgChildren.Count < _nPopulationSize) { // pre-calculate the parameter value weights double [] [] rgrgWeights = new double [cParams] []; double [] rgTotalWeights = new double [cParams]; for (int iParam = 0; iParam < cParams; iParam++) { int cValues = _rgParameterDefinitions [iParam].CountValues; rgrgWeights [iParam] = new double [cValues]; double [] rgAverages = _rgParameterRunAverage [iParam]; // get the range of PERF values double minPerformance = double.PositiveInfinity; double maxPerformance = double.NegativeInfinity; for (int i = 0; i < cValues; i++) { double performance = rgAverages [i]; if (minPerformance > performance) { minPerformance = performance; } if (maxPerformance < performance) { maxPerformance = performance; } } // weight the procreation probabilities double totalWeight = 0; //if (maxPerformance != minPerformance) { for (int iValue = 0; iValue < cValues; iValue++) { double average = rgAverages [iValue]; if (double.IsNaN(average) || double.IsInfinity(average)) { average = maxPerformance; } double weight = Math.Pow((average - minPerformance) / (maxPerformance - minPerformance), loopFitnessGain); if (double.IsNaN(weight)) { weight = 0.0; } weight += 0.001; rgrgWeights [iParam] [iValue] = weight; totalWeight += weight; } } rgTotalWeights [iParam] = totalWeight; } cCollisions = _nPopulationSize; while (cCollisions > 0 && rgChildren.Count < _nPopulationSize && setChildren.Count < cCombinations) { // create a new set of genes int [] rgParams = new int [cParams]; for (int iParam = 0; iParam < cParams; iParam++) { int cValues = _rgParameterDefinitions [iParam].CountValues; double [] rgWeights = rgrgWeights [iParam]; double weightRandom = _rand.NextDouble() * rgTotalWeights [iParam]; int iValueRandom = 0; while (iValueRandom < cValues && weightRandom > rgWeights [iValueRandom]) { weightRandom -= rgWeights [iValueRandom]; iValueRandom++; } rgParams [iParam] = iValueRandom; } // create the new child, and make sure it's unique ParameterSet child = new ParameterSet(rgParams); if (setChildren.ContainsKey(child)) { if (loopFitnessGain > 1) { loopFitnessGain--; } cCollisions--; } else { setChildren.Add(child, true); rgChildren.Add(child); } } } } } catch (AbortOptimizationException) { Strategy.Print("Optimization Aborted..."); } catch (Exception e) { System.Diagnostics.Debug.WriteLine(e); Strategy.Print(e.ToString()); //throw; } finally { #if NT7 WaitForIterationsCompleted(true); #endif DateTime timeEnd = DateTime.Now; TimeSpan tsDuration = timeEnd - timeStart; if (iGeneration > 0) { Strategy.Print(string.Format( "{0}: PH Optimizer End @ {1}, duration: {2} ({3} per iteration)", Strategy.Instrument.FullName, timeEnd, tsDuration, TimeSpan.FromTicks(tsDuration.Ticks / iGeneration) ) ); } if (bestChild != null) { Dump(bestChild); } } }
internal void InitializeParameters(ParameterDefinitions rgParameterDefinitions) { if (_rgParameterDefinitions != null) { rgParameterDefinitions.InitializeValuesFrom(_rgParameterDefinitions); } tableLayoutPanel1.Controls.Clear(); tableLayoutPanel1.RowCount = 1; _rgParameterDefinitions = rgParameterDefinitions; bool fShowColumns = false; int iRow = 0; foreach (ParameterDefinition pd in rgParameterDefinitions) { SetParameterDefinition ed = pd as SetParameterDefinition; if (ed != null) { fShowColumns = true; CheckBox cbTitle = new CheckBox(); cbTitle.Text = ed.Parameter.Name; cbTitle.AutoSize = true; cbTitle.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; int iRowStart = iRow; List <CheckBox> rgCheckboxes = new List <CheckBox> (); bool fUpdating = false; Action <bool> initTitleCheckbox = delegate(bool f) { bool fAllChecked = true; bool fAllUnchecked = true; foreach (CheckBox cb in rgCheckboxes) { if (cb.Checked) { fAllUnchecked = false; } else { fAllChecked = false; } } if (!fAllChecked && !fAllUnchecked) { cbTitle.CheckState = CheckState.Indeterminate; } else { cbTitle.CheckState = fAllChecked ? CheckState.Checked : CheckState.Unchecked; } }; foreach (SetParameterDefinition.ValueInfo pvdEnum in ed.GetPossibleValues()) { SetParameterDefinition.ValueInfo pvd = pvdEnum; // extract for closure CheckBox cbValue = new CheckBox(); cbValue.Text = pvd.Name; cbValue.AutoSize = true; cbValue.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; cbValue.Margin = new Padding(0); cbValue.Checked = pvd.IsActive; cbValue.CheckedChanged += delegate(object sender, EventArgs args) { pvd.Setter(cbValue.Checked); if (fUpdating) { return; } try { fUpdating = true; initTitleCheckbox(true); } finally { fUpdating = false; } }; rgCheckboxes.Add(cbValue); while (iRow >= tableLayoutPanel1.RowCount) { tableLayoutPanel1.RowCount++; } tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.AutoSize)); tableLayoutPanel1.Controls.Add(cbValue, 1, iRow); iRow++; } tableLayoutPanel1.Controls.Add(cbTitle, 0, iRowStart); tableLayoutPanel1.SetRowSpan(cbTitle, tableLayoutPanel1.RowCount - iRowStart - 1); initTitleCheckbox(true); cbTitle.CheckedChanged += delegate(object sender, EventArgs args) { if (fUpdating) { return; } try { fUpdating = true; foreach (CheckBox cb in rgCheckboxes) { cb.Checked = cbTitle.Checked; } } finally { fUpdating = false; } }; } } if (fShowColumns != panel1.Enabled) { panel1.Visible = panel1.Enabled = fShowColumns; if (fShowColumns) { this.Width += panel1.Width; } else { this.Width -= panel1.Width; } } }
public override void Optimize() { DNA dnaBestEver = null; try { // initialize the parameter definition bool fFirstRun = (_form == null); _rgParameterDefinitions = new ParameterDefinitions(this.Strategy, fFirstRun); if (fFirstRun) { _form = new GeneticOptionsDialog(); } _form.InitializeParameters(_rgParameterDefinitions); DateTime dateStartLast = _dateStartLast; _dateStartLast = Strategy.BackTestFrom; if (!_form.WalkForward || Strategy.BackTestFrom <= dateStartLast) { if (_form.ShowDialog(Form.ActiveForm) != DialogResult.OK) { #if NT7 WaitForIterationsCompleted(true); #endif return; } } #if !NT7 _nPopulationSize = _form.PopulationSize; _cMaxGenerations = _form.MaxGenerations; _mutationRate = _form.MutationRate; _mutationStrength = _form.MutationStrength; _fitnessGain = _form.FitnessGain; _percentAliens = _form.Aliens; _stabilitySize = _form.StabilitySize; _resetSize = _form.ResetSize; _nMinimumPerformce = _form.MinimumPerformance; #endif int cAliens = (int)Math.Ceiling(_nPopulationSize * _percentAliens); int nStabilitySize = (int)Math.Ceiling(_nPopulationSize * _stabilitySize); int nResetSize = _nPopulationSize - (int)Math.Ceiling(_nPopulationSize * _resetSize); DateTime timeStart = DateTime.Now; int cParams = _rgParameterDefinitions.Count; decimal cCombinationsActual = _rgParameterDefinitions.CountCombinations; long cCombinations = (long)Math.Min(cCombinationsActual, (decimal)long.MaxValue); Strategy.Print( string.Format( "{0}: PH Genetic Optimizer Start @ {1}, combinations: {2:N0}", Strategy.Instrument.FullName, timeStart, cCombinationsActual ) ); List <DNA> rgChildren = new List <DNA> (); Dictionary <DNA, bool> setChildren = new Dictionary <DNA, bool> (); // create an initial generation of aliens int cIterations = 0; double stabilityScorePrev = double.NaN; List <DNA> rgParents = new List <DNA> (); int iGeneration; for (iGeneration = 1; iGeneration <= _cMaxGenerations; iGeneration++) { // fill the rest of this generation with aliens while (rgChildren.Count < _nPopulationSize && setChildren.Count < cCombinations) { DNA child = CreateAlien(0); if (setChildren.ContainsKey(child)) { continue; } setChildren.Add(child, true); rgChildren.Add(child); } DNA dnaBestSinceReset = null; try { // score the new generation ScoreGeneration(rgChildren); //if (rgParents.Count > nPopulationSize) // rgParents.RemoveRange (nPopulationSize, rgParents.Count - nPopulationSize); rgParents.AddRange(rgChildren); rgParents.Sort(); dnaBestSinceReset = rgParents [0]; } finally { if (rgParents.Count > 0 && dnaBestSinceReset != null && (dnaBestEver == null || dnaBestEver.Performance < dnaBestSinceReset.Performance)) { dnaBestEver = dnaBestSinceReset; } } double stabilityScore = 0.0; int cStabilityIndividuals = (int)Math.Min(rgParents.Count, nStabilitySize); if (cStabilityIndividuals < 1) { cStabilityIndividuals = 1; } for (int i = 0; i < cStabilityIndividuals; i++) { double scoreParent = rgParents [i].Performance; if (scoreParent > double.NegativeInfinity) { stabilityScore += rgParents [i].Performance; } } cIterations += rgChildren.Count; TimeSpan diff = DateTime.Now - timeStart; double iterPerSec = cIterations / diff.TotalSeconds; Strategy.Print(string.Format( "{0}: gen {1}/{2}, {3:N1} ips, max PERF: {4:N2}, stability PERF: {5:N2}\t{6}", Strategy.Instrument.FullName, iGeneration, _cMaxGenerations, iterPerSec, dnaBestSinceReset.Performance, stabilityScore / cStabilityIndividuals, rgParents.Count == 0 ? "" : _rgParameterDefinitions.ToString(dnaBestSinceReset))); if (dnaBestEver != null) { Strategy.Print(dnaBestEver.Performance + ", " + _nMinimumPerformce); } if (dnaBestEver != null && dnaBestEver.Performance > _nMinimumPerformce) { Strategy.Print(string.Format("{0}: Minimum performance reached.", Strategy.Instrument.FullName)); return; } if (iGeneration == _cMaxGenerations) { break; } if (setChildren.Count >= cCombinations) { break; } if (stabilityScore == stabilityScorePrev) { //rgParents.RemoveRange (1, rgParents.Count - 1); rgParents.Clear(); rgChildren.Clear(); Strategy.Print(string.Format( "{0}: reset", Strategy.Instrument.FullName ) ); //stabilityScore = double.NaN; continue; } // get the range of PERF values double minPerformance = double.MaxValue; double maxPerformance = double.MinValue; for (int i = 0; i < rgParents.Count; i++) { double performance = rgParents [i].Performance; if (performance == double.NegativeInfinity) { continue; } if (minPerformance > performance) { minPerformance = performance; } if (maxPerformance < performance) { maxPerformance = performance; } } // weight the procreation probabilities if (maxPerformance != minPerformance) { for (int i = 0; i < rgParents.Count; i++) { DNA parent = rgParents [i]; double performance = parent.Performance; if (performance == double.NegativeInfinity) { parent.Weight = 0; } else { double weight = (parent.Performance - minPerformance) / (maxPerformance - minPerformance); #if true parent.Weight = Math.Pow(weight, _fitnessGain) + 0.001; #else parent.Weight = (Math.Pow(weight, fitnessGain / (iGeneration - parent.Generation)) + 0.001); #endif } } } double totalWeight = 0; for (int i = 0; i < rgParents.Count; i++) { totalWeight += rgParents [i].Weight; } // initialize a new generation rgChildren.Clear(); // a certain percentage of the new population are aliens: int cAliensThisGeneration; if (stabilityScore == stabilityScorePrev) { cAliensThisGeneration = nResetSize; } else { cAliensThisGeneration = cAliens; } while (rgChildren.Count < cAliensThisGeneration && setChildren.Count < cCombinations) { DNA child = CreateAlien(iGeneration); if (setChildren.ContainsKey(child)) { continue; } setChildren.Add(child, true); rgChildren.Add(child); } // fuzz each param individually for (int iParam = 0; iParam < cParams; iParam++) { int cValues = _rgParameterDefinitions [iParam].CountValues; for (int iFuzz = 0; iFuzz < 5; iFuzz++) { int [] rgParams = new int [cParams]; for (int iParamFuzz = 0; iParamFuzz < cParams; iParamFuzz++) { rgParams [iParamFuzz] = dnaBestSinceReset.GetParam(iParamFuzz); } rgParams [iParam] = MutateParam(_mutationStrength, cValues, rgParams [iParam]); DNA child = new DNA(rgParams, dnaBestSinceReset.Generation + 1); if (!setChildren.ContainsKey(child)) { setChildren.Add(child, true); rgChildren.Add(child); } } } while (rgChildren.Count < _nPopulationSize - cAliensThisGeneration && setChildren.Count < cCombinations) { if (UserAbort) { throw new AbortOptimizationException(); } // find parents rendomly according to weighted fitness double weightA = _rand.NextDouble() * totalWeight; int iParentA = 0; while (iParentA < rgParents.Count && weightA > rgParents [iParentA].Weight) { weightA -= rgParents [iParentA].Weight; iParentA++; } double weightB = _rand.NextDouble() * totalWeight; int iParentB = 0; while (iParentB < rgParents.Count && weightB > rgParents [iParentB].Weight) { weightB -= rgParents [iParentB].Weight; iParentB++; } // these are the parents: DNA parentA = rgParents [iParentA]; DNA parentB = rgParents [iParentB]; // create a new set of genes int [] rgParams = new int [cParams]; for (int iParam = 0; iParam < cParams; iParam++) { // Take an attribute from parents DNA parent = (_rand.Next(100) < 50) ? parentA : parentB; rgParams [iParam] = parent.GetParam(iParam); // Should we mutate? int cValues = _rgParameterDefinitions [iParam].CountValues; if (cValues > 1 && _rand.NextDouble() < _mutationRate) { rgParams [iParam] = MutateParam(_mutationStrength, cValues, rgParams [iParam]); } } // create the new child, and make sure it's unique //int iGenerationChild = iGeneration; //int iGenerationChild = 1 + Math.Min (parentA.Generation, parentB.Generation); int iGenerationChild = (parentA.Generation + parentB.Generation) / 2; DNA child = new DNA(rgParams, iGenerationChild); if (!setChildren.ContainsKey(child)) { setChildren.Add(child, true); rgChildren.Add(child); } } stabilityScorePrev = stabilityScore; } DateTime timeEnd = DateTime.Now; TimeSpan tsDuration = timeEnd - timeStart; Strategy.Print(string.Format( "{0}: PH Optimizer End @ {1}, duration: {2} ({3} per iteration)", Strategy.Instrument.FullName, timeEnd, tsDuration, TimeSpan.FromTicks(tsDuration.Ticks / iGeneration) ) ); } catch (AbortOptimizationException) { Strategy.Print("Optimization Aborted..."); } catch (Exception e) { System.Diagnostics.Debug.WriteLine(e); Strategy.Print(e.ToString()); //throw; } finally { if (dnaBestEver != null) { Dump(dnaBestEver); } } #if NT7 WaitForIterationsCompleted(true); #endif }