/// <summary> /// Constructor /// </summary> public OverOptimizationChartsForm(OverOptimizationDataTable[] tableReport, List<string> paramNames) { TableReport = tableReport; Text = Language.T("Over-optimization Report"); Icon = Data.Icon; FormBorderStyle = FormBorderStyle.Sizable; AcceptButton = BtnClose; // Button Next Chart BtnNextCharts = new Button {Parent = this, Text = Language.T("Next Chart")}; BtnNextCharts.Click += BtnNextChartsClick; BtnNextCharts.DoubleClick += BtnNextChartsClick; BtnNextCharts.MouseWheel += ChartMouseWheel; BtnNextCharts.KeyUp += NextChartsKeyUp; BtnNextCharts.UseVisualStyleBackColor = true; // Button Close BtnClose = new Button { Parent = this, Text = Language.T("Close"), DialogResult = DialogResult.Cancel, UseVisualStyleBackColor = true }; CurrentChart = new OverOptimizationCharts {Parent = this}; CurrentChart.InitChart(tableReport[_currentChartNumber]); ChartLegend = new OverOptimizationChartLegend { Parent = this }; ChartLegend.InitChart(paramNames); }
/// <summary> /// Calculates Data Tables. /// </summary> private void CalculateStatsTables(int percentDeviation, int countParam) { string unit = " " + Configs.AccountCurrency; var tableNames = new[] { Language.T("Account balance") + unit, Language.T("Profit per day") + unit, Language.T("Maximum drawdown") + unit, Language.T("Gross profit") + unit, Language.T("Gross loss") + unit, Language.T("Executed orders"), Language.T("Traded lots"), Language.T("Time in position") + " %", Language.T("Sent orders"), Language.T("Charged spread") + unit, Language.T("Charged rollover") + unit, Language.T("Winning trades"), Language.T("Losing trades"), Language.T("Win/loss ratio"), Language.T("Max equity drawdown") + " %" }; _tablesCount = tableNames.Length; _tableReport = new OverOptimizationDataTable[_tablesCount]; for (int t = 0; t < tableNames.Length; t++) { _tableReport[t] = new OverOptimizationDataTable(percentDeviation, countParam) {Name = tableNames[t]}; } int parNumber = 0; bool isBGWorkCanceled = false; for (int slot = 0; slot < Data.Strategy.Slots && !isBGWorkCanceled; slot++) for (int numParam = 0; numParam < 6 && !isBGWorkCanceled; numParam++) if (Data.Strategy.Slot[slot].IndParam.NumParam[numParam].Enabled && parNumber < countParam) { for (int index = percentDeviation; index >= -percentDeviation && !isBGWorkCanceled; index--) { isBGWorkCanceled = _bgWorker.CancellationPending; Data.Strategy.Slot[slot].IndParam.NumParam[numParam].Value = _tableParameters.GetData( index, parNumber); CalculateIndicator(slot); Backtester.Calculate(); Backtester.CalculateAccountStats(); var statValues = new[] { Backtester.NetMoneyBalance, Backtester.MoneyProfitPerDay, Backtester.MaxMoneyDrawdown, Backtester.GrossMoneyProfit, Backtester.GrossMoneyLoss, Backtester.ExecutedOrders, Backtester.TradedLots, Backtester.TimeInPosition, Backtester.SentOrders, Backtester.TotalChargedMoneySpread, Backtester.TotalChargedMoneyRollOver, Backtester.WinningTrades, Backtester.LosingTrades, Backtester.WinLossRatio, Backtester.MoneyEquityPercentDrawdown }; for (int tn = 0; tn < _tablesCount; tn++) _tableReport[tn].SetData(index, parNumber, statValues[tn]); // Report progress as a percentage of the total task. _computedCycles++; int percentComplete = Math.Min(100*_computedCycles/_cycles, 100); if (percentComplete > _progressPercent) { _progressPercent = percentComplete; _bgWorker.ReportProgress(percentComplete); } } // Set default value Data.Strategy.Slot[slot].IndParam.NumParam[numParam].Value = _tableParameters.GetData(0, parNumber); CalculateIndicator(slot); parNumber++; } }
/// <summary> /// Sets table with parameter values. /// </summary> private void SetParametersValues(int percentDeviation, int countParam) { _listParametersName = "Index" + Configs.ColumnSeparator + "Parameter name" + Environment.NewLine; _countStratParams = 0; _cycles = 0; _deviationSteps = 2*percentDeviation + 1; _tableParameters = new OverOptimizationDataTable(percentDeviation, countParam) {Name = "Values of the Parameters"}; for (int slot = 0; slot < Data.Strategy.Slots; slot++) for (int numParam = 0; numParam < 6; numParam++) if (Data.Strategy.Slot[slot].IndParam.NumParam[numParam].Enabled && _countStratParams < countParam) { NumericParam currentParam = Data.Strategy.Slot[slot].IndParam.NumParam[numParam]; double minVal = currentParam.Min; double maxVal = currentParam.Max; int point = currentParam.Point; double originalValue = currentParam.Value; double deltaStep = originalValue/100.0; for (int p = 0; p < _deviationSteps; p++) { int index = percentDeviation - p; double value = originalValue + index*deltaStep; value = Math.Round(value, point); if (index == 0) value = originalValue; if (value < minVal) value = minVal; if (value > maxVal) value = maxVal; _tableParameters.SetData(index, _countStratParams, value); _cycles++; } _listParametersName += (_countStratParams + 1) + Configs.ColumnSeparator + currentParam.Caption + Environment.NewLine; _countStratParams++; } for (int prm = _countStratParams; prm < countParam; prm++) _listParametersName += (prm + 1) + Environment.NewLine; _listParametersName += Environment.NewLine; }
/// <summary> /// Sets table with parameter values. /// </summary> private void SetParametersValues(int percentDeviation, int countParam) { _paramNames = new List <string>(); _listParametersName = "Index" + Configs.ColumnSeparator + "Parameter name" + Environment.NewLine; _countStratParams = 0; _cycles = 0; _deviationSteps = 2 * percentDeviation + 1; _tableParameters = new OverOptimizationDataTable(percentDeviation, countParam) { Name = "Values of the Parameters" }; for (int slot = 0; slot < Data.Strategy.Slots; slot++) { for (int numParam = 0; numParam < 6; numParam++) { if (Data.Strategy.Slot[slot].IndParam.NumParam[numParam].Enabled && _countStratParams < countParam) { NumericParam currentParam = Data.Strategy.Slot[slot].IndParam.NumParam[numParam]; double minVal = currentParam.Min; double maxVal = currentParam.Max; int point = currentParam.Point; double originalValue = currentParam.Value; double deltaStep = originalValue / 100.0; for (int p = 0; p < _deviationSteps; p++) { int index = p - percentDeviation; double value = originalValue + index * deltaStep; value = Math.Round(value, point); if (index == 0) { value = originalValue; } if (value < minVal) { value = minVal; } if (value > maxVal) { value = maxVal; } _tableParameters.SetData(index, _countStratParams, value); _cycles++; } _paramNames.Add(currentParam.Caption); _listParametersName += (_countStratParams + 1) + Configs.ColumnSeparator + currentParam.Caption + Environment.NewLine; _countStratParams++; } } } for (int prm = _countStratParams; prm < countParam; prm++) { _listParametersName += (prm + 1) + Environment.NewLine; } _listParametersName += Environment.NewLine; }
/// <summary> /// Calculates Data Tables. /// </summary> private void CalculateStatsTables(int percentDeviation, int countParam) { string unit = " " + Configs.AccountCurrency; var tableNames = new[] { Language.T("Account balance") + unit, Language.T("Profit per day") + unit, Language.T("Maximum drawdown") + unit, Language.T("Gross profit") + unit, Language.T("Gross loss") + unit, Language.T("Executed orders"), Language.T("Traded lots"), Language.T("Time in position") + " %", Language.T("Sent orders"), Language.T("Charged spread") + unit, Language.T("Charged rollover") + unit, Language.T("Winning trades"), Language.T("Losing trades"), Language.T("Win/loss ratio"), Language.T("Max equity drawdown") + " %" }; _tablesCount = tableNames.Length; _tableReport = new OverOptimizationDataTable[_tablesCount]; for (int t = 0; t < tableNames.Length; t++) { _tableReport[t] = new OverOptimizationDataTable(percentDeviation, countParam) { Name = tableNames[t] }; } int parNumber = 0; bool isBGWorkCanceled = false; for (int slot = 0; slot < Data.Strategy.Slots && !isBGWorkCanceled; slot++) { for (int numParam = 0; numParam < 6 && !isBGWorkCanceled; numParam++) { if (Data.Strategy.Slot[slot].IndParam.NumParam[numParam].Enabled && parNumber < countParam) { for (int index = percentDeviation; index >= -percentDeviation && !isBGWorkCanceled; index--) { isBGWorkCanceled = _bgWorker.CancellationPending; Data.Strategy.Slot[slot].IndParam.NumParam[numParam].Value = _tableParameters.GetData( index, parNumber); CalculateIndicator(slot); Backtester.Calculate(); Backtester.CalculateAccountStats(); var statValues = new[] { Backtester.NetMoneyBalance, Backtester.MoneyProfitPerDay, Backtester.MaxMoneyDrawdown, Backtester.GrossMoneyProfit, Backtester.GrossMoneyLoss, Backtester.ExecutedOrders, Backtester.TradedLots, Backtester.TimeInPosition, Backtester.SentOrders, Backtester.TotalChargedMoneySpread, Backtester.TotalChargedMoneyRollOver, Backtester.WinningTrades, Backtester.LosingTrades, Backtester.WinLossRatio, Backtester.MoneyEquityPercentDrawdown }; for (int tn = 0; tn < _tablesCount; tn++) { _tableReport[tn].SetData(index, parNumber, statValues[tn]); } // Report progress as a percentage of the total task. _computedCycles++; int percentComplete = Math.Min(100 * _computedCycles / _cycles, 100); if (percentComplete > _progressPercent) { _progressPercent = percentComplete; _bgWorker.ReportProgress(percentComplete); } } // Set default value Data.Strategy.Slot[slot].IndParam.NumParam[numParam].Value = _tableParameters.GetData(0, parNumber); CalculateIndicator(slot); parNumber++; } } } }
/// <summary> /// Sets the chart parameters /// </summary> public void InitChart(OverOptimizationDataTable table) { Table = table; // Chart Title _chartTitle = table.Name; _font = new Font(Font.FontFamily, 9); _captionHeight = Math.Max(_font.Height, 18); _rectfCaption = new RectangleF(0, 0, ClientSize.Width, _captionHeight); _stringFormatCaption = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter, FormatFlags = StringFormatFlags.NoWrap }; _brushFore = new SolidBrush(LayoutColors.ColorChartFore); _penGrid = new Pen(LayoutColors.ColorChartGrid) {DashStyle = DashStyle.Dash, DashPattern = new float[] {4, 2}}; _penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), Border); _devSteps = table.CountDeviationSteps; _percentDev = (_devSteps - 1)/2; _parameters = table.CountStrategyParams; if (_parameters == 0) return; double minValue = double.MaxValue; double maxValue = double.MinValue; for (int param = 0; param < _parameters; param++) { double min = double.MaxValue; double max = double.MinValue; for (int dev = 0; dev < _devSteps; dev++) { int index = _percentDev - dev; double value = table.GetData(index, param); if (min > value) min = value; if (max < value) max = value; } if (minValue > min) minValue = min; if (maxValue < max) maxValue = max; } _maximum = (int) Math.Round(maxValue + 0.1*Math.Abs(maxValue)); _minimum = (int) Math.Round(minValue - 0.1*Math.Abs(minValue)); int roundStep = Math.Abs(_minimum) > 1 ? 10 : 1; _minimum = (int) (Math.Floor(_minimum/(float) roundStep)*roundStep); if (Math.Abs(_maximum - _minimum) < 1) _maximum = _minimum + 1; _yTop = (int) _captionHeight + 2*Space + 1; _yBottom = ClientSize.Height - 2*Space - 1 - Border - Space - Font.Height; Graphics g = CreateGraphics(); _labelWidth = (int) Math.Max(g.MeasureString(_minimum.ToString(CultureInfo.InvariantCulture), _font).Width, g.MeasureString(_maximum.ToString(CultureInfo.InvariantCulture), _font).Width); g.Dispose(); _labelWidth = Math.Max(_labelWidth, 30); _xLeft = Border + 3*Space; _xRight = ClientSize.Width - Border - 2*Space - _labelWidth; _xScale = (_xRight - _xLeft)/(float) (_devSteps - 1); _xMiddle = (int) (_xLeft + _percentDev*_xScale); _countLabels = Math.Max((_yBottom - _yTop)/20, 2); _delta = (float) Math.Max(Math.Round((_maximum - _minimum)/(float) _countLabels), roundStep); _step = (int) Math.Ceiling(_delta/roundStep)*roundStep; _countLabels = (int) Math.Ceiling((_maximum - _minimum)/(float) _step); _maximum = _minimum + _countLabels*_step; _yScale = (_yBottom - _yTop)/(_countLabels*(float) _step); _apntParameters = new PointF[_parameters][]; for (int param = 0; param < _parameters; param++) { _apntParameters[param] = new PointF[_devSteps]; for (int dev = 0; dev < _devSteps; dev++) { int index = _percentDev - dev; _apntParameters[param][dev].X = _xLeft + dev*_xScale; _apntParameters[param][dev].Y = (float) (_yBottom - (table.GetData(index, param) - _minimum)*_yScale); } } }
/// <summary> /// Sets the chart parameters /// </summary> public void InitChart(OverOptimizationDataTable table) { Table = table; // Chart Title _chartTitle = table.Name; _font = new Font(Font.FontFamily, 9); _captionHeight = Math.Max(_font.Height, 18); _rectfCaption = new RectangleF(0, 0, ClientSize.Width, _captionHeight); _stringFormatCaption = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter, FormatFlags = StringFormatFlags.NoWrap }; _brushFore = new SolidBrush(LayoutColors.ColorChartFore); _penGrid = new Pen(LayoutColors.ColorChartGrid) { DashStyle = DashStyle.Dash, DashPattern = new float[] { 4, 2 } }; _penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), Border); _devSteps = table.CountDeviationSteps; _percentDev = (_devSteps - 1) / 2; _parameters = table.CountStrategyParams; if (_parameters == 0) { return; } double minValue = double.MaxValue; double maxValue = double.MinValue; for (int param = 0; param < _parameters; param++) { double min = double.MaxValue; double max = double.MinValue; for (int dev = 0; dev < _devSteps; dev++) { int index = _percentDev - dev; double value = table.GetData(index, param); if (min > value) { min = value; } if (max < value) { max = value; } } if (minValue > min) { minValue = min; } if (maxValue < max) { maxValue = max; } } _maximum = (int)Math.Round(maxValue + 0.1 * Math.Abs(maxValue)); _minimum = (int)Math.Round(minValue - 0.1 * Math.Abs(minValue)); int roundStep = Math.Abs(_minimum) > 1 ? 10 : 1; _minimum = (int)(Math.Floor(_minimum / (float)roundStep) * roundStep); if (Math.Abs(_maximum - _minimum) < 1) { _maximum = _minimum + 1; } _yTop = (int)_captionHeight + 2 * Space + 1; _yBottom = ClientSize.Height - 2 * Space - 1 - Border - Space - Font.Height; Graphics g = CreateGraphics(); _labelWidth = (int) Math.Max(g.MeasureString(_minimum.ToString(CultureInfo.InvariantCulture), _font).Width, g.MeasureString(_maximum.ToString(CultureInfo.InvariantCulture), _font).Width); g.Dispose(); _labelWidth = Math.Max(_labelWidth, 30); _xLeft = Border + 3 * Space; _xRight = ClientSize.Width - Border - 2 * Space - _labelWidth; _xScale = (_xRight - _xLeft) / (float)(_devSteps - 1); _xMiddle = (int)(_xLeft + _percentDev * _xScale); _countLabels = Math.Max((_yBottom - _yTop) / 20, 2); _delta = (float)Math.Max(Math.Round((_maximum - _minimum) / (float)_countLabels), roundStep); _step = (int)Math.Ceiling(_delta / roundStep) * roundStep; _countLabels = (int)Math.Ceiling((_maximum - _minimum) / (float)_step); _maximum = _minimum + _countLabels * _step; _yScale = (_yBottom - _yTop) / (_countLabels * (float)_step); _apntParameters = new PointF[_parameters][]; for (int param = 0; param < _parameters; param++) { _apntParameters[param] = new PointF[_devSteps]; for (int dev = 0; dev < _devSteps; dev++) { int index = _percentDev - dev; _apntParameters[param][dev].X = _xLeft + dev * _xScale; _apntParameters[param][dev].Y = (float)(_yBottom - (table.GetData(index, param) - _minimum) * _yScale); } } }