/// <summary> /// Constructor /// </summary> public Over_optimization_Charts_Form(Over_optimization_Data_Table[] tableReport) { this.tableReport = tableReport; Text = Language.T("Over-optimization Report"); Icon = Data.Icon; FormBorderStyle = FormBorderStyle.Sizable; AcceptButton = btnClose; // Button Close btnNextCharts = new Button(); btnNextCharts.Parent = this; btnNextCharts.Text = Language.T("Next Chart"); btnNextCharts.Click += new EventHandler(BtnNextCharts_Click); btnNextCharts.UseVisualStyleBackColor = true; // Button Close btnClose = new Button(); btnClose.Parent = this; btnClose.Text = Language.T("Close"); btnClose.DialogResult = DialogResult.Cancel; btnClose.UseVisualStyleBackColor = true; currentChart = new Over_optimization_Charts(); currentChart.Parent = this; currentChart.InitChart(tableReport[currentChartNumber]); }
/// <summary> /// Sets table with parameter values. /// </summary> void SetParametersValues(int percentDeviation, int countParam) { listParametersName = "Index" + Configs.ColumnSeparator + "Parameter name" + Environment.NewLine; countStratParams = 0; cycles = 0; deviationSteps = 2 * percentDeviation + 1; tableParameters = new Over_optimization_Data_Table(percentDeviation, countParam); tableParameters.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).ToString() + Configs.ColumnSeparator + currentParam.Caption + Environment.NewLine; countStratParams++; } } } for (int prm = countStratParams; prm < countParam; prm++) { listParametersName += (prm + 1).ToString() + Environment.NewLine; } listParametersName += Environment.NewLine; }
/// <summary> /// Calculates Data Tables. /// </summary> void CalculateStatsTables(int percentDeviation, int countParam) { string unit = " " + Configs.AccountCurrency; string[] tableNames = new string[] { 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 Over_optimization_Data_Table[tablesCount]; for (int t = 0; t < tableNames.Length; t++) { tableReport[t] = new Over_optimization_Data_Table(percentDeviation, countParam); tableReport[t].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(); double[] statValues = new double[] { 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> /// Calculates Data Tables. /// </summary> void CalculateStatsTables(int percentDeviation, int countParam) { string unit = " " + Configs.AccountCurrency; string[] tableNames = new string[] { 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 Over_optimization_Data_Table[tablesCount]; for (int t = 0; t < tableNames.Length; t++) { tableReport[t] = new Over_optimization_Data_Table(percentDeviation, countParam); tableReport[t].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(); double[] statValues = new double[] { 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> void SetParametersValues(int percentDeviation, int countParam) { listParametersName = "Index" + Configs.ColumnSeparator + "Parameter name" + Environment.NewLine; countStratParams = 0; cycles = 0; deviationSteps = 2 * percentDeviation + 1; tableParameters = new Over_optimization_Data_Table(percentDeviation, countParam); tableParameters.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).ToString() + Configs.ColumnSeparator + currentParam.Caption + Environment.NewLine; countStratParams++; } for (int prm = countStratParams; prm < countParam; prm++) listParametersName += (prm + 1).ToString() + Environment.NewLine; listParametersName += Environment.NewLine; }
/// <summary> /// Sets the chart parameters /// </summary> public void InitChart(Over_optimization_Data_Table table) { this.table = table; // Chart Title chartTitle = table.Name; font = new Font(Font.FontFamily, 9); captionHeight = (float)Math.Max(font.Height, 18); rectfCaption = new RectangleF(0, 0, ClientSize.Width, captionHeight); stringFormatCaption = new StringFormat(); stringFormatCaption.Alignment = StringAlignment.Center; stringFormatCaption.LineAlignment = StringAlignment.Center; stringFormatCaption.Trimming = StringTrimming.EllipsisCharacter; stringFormatCaption.FormatFlags = StringFormatFlags.NoWrap; brushFore = new SolidBrush(LayoutColors.ColorChartFore); penGrid = new Pen(LayoutColors.ColorChartGrid); penGrid.DashStyle = DashStyle.Dash; penGrid.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(), font).Width, g.MeasureString(maximum.ToString(), 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 = (int)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(Over_optimization_Data_Table table) { this.table = table; // Chart Title chartTitle = table.Name; font = new Font(Font.FontFamily, 9); captionHeight = (float)Math.Max(font.Height, 18); rectfCaption = new RectangleF(0, 0, ClientSize.Width, captionHeight); stringFormatCaption = new StringFormat(); stringFormatCaption.Alignment = StringAlignment.Center; stringFormatCaption.LineAlignment = StringAlignment.Center; stringFormatCaption.Trimming = StringTrimming.EllipsisCharacter; stringFormatCaption.FormatFlags = StringFormatFlags.NoWrap; brushFore = new SolidBrush(LayoutColors.ColorChartFore); penGrid = new Pen(LayoutColors.ColorChartGrid); penGrid.DashStyle = DashStyle.Dash; penGrid.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(), font).Width, g.MeasureString(maximum.ToString(), 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 = (int)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); } } }