/// <summary> /// Prepare the parameters /// </summary> public void SetUpChart() { // Panel caption stringCaptionText = Language.T("Indicator Chart"); fontCaptionText = new Font(Font.FontFamily, 9); captionHeight = Math.Max(fontCaptionText.Height, 18); captionWidth = this.ClientSize.Width; brushCaptionText = new SolidBrush(LayoutColors.ColorCaptionText); rectfCaption = new RectangleF(0, 0, captionWidth, captionHeight); stringFormatCaption = new StringFormat(); stringFormatCaption.Alignment |= StringAlignment.Center; stringFormatCaption.LineAlignment |= StringAlignment.Center; stringFormatCaption.Trimming |= StringTrimming.EllipsisCharacter; stringFormatCaption.FormatFlags |= StringFormatFlags.NoWrap; if (!Data.IsData || !Data.IsResult || Data.Bars <= Data.FirstBar) { return; } clSzWidth = this.ClientSize.Width; clSzHeight = this.ClientSize.Height; xLeft = space; xRight = clSzWidth - space; yTop = (int)captionHeight + space; yBottom = clSzHeight - scrollBar.Height - space; yPrcBottom = yBottom; // Price chart y inds = 0; // Count of separated indicators indHeight = 0; // Height of Ind charts aiIndSlot = new int[12]; penFore = new Pen(LayoutColors.ColorChartFore); penVolume = new Pen(LayoutColors.ColorVolume); penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); for (int slot = Data.Strategy.Slots - 1; slot >= 0; slot--) { if (Data.Strategy.Slot[slot].SeparatedChart) { aiIndSlot[inds++] = slot; } } if (inds > 0) { indHeight = (yBottom - yTop) / (2 + inds); yPrcBottom = yBottom - inds * indHeight; } maxPrice = double.MinValue; minPrice = double.MaxValue; maxVolume = int.MinValue; for (int bar = firstBar; bar <= lastBar; bar++) { if (Data.High[bar] > maxPrice) { maxPrice = Data.High[bar]; } if (Data.Low[bar] < minPrice) { minPrice = Data.Low[bar]; } if (Data.Volume[bar] > maxVolume) { maxVolume = Data.Volume[bar]; } } minPrice = Math.Round(minPrice, Data.InstrProperties.Point < 0.001 ? 3 : 1) - Data.InstrProperties.Point * 10; maxPrice = Math.Round(maxPrice, Data.InstrProperties.Point < 0.001 ? 3 : 1) + Data.InstrProperties.Point * 10; scaleY = (yPrcBottom - yTop) / (maxPrice - minPrice); scaleYVol = maxVolume > 0 ? ((yPrcBottom - yTop) / 8d) / maxVolume : 0d; // Volume, Lots and Price x = new int[chartBars]; yOpen = new int[chartBars]; yHigh = new int[chartBars]; yLow = new int[chartBars]; yClose = new int[chartBars]; yVolume = new int[chartBars]; rectPosition = new Rectangle[chartBars]; brushPosition = new Brush[chartBars]; int index = 0; for (int bar = firstBar; bar <= lastBar; bar++) { x[index] = (bar - firstBar) * barPixels + xLeft; yOpen[index] = (int)(yPrcBottom - (Data.Open[bar] - minPrice) * scaleY); yHigh[index] = (int)(yPrcBottom - (Data.High[bar] - minPrice) * scaleY); yLow[index] = (int)(yPrcBottom - (Data.Low[bar] - minPrice) * scaleY); yClose[index] = (int)(yPrcBottom - (Data.Close[bar] - minPrice) * scaleY); yVolume[index] = (int)(yPrcBottom - Data.Volume[bar] * scaleYVol); // Draw position lots if (Backtester.IsPos(bar)) { int iPosHight = (int)(Math.Max(Backtester.SummaryLots(bar) * 2, 2)); int iPosY = yPrcBottom - iPosHight; if (Backtester.SummaryDir(bar) == PosDirection.Long) { // Long rectPosition[index] = new Rectangle(x[index], iPosY, 1, iPosHight); brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeLong); } else if (Backtester.SummaryDir(bar) == PosDirection.Short) { // Short rectPosition[index] = new Rectangle(x[index], iPosY, 1, iPosHight); brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeShort); } else { // Close position rectPosition[index] = new Rectangle(x[index], iPosY - 2, 1, 2); brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeClose); } } else { // There is no position rectPosition[index] = Rectangle.Empty; brushPosition[index] = new SolidBrush(LayoutColors.ColorChartBack); } index++; } // Indicators in the chart slots = Data.Strategy.Slots; bIsSeparatedChart = new bool[slots]; iComponentLenght = new int[slots]; chartType = new IndChartType[slots][]; chartLine = new Point[slots][][]; chartDot = new Rectangle[slots][][]; chartLevel = new Rectangle[slots][][]; chartValue = new double[slots][][]; chartPen = new Pen[slots][][]; chartBrush = new Brush[slots][]; for (int iSlot = 0; iSlot < slots; iSlot++) { bIsSeparatedChart[iSlot] = Data.Strategy.Slot[iSlot].SeparatedChart; int iLenght = Data.Strategy.Slot[iSlot].Component.Length; iComponentLenght[iSlot] = iLenght; chartType[iSlot] = new IndChartType[iLenght]; chartLine[iSlot] = new Point[iLenght][]; chartDot[iSlot] = new Rectangle[iLenght][]; chartLevel[iSlot] = new Rectangle[iLenght][]; chartValue[iSlot] = new double[iLenght][]; chartPen[iSlot] = new Pen[iLenght][]; chartBrush[iSlot] = new Brush[iLenght]; } for (int slot = 0; slot < slots; slot++) { if (bIsSeparatedChart[slot]) { continue; } for (int comp = 0; comp < iComponentLenght[slot]; comp++) { chartType[slot][comp] = Data.Strategy.Slot[slot].Component[comp].ChartType; if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.Line || Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.CloudUp || Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.CloudDown) { // Line chartBrush[slot][comp] = new SolidBrush(Data.Strategy.Slot[slot].Component[comp].ChartColor); chartLine[slot][comp] = new Point[lastBar - firstBar + 1]; for (int bar = firstBar; bar <= lastBar; bar++) { double dValue = Data.Strategy.Slot[slot].Component[comp].Value[bar]; int ix = (bar - firstBar) * barPixels + xLeft; int iy = (int)(yPrcBottom - (dValue - minPrice) * scaleY); if (dValue == 0) { chartLine[slot][comp][bar - firstBar] = chartLine[slot][comp][Math.Max(bar - firstBar - 1, 0)]; } else { chartLine[slot][comp][bar - firstBar] = new Point(ix, iy); } } } else if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.Dot) { // Dots chartBrush[slot][comp] = new SolidBrush(Data.Strategy.Slot[slot].Component[comp].ChartColor); chartDot[slot][comp] = new Rectangle[lastBar - firstBar + 1]; for (int bar = firstBar; bar <= lastBar; bar++) { double dValue = Data.Strategy.Slot[slot].Component[comp].Value[bar]; int ix = (bar - firstBar) * barPixels + xLeft; int iy = (int)(yPrcBottom - (dValue - minPrice) * scaleY); chartDot[slot][comp][bar - firstBar] = new Rectangle(ix, iy, 1, 1); } } else if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.Level) { // Level chartBrush[slot][comp] = new SolidBrush(Data.Strategy.Slot[slot].Component[comp].ChartColor); chartLevel[slot][comp] = new Rectangle[lastBar - firstBar + 1]; for (int bar = firstBar; bar <= lastBar; bar++) { double dValue = Data.Strategy.Slot[slot].Component[comp].Value[bar]; int ix = (bar - firstBar) * barPixels + xLeft; int iy = (int)(yPrcBottom - (dValue - minPrice) * scaleY); chartLevel[slot][comp][bar - firstBar] = new Rectangle(ix, iy, barPixels, 1); } } } } // Separate indicators yIndTop = new int[inds]; yIndBottom = new int[inds]; dMaxValue = new double[inds]; dMinValue = new double[inds]; dScale = new double[inds]; for (int ind = 0; ind < inds; ind++) { yIndTop[ind] = yBottom - (ind + 1) * indHeight + 1; yIndBottom[ind] = yBottom - ind * indHeight - 1; dMaxValue[ind] = double.MinValue; dMinValue[ind] = double.MaxValue; int iSlot = aiIndSlot[ind]; double dValue; for (int iComp = 0; iComp < iComponentLenght[iSlot]; iComp++) { if (Data.Strategy.Slot[iSlot].Component[iComp].ChartType != IndChartType.NoChart) { for (bar = Math.Max(firstBar, Data.Strategy.Slot[iSlot].Component[iComp].FirstBar); bar <= lastBar; bar++) { dValue = Data.Strategy.Slot[iSlot].Component[iComp].Value[bar]; if (dValue > dMaxValue[ind]) { dMaxValue[ind] = dValue; } if (dValue < dMinValue[ind]) { dMinValue[ind] = dValue; } } } } dMaxValue[ind] = Math.Max(dMaxValue[ind], Data.Strategy.Slot[iSlot].MaxValue); dMinValue[ind] = Math.Min(dMinValue[ind], Data.Strategy.Slot[iSlot].MinValue); foreach (double dSpecVal in Data.Strategy.Slot[iSlot].SpecValue) { if (dSpecVal == 0) { dMaxValue[ind] = Math.Max(dMaxValue[ind], 0); dMinValue[ind] = Math.Min(dMinValue[ind], 0); } } dScale[ind] = (yIndBottom[ind] - yIndTop[ind] - 2) / (Math.Max(dMaxValue[ind] - dMinValue[ind], 0.0001f)); // Indicator chart for (int iComp = 0; iComp < Data.Strategy.Slot[iSlot].Component.Length; iComp++) { chartType[iSlot][iComp] = Data.Strategy.Slot[iSlot].Component[iComp].ChartType; if (Data.Strategy.Slot[iSlot].Component[iComp].ChartType == IndChartType.Line) { // Line chartBrush[iSlot][iComp] = new SolidBrush(Data.Strategy.Slot[iSlot].Component[iComp].ChartColor); chartLine[iSlot][iComp] = new Point[lastBar - firstBar + 1]; for (bar = firstBar; bar <= lastBar; bar++) { dValue = Data.Strategy.Slot[iSlot].Component[iComp].Value[bar]; int ix = (bar - firstBar) * barPixels + xLeft; int iy = (int)(yIndBottom[ind] - 1 - (dValue - dMinValue[ind]) * dScale[ind]); chartLine[iSlot][iComp][bar - firstBar] = new Point(ix, iy); } } else if (Data.Strategy.Slot[iSlot].Component[iComp].ChartType == IndChartType.Histogram) { // Histogram chartValue[iSlot][iComp] = new double[lastBar - firstBar + 1]; chartPen[iSlot][iComp] = new Pen[lastBar - firstBar + 1]; for (bar = firstBar; bar <= lastBar; bar++) { dValue = Data.Strategy.Slot[iSlot].Component[iComp].Value[bar]; chartValue[iSlot][iComp][bar - firstBar] = dValue; if (dValue > Data.Strategy.Slot[iSlot].Component[iComp].Value[bar - 1]) { chartPen[iSlot][iComp][bar - firstBar] = penGreen; } else { chartPen[iSlot][iComp][bar - firstBar] = penRed; } } } } } }
/// <summary> /// Exports the bar summary /// </summary> public void ExportBarSummary() { string stage = String.Empty; if (Data.IsProgramBeta) { stage = " " + Language.T("Beta"); } else if (Data.IsProgramRC) { stage = " " + "RC"; } sb.Append("Forex Strategy Builder v" + Data.ProgramVersion + stage + Environment.NewLine); sb.Append("Strategy name: " + Data.Strategy.StrategyName + Environment.NewLine); sb.Append("Exported on " + DateTime.Now.ToString() + Environment.NewLine); sb.Append(Data.Symbol + " " + Data.PeriodString + "; Values in pips" + Environment.NewLine); sb.Append("Bar Numb\t"); sb.Append("Date\t"); sb.Append("Hour\t"); sb.Append("Open\t"); sb.Append("High\t"); sb.Append("Low\t"); sb.Append("Close\t"); sb.Append("Volume\t"); sb.Append("Direction\t"); sb.Append("Lots\t"); sb.Append("Transaction\t"); sb.Append("Price\t"); sb.Append("Profit Loss\t"); sb.Append("Floating P/L\t"); sb.Append("Spread\t"); sb.Append("Rollover\t"); sb.Append("Balance\t"); sb.Append("Equity\t"); sb.Append("Interpolation" + Environment.NewLine); for (int bar = 0; bar < Data.Bars; bar++) { sb.Append((bar + 1).ToString() + "\t"); sb.Append(Data.Time[bar].ToString(sDF) + "\t"); sb.Append(Data.Time[bar].ToString("HH:mm") + "\t"); sb.Append(Data.Open[bar].ToString(FF) + "\t"); sb.Append(Data.High[bar].ToString(FF) + "\t"); sb.Append(Data.Low[bar].ToString(FF) + "\t"); sb.Append(Data.Close[bar].ToString(FF) + "\t"); sb.Append(Data.Volume[bar].ToString() + "\t"); if (Backtester.IsPos(bar)) { sb.Append(Backtester.SummaryDir(bar).ToString() + "\t"); sb.Append(Backtester.SummaryLots(bar).ToString() + "\t"); sb.Append(Backtester.SummaryTrans(bar).ToString() + "\t"); sb.Append(Backtester.SummaryPrice(bar).ToString(FF) + "\t"); sb.Append(Backtester.ProfitLoss(bar).ToString() + "\t"); sb.Append(Backtester.FloatingPL(bar).ToString() + "\t"); } else { sb.Append("\t\t\t\t\t\t"); } sb.Append(Backtester.ChargedSpread(bar).ToString() + "\t"); sb.Append(Backtester.ChargedRollOver(bar).ToString() + "\t"); sb.Append(Backtester.Balance(bar).ToString() + "\t"); sb.Append(Backtester.Equity(bar).ToString() + "\t"); sb.Append(Backtester.BackTestEval(bar) + "\t"); sb.Append(Environment.NewLine); } string fileName = Data.Strategy.StrategyName + "-" + Data.Symbol.ToString() + "-" + Data.Period.ToString(); SaveData(fileName); return; }
/// <summary> /// Updates the journal data from the backtester /// </summary> void UpdateJournalData() { asJournalData = new string[shownBars, columns]; aiPositionIcons = new Image[shownBars]; for (int bar = firstBar; bar < firstBar + shownBars; bar++) { int row = bar - firstBar; asJournalData[row, 0] = (bar + 1).ToString(); asJournalData[row, 1] = Data.Time[bar].ToString(Data.DF); asJournalData[row, 2] = Data.Time[bar].ToString("HH:mm"); asJournalData[row, 3] = Data.Open[bar].ToString(Data.FF); asJournalData[row, 4] = Data.High[bar].ToString(Data.FF); asJournalData[row, 5] = Data.Low[bar].ToString(Data.FF); asJournalData[row, 6] = Data.Close[bar].ToString(Data.FF); asJournalData[row, 7] = Data.Volume[bar].ToString(); if (Backtester.IsPos(bar)) { asJournalData[row, 8] = Language.T(Backtester.SummaryTrans(bar).ToString()); asJournalData[row, 9] = Language.T(Backtester.SummaryDir(bar).ToString()); if (Configs.AccountInMoney) { string sign = Backtester.SummaryDir(bar) == PosDirection.Short ? "-" : ""; asJournalData[row, 10] = sign + Backtester.SummaryAmount(bar).ToString(); } else { asJournalData[row, 10] = Backtester.SummaryLots(bar).ToString(); } asJournalData[row, 11] = Backtester.SummaryPrice(bar).ToString(Data.FF); if (Configs.AccountInMoney) { // Profit Loss if (Backtester.SummaryTrans(bar) == Transaction.Close || Backtester.SummaryTrans(bar) == Transaction.Reduce || Backtester.SummaryTrans(bar) == Transaction.Reverse) { asJournalData[row, 12] = Backtester.MoneyProfitLoss(bar).ToString("F2"); } else { asJournalData[row, 12] = "-"; } // Floating Profit Loss if (Backtester.SummaryTrans(bar) != Transaction.Close) { asJournalData[row, 13] = Backtester.MoneyFloatingPL(bar).ToString("F2"); } else { asJournalData[row, 13] = "-"; } } else { // Profit Loss if (Backtester.SummaryTrans(bar) == Transaction.Close || Backtester.SummaryTrans(bar) == Transaction.Reduce || Backtester.SummaryTrans(bar) == Transaction.Reverse) { asJournalData[row, 12] = Backtester.ProfitLoss(bar).ToString(); } else { asJournalData[row, 12] = "-"; } // Floating Profit Loss if (Backtester.SummaryTrans(bar) != Transaction.Close) { asJournalData[row, 13] = Backtester.FloatingPL(bar).ToString(); } else { asJournalData[row, 13] = "-"; } } // Icons aiPositionIcons[row] = Backtester.SummaryPositionIcon(bar); } else { // Icons aiPositionIcons[row] = Properties.Resources.pos_square; } if (Configs.AccountInMoney) { asJournalData[row, 14] = Backtester.MoneyBalance(bar).ToString("F2"); asJournalData[row, 15] = Backtester.MoneyEquity(bar).ToString("F2"); } else { asJournalData[row, 14] = Backtester.Balance(bar).ToString(); asJournalData[row, 15] = Backtester.Equity(bar).ToString(); } asJournalData[row, 16] = Backtester.SummaryRequiredMargin(bar).ToString("F2"); asJournalData[row, 17] = Backtester.SummaryFreeMargin(bar).ToString("F2"); asJournalData[row, 18] = Language.T(Backtester.BackTestEval(bar)); } return; }