/// <summary> /// Constructor /// </summary> public FancyPanel(string captionText, Color borderColor) { _caption = captionText; _colorCaptionBack = borderColor; _brushCaption = new SolidBrush(LayoutColors.ColorCaptionText); _penBorder = new Pen(Data.GetGradientColor(borderColor, -LayoutColors.DepthCaption), Border); InitializeParameters(); }
/// <summary> /// Constructor /// </summary> public Fancy_Panel(string sCaption, Color colorCaption) { this.caption = sCaption; colorCaptionBack = colorCaption; brushCaption = new SolidBrush(LayoutColors.ColorCaptionText); penBorder = new Pen(Data.GetGradientColor(colorCaption, -LayoutColors.DepthCaption), border); InitializeParameters(); return; }
/// <summary> /// Sets the journal colors /// </summary> void SetJournalColors() { colorBack = LayoutColors.ColorControlBack; colorCaptionBack = LayoutColors.ColorCaptionBack; brushCaptionText = new SolidBrush(LayoutColors.ColorCaptionText); brushEvenRowBack = new SolidBrush(LayoutColors.ColorEvenRowBack); brushRowText = new SolidBrush(LayoutColors.ColorControlText); penLines = new Pen(LayoutColors.ColorJournalLines); penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); return; }
/// <summary> /// Sets the panel colors /// </summary> public void SetColors() { _colorCaptionBack = LayoutColors.ColorCaptionBack; _colorBackroundEvenRows = LayoutColors.ColorEvenRowBack; _colorBackroundWarningRow = LayoutColors.ColorWarningRowBack; _colorTextWarningRow = LayoutColors.ColorWarningRowText; _colorBackroundOddRows = LayoutColors.ColorOddRowBack; _brushCaption = new SolidBrush(LayoutColors.ColorCaptionText); _brushParams = new SolidBrush(LayoutColors.ColorControlText); _brushData = new SolidBrush(LayoutColors.ColorControlText); _penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), Border); }
/// <summary> /// Sets the journal colors /// </summary> private void SetJournalColors() { _colorBack = LayoutColors.ColorControlBack; _brushCaptionText = new SolidBrush(LayoutColors.ColorCaptionText); _brushEvenRowBack = new SolidBrush(LayoutColors.ColorEvenRowBack); _brushRowText = new SolidBrush(LayoutColors.ColorControlText); _penLines = new Pen(LayoutColors.ColorJournalLines); _penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), Border); ButtonsColorBack = LayoutColors.ColorCaptionBack; ButtonColorFore = LayoutColors.ColorCaptionText; ContextMenuColorBack = LayoutColors.ColorControlBack; ContextMenuColorFore = LayoutColors.ColorControlText; }
/// <summary> /// Paints panel pnlChart /// </summary> void PnlChart_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clear(LayoutColors.ColorChartBack); if (!Data.IsData || !Data.IsResult) { return; } Panel pnl = (Panel)sender; Pen penFore = new Pen(LayoutColors.ColorControlText); string FF = Data.FF; // Format modifier to print the floats int width = pnl.ClientSize.Width; Size size = new Size(width, infoRowHeight); StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Near; // Caption background PointF pntStart = new PointF(0, 0); SizeF szfCaption = new Size(width, infoRowHeight); RectangleF rectfCaption = new RectangleF(pntStart, szfCaption); Data.GradientPaint(g, rectfCaption, LayoutColors.ColorCaptionBack, LayoutColors.DepthCaption); // Caption Text StringFormat stringFormatCaption = new StringFormat(); stringFormatCaption.LineAlignment = StringAlignment.Center; stringFormatCaption.Trimming = StringTrimming.EllipsisCharacter; stringFormatCaption.FormatFlags = StringFormatFlags.NoWrap; stringFormatCaption.Alignment = StringAlignment.Center; string stringCaptionText = Language.T("Price Route Inside the Bar"); rectfCaption = new RectangleF(border, 0, pnl.ClientSize.Width - 2 * border, infoRowHeight); g.DrawString(stringCaptionText, fontInfo, brushCaptionText, rectfCaption, stringFormatCaption); // Paint the panel background RectangleF rectClient = new RectangleF(0, infoRowHeight, pnl.ClientSize.Width, pnl.Height - infoRowHeight); Data.GradientPaint(g, rectClient, LayoutColors.ColorChartBack, LayoutColors.DepthControl); // Paint bar info RectangleF rectBarInfo = new RectangleF(border, infoRowHeight + 1, pnl.ClientSize.Width - 2 * border, infoRowHeight); g.DrawString(barInfo, fontInfo, brushGridText, rectBarInfo, stringFormatCaption); // Searching the min and the max price and volume width = pnl.ClientSize.Width - 2 * border; double maxPrice = Data.High[bar]; double minPrice = Data.Low[bar]; int space = 8; int spcRight = szPrice.Width + 4; int XLeft = border + space; int XRight = width - spcRight; int chartWidth = XRight - XLeft; int YTop = 2 * infoRowHeight + 6; int YBottom = pnl.ClientSize.Height - 22; int barPixels = 28; int spcLeft = 3; int x = barPixels + spcLeft; int pointLeft = x + barPixels + 30; int pointX = pointLeft; int pointRight = XRight - 20; int points = Backtester.WayPoints(bar); int pointRadius = 3; // Grid int iCntLabels = (int)Math.Max((YBottom - YTop) / 30d, 1); double deltaPoint = (Data.InstrProperties.Digits == 5 || Data.InstrProperties.Digits == 3) ? Data.InstrProperties.Point * 100 : Data.InstrProperties.Point * 10; double delta = Math.Max(Math.Round((maxPrice - minPrice) / iCntLabels, Data.InstrProperties.Point < 0.001 ? 3 : 1), deltaPoint); minPrice = Math.Round(minPrice, Data.InstrProperties.Point < 0.001f ? 3 : 1) - Data.InstrProperties.Point * 10; minPrice -= delta; maxPrice += delta; iCntLabels = (int)Math.Ceiling((maxPrice - minPrice) / delta); maxPrice = minPrice + iCntLabels * delta; double scaleY = (YBottom - YTop) / (iCntLabels * delta); int yOpen = (int)(YBottom - (Data.Open[bar] - minPrice) * scaleY); int yHigh = (int)(YBottom - (Data.High[bar] - minPrice) * scaleY); int yLow = (int)(YBottom - (Data.Low[bar] - minPrice) * scaleY); int yClose = (int)(YBottom - (Data.Close[bar] - minPrice) * scaleY); // Find the price distance double priceDistance = 0; for (int point = 1; point < points; point++) { priceDistance += Math.Abs(Backtester.WayPoint(bar, point).Price - Backtester.WayPoint(bar, point - 1).Price); } double dPriceForAPixel = (pointRight - pointLeft) / priceDistance; // Points X int[] aiPointX = new int[points]; aiPointX[0] = pointLeft; for (int point = 1; point < points - 1; point++) { int iDistance = (int)(Math.Abs(Backtester.WayPoint(bar, point).Price - Backtester.WayPoint(bar, point - 1).Price) * dPriceForAPixel); aiPointX[point] = aiPointX[point - 1] + iDistance; } aiPointX[points - 1] = pointRight; for (int point = 1; point < points - 1; point++) { if (aiPointX[point] - aiPointX[point - 1] < barPixels + 1) { aiPointX[point] = aiPointX[point - 1] + barPixels + 1; } } for (int point = points - 2; point > 0; point--) { if (aiPointX[point + 1] - aiPointX[point] < barPixels + 1) { aiPointX[point] = aiPointX[point + 1] - barPixels - 1; } } // Find coordinates of the Way Points Point[] pntWay = new Point[points]; for (int point = 0; point < points; point++) { int pointY = (int)(YBottom - (Backtester.WayPoint(bar, point).Price - minPrice) * scaleY); pntWay[point] = new Point(aiPointX[point], pointY); } // Horizontal grid and Price labels for (double label = minPrice; label <= maxPrice + Data.InstrProperties.Point; label += delta) { int labelY = (int)(YBottom - (label - minPrice) * scaleY); g.DrawString(label.ToString(Data.FF), Font, brushGridText, XRight, labelY - Font.Height / 2 - 1); g.DrawLine(penGrid, border + space, labelY, XRight, labelY); } // Vertical Grid g.DrawLine(penGrid, x + barPixels / 2 - 1, YTop, x + barPixels / 2 - 1, YBottom + 2); for (int point = 0; point < points; point++) { Point pt1 = new Point(pntWay[point].X, YTop); Point pt2 = new Point(pntWay[point].X, YBottom + 2); Point pt3 = new Point(pntWay[point].X - 5, YBottom + 4); g.DrawLine(penGrid, pt1, pt2); g.DrawString((point + 1).ToString(), Font, brushGridText, pt3); } // Bar Number string barNumber = (bar + 1).ToString(); int stringX = x + barPixels / 2 - 1 - g.MeasureString(barNumber, Font).ToSize().Width / 2; if (Backtester.BackTestEval(bar) == "Ambiguous") { g.DrawString(barNumber, Font, brushRed, stringX, YBottom + 4); } else { g.DrawString(barNumber, Font, brushGridText, stringX, YBottom + 4); } // Draw the bar g.DrawLine(penBarBorder, x + barPixels / 2 - 1, yLow, x + barPixels / 2 - 1, yHigh); if (yClose < yOpen) // White bar { Rectangle rect = new Rectangle(x, yClose, barPixels - 2, yOpen - yClose); LinearGradientBrush lgBrush = new LinearGradientBrush(rect, colorBarWight1, colorBarWight2, 5f); g.FillRectangle(lgBrush, rect); g.DrawRectangle(penBarBorder, x, yClose, barPixels - 2, yOpen - yClose); } else if (yClose > yOpen) // Black bar { Rectangle rect = new Rectangle(x, yOpen, barPixels - 2, yClose - yOpen); LinearGradientBrush lgBrush = new LinearGradientBrush(rect, colorBarBlack1, colorBarBlack2, 5f); g.FillRectangle(lgBrush, rect); g.DrawRectangle(penBarBorder, x, yOpen, barPixels - 2, yClose - yOpen); } else // Cross { g.DrawLine(penBarBorder, x, yClose, x + barPixels - 2, yClose); } // Draw cancelled orders for (int orderIndex = 0; orderIndex < Backtester.Orders(bar); orderIndex++) { int ordNumber = Backtester.OrdNumb(bar, orderIndex); Order order = Backtester.OrdFromNumb(ordNumber); if (order.OrdStatus != OrderStatus.Cancelled) { continue; } if (order.OrdPrice > Data.High[bar] || order.OrdPrice < Data.Low[bar]) { continue; } int d = barPixels / 2 - 1; int x1 = x + d; int x2 = x + barPixels - 2; int yDeal = (int)(YBottom - (order.OrdPrice - minPrice) * scaleY); Pen pen = new Pen(LayoutColors.ColorChartGrid, 2); if (order.OrdDir == OrderDirection.Buy) { g.DrawLine(pen, x, yDeal, x1, yDeal); g.DrawLine(pen, x1, yDeal, x2, yDeal - d); g.DrawLine(pen, x2 + 1, yDeal - d + 1, x1 + d / 2 + 1, yDeal - d + 1); g.DrawLine(pen, x2, yDeal - d, x2, yDeal - d / 2); } else if (order.OrdDir == OrderDirection.Sell) { g.DrawLine(pen, x, yDeal + 1, x1 + 1, yDeal + 1); g.DrawLine(pen, x1, yDeal, x2, yDeal + d); g.DrawLine(pen, x1 + d / 2 + 1, yDeal + d, x2, yDeal + d); g.DrawLine(pen, x2, yDeal + d, x2, yDeal + d / 2 + 1); } } // Draw the deals on the bar for (int pos = 0; pos < Backtester.Positions(bar); pos++) { if (Backtester.PosTransaction(bar, pos) == Transaction.Transfer) { continue; } int yDeal = (int)(YBottom - (Backtester.PosOrdPrice(bar, pos) - minPrice) * scaleY); if (Backtester.PosDir(bar, pos) == PosDirection.Long || Backtester.PosDir(bar, pos) == PosDirection.Short) { int d = barPixels / 2 - 1; int x1 = x + d; int x2 = x + barPixels - 2; if (Backtester.OrdFromNumb(Backtester.PosOrdNumb(bar, pos)).OrdDir == OrderDirection.Buy) { // Buy Pen pen = new Pen(LayoutColors.ColorTradeLong, 2); g.DrawLine(pen, x, yDeal, x1, yDeal); g.DrawLine(pen, x1, yDeal, x2, yDeal - d); g.DrawLine(pen, x2 + 1, yDeal - d + 1, x1 + d / 2 + 1, yDeal - d + 1); g.DrawLine(pen, x2, yDeal - d, x2, yDeal - d / 2); } else { // Sell Pen pen = new Pen(LayoutColors.ColorTradeShort, 2); g.DrawLine(pen, x, yDeal + 1, x1 + 1, yDeal + 1); g.DrawLine(pen, x1, yDeal, x2, yDeal + d); g.DrawLine(pen, x1 + d / 2 + 1, yDeal + d, x2, yDeal + d); g.DrawLine(pen, x2, yDeal + d, x2, yDeal + d / 2 + 1); } } else if (Backtester.PosDir(bar, pos) == PosDirection.Closed) { // Close position int d = barPixels / 2 - 1; int x1 = x + d; int x2 = x + barPixels - 3; Pen pen = new Pen(LayoutColors.ColorTradeClose, 2); g.DrawLine(pen, x, yDeal, x1, yDeal); g.DrawLine(pen, x1, yDeal + d / 2, x2, yDeal - d / 2); g.DrawLine(pen, x1, yDeal - d / 2, x2, yDeal + d / 2); } } // Draw position lots for (int point = 0; point < points; point++) { int posNumber = Backtester.WayPoint(bar, point).PosNumb; if (posNumber == -1) { continue; } double posLots = Backtester.PosFromNumb(posNumber).PosLots; PosDirection posDirection = Backtester.PosFromNumb(posNumber).PosDir; WayPointType wpType = Backtester.WayPoint(bar, point).WPType; int posHight = (int)(Math.Max(posLots * 2, 2)); int posY = YBottom - posHight; int d = (barPixels - 1) / 2; x = pntWay[point].X - d; if (posDirection == PosDirection.Long) { // Long Rectangle rect = new Rectangle(x - 1, posY, barPixels + 1, posHight); LinearGradientBrush lgBrush = new LinearGradientBrush(rect, colorLongTrade1, colorLongTrade2, 0f); rect = new Rectangle(x, posY, barPixels - 1, posHight); g.FillRectangle(lgBrush, rect); } else if (posDirection == PosDirection.Short) { // Short Rectangle rect = new Rectangle(x - 1, posY, barPixels + 1, posHight); LinearGradientBrush lgBrush = new LinearGradientBrush(rect, colorShortTrade1, colorShortTrade2, 0f); rect = new Rectangle(x, posY, barPixels - 1, posHight); g.FillRectangle(lgBrush, rect); } else if (posDirection == PosDirection.Closed && wpType == WayPointType.Exit) { // Closed Rectangle rect = new Rectangle(x - 1, YBottom - 2, barPixels + 1, 2); LinearGradientBrush lgBrush = new LinearGradientBrush(rect, colorClosedTrade1, colorClosedTrade2, 0f); rect = new Rectangle(x, YBottom - 2, barPixels - 1, 2); g.FillRectangle(lgBrush, rect); } } // Draw the Beziers for (int point = 1; point < points; point++) { Point ptKnot1 = pntWay[point - 1]; Point ptKnot2 = pntWay[point]; int ctrlX1 = (ptKnot1.X + ptKnot2.X) / 2; int ctrlX2 = (ptKnot1.X + ptKnot2.X) / 2; int ctrlY1 = ptKnot1.Y; int ctrlY2 = ptKnot2.Y; if (point > 1) { if (pntWay[point - 2].Y > pntWay[point - 1].Y && pntWay[point - 1].Y > pntWay[point].Y || pntWay[point - 2].Y < pntWay[point - 1].Y && pntWay[point - 1].Y < pntWay[point].Y) { ctrlY1 = (pntWay[point - 1].Y + pntWay[point].Y) / 2; } } if (point < points - 1) { if (pntWay[point - 1].Y > pntWay[point].Y && pntWay[point].Y > pntWay[point + 1].Y || pntWay[point - 1].Y < pntWay[point].Y && pntWay[point].Y < pntWay[point + 1].Y) { ctrlY2 = (pntWay[point - 1].Y + pntWay[point].Y) / 2; } } if (point == 1) { ctrlX1 = ptKnot1.X; ctrlY1 = ptKnot1.Y; } if (point == points - 1) { ctrlX2 = ptKnot2.X; ctrlY2 = ptKnot2.Y; } Point ptControl1 = new Point(ctrlX1, ctrlY1); Point ptControl2 = new Point(ctrlX2, ctrlY2); g.DrawBezier(penCross, ptKnot1, ptControl1, ptControl2, ptKnot2); } // Draw the WayPoints Brush brushWeyPnt = new SolidBrush(LayoutColors.ColorChartBack); for (int point = 0; point < points; point++) { g.FillEllipse(brushWeyPnt, pntWay[point].X - pointRadius, pntWay[point].Y - pointRadius, 2 * pointRadius, 2 * pointRadius); g.DrawEllipse(penCross, pntWay[point].X - pointRadius, pntWay[point].Y - pointRadius, 2 * pointRadius, 2 * pointRadius); } // Draw the deals on the route for (int point = 0; point < points; point++) { int posNumber = Backtester.WayPoint(bar, point).PosNumb; int ordNumber = Backtester.WayPoint(bar, point).OrdNumb; if (posNumber < 0 || ordNumber < 0) { continue; } PosDirection posDirection = Backtester.PosFromNumb(posNumber).PosDir; OrderDirection ordDirection = Backtester.OrdFromNumb(ordNumber).OrdDir; WayPointType wpType = Backtester.WayPoint(bar, point).WPType; if (Backtester.PosFromNumb(posNumber).Transaction == Transaction.Transfer || wpType == WayPointType.Cancel || wpType == WayPointType.None || wpType == WayPointType.Open || wpType == WayPointType.High || wpType == WayPointType.Low || wpType == WayPointType.Close) { continue; } int yDeal = pntWay[point].Y; if (posDirection == PosDirection.Long || posDirection == PosDirection.Short) { int d = barPixels / 2 - 1; x = pntWay[point].X - d; int x1 = pntWay[point].X; int x2 = x + barPixels - 2; if (ordDirection == OrderDirection.Buy) { // Buy Pen pen = new Pen(LayoutColors.ColorTradeLong, 2); g.DrawLine(pen, x, yDeal, x1, yDeal); g.DrawLine(pen, x1, yDeal, x2, yDeal - d); g.DrawLine(pen, x2 + 1, yDeal - d + 1, x1 + d / 2 + 1, yDeal - d + 1); g.DrawLine(pen, x2, yDeal - d, x2, yDeal - d / 2); } else { // Sell Pen pen = new Pen(LayoutColors.ColorTradeShort, 2); g.DrawLine(pen, x, yDeal + 1, x1 + 1, yDeal + 1); g.DrawLine(pen, x1, yDeal, x2, yDeal + d); g.DrawLine(pen, x1 + d / 2 + 1, yDeal + d, x2, yDeal + d); g.DrawLine(pen, x2, yDeal + d, x2, yDeal + d / 2 + 1); } } else if (posDirection == PosDirection.Closed) { // Close position int d = barPixels / 2 - 1; x = pntWay[point].X - d; int x1 = pntWay[point].X; int x2 = x + barPixels - 3; Pen pen = new Pen(LayoutColors.ColorTradeClose, 2); g.DrawLine(pen, x, yDeal, x1, yDeal); g.DrawLine(pen, x1, yDeal + d / 2, x2, yDeal - d / 2); g.DrawLine(pen, x1, yDeal - d / 2, x2, yDeal + d / 2); } } // Coordinate axes g.DrawLine(penAxes, XLeft, YTop - 4, XLeft, YBottom); // Vertical left line g.DrawLine(penAxes, XLeft, YBottom, XRight, YBottom); // Border Pen penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); g.DrawLine(penBorder, 1, infoRowHeight, 1, pnl.ClientSize.Height); g.DrawLine(penBorder, pnl.ClientSize.Width - border + 1, infoRowHeight, pnl.ClientSize.Width - border + 1, pnl.ClientSize.Height); g.DrawLine(penBorder, 0, pnl.ClientSize.Height - border + 1, pnl.ClientSize.Width, pnl.ClientSize.Height - border + 1); }
/// <summary> /// Paints the charts /// </summary> private void PnlChartPaint(object sender, PaintEventArgs e) { var pnl = (Panel)sender; Graphics g = e.Graphics; const int space = 5; const int border = 2; // Chart Title string unit = " [" + (Configs.AccountInMoney ? Configs.AccountCurrency : Language.T("pips")) + "]"; string str = Language.T("Balance Chart") + unit; var font = new Font(Font.FontFamily, 9); var fCaptionHeight = (float)Math.Max(font.Height, 18); var rectfCaption = new RectangleF(0, 0, pnl.ClientSize.Width, fCaptionHeight); var stringFormatCaption = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; Data.GradientPaint(g, rectfCaption, LayoutColors.ColorCaptionBack, LayoutColors.DepthCaption); g.DrawString(str, Font, new SolidBrush(LayoutColors.ColorCaptionText), rectfCaption, stringFormatCaption); // Paint the panel background var rectClient = new RectangleF(border, fCaptionHeight, pnl.ClientSize.Width - 2 * border, pnl.Height - fCaptionHeight - border); Data.GradientPaint(g, rectClient, LayoutColors.ColorChartBack, LayoutColors.DepthControl); var penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); g.DrawLine(penBorder, 1, fCaptionHeight, 1, pnl.ClientSize.Height); g.DrawLine(penBorder, pnl.ClientSize.Width - border + 1, fCaptionHeight, pnl.ClientSize.Width - border + 1, pnl.ClientSize.Height); g.DrawLine(penBorder, 0, pnl.ClientSize.Height - border + 1, pnl.ClientSize.Width, pnl.ClientSize.Height - border + 1); if (!_isPaintChart) { if (Backtester.AmbiguousBars == 0) { string sNote = Language.T("The Comparator is useful when the backtest shows ambiguous bars!"); var rectfNote = new RectangleF(0, 30, pnl.ClientSize.Width, Font.Height); g.DrawString(sNote, Font, new SolidBrush(LayoutColors.ColorChartFore), rectfNote, stringFormatCaption); } return; } int bars = Data.Bars - Data.FirstBar; int max = (int)Math.Max(_maximum, _maximumRandom) + 1; int min = (int)Math.Min(_minimum, _minimumRandom) - 1; min = (int)Math.Floor(min / 10f) * 10; int yTop = (int)fCaptionHeight + 2 * space + 1; int yBottom = (pnl.ClientSize.Height - 2 * space - border); var labelWidth = (int) Math.Max(g.MeasureString(min.ToString(CultureInfo.InvariantCulture), Font).Width, g.MeasureString(max.ToString(CultureInfo.InvariantCulture), Font).Width); labelWidth = Math.Max(labelWidth, 30); int xRight = pnl.ClientSize.Width - border - space - labelWidth; // // Grid // int cntLabels = Math.Max((yBottom - yTop) / 20, 1); var delta = (float)Math.Max(Math.Round((max - min) / (float)cntLabels), 10); int step = (int)Math.Ceiling(delta / 10) * 10; cntLabels = (int)Math.Ceiling((max - min) / (float)step); max = min + cntLabels * step; float scaleY = (yBottom - yTop) / (cntLabels * (float)step); Brush brushFore = new SolidBrush(LayoutColors.ColorChartFore); var penGrid = new Pen(LayoutColors.ColorChartGrid) { DashStyle = DashStyle.Dash, DashPattern = new float[] { 4, 2 } }; // Price labels for (int label = min; label <= max; label += step) { var labelY = (int)(yBottom - (label - min) * scaleY); g.DrawString(label.ToString(CultureInfo.InvariantCulture), Font, brushFore, xRight, labelY - Font.Height / 2 - 1); g.DrawLine(penGrid, border + space, labelY, xRight, labelY); } float fScaleX = (xRight - 2 * space - border) / (float)bars; if (_isRandom) { // Draws the random area and Min Max lines var apntMinRandom = new PointF[bars]; var apntMaxRandom = new PointF[bars]; for (int iBar = 0; iBar < bars; iBar++) { apntMinRandom[iBar].X = border + space + iBar * fScaleX; apntMinRandom[iBar].Y = yBottom - (_afMinRandom[iBar] - min) * scaleY; apntMaxRandom[iBar].X = border + space + iBar * fScaleX; apntMaxRandom[iBar].Y = yBottom - (_afMaxRandom[iBar] - min) * scaleY; } apntMinRandom[0].Y = apntMaxRandom[0].Y; var path = new GraphicsPath(); path.AddLines(apntMinRandom); path.AddLine(apntMinRandom[bars - 1], apntMaxRandom[bars - 1]); path.AddLines(apntMaxRandom); var region = new Region(path); g.FillRegion(_brushRandArea, region); g.DrawLines(_penRandBands, apntMinRandom); g.DrawLines(_penRandBands, apntMaxRandom); } // Draws the lines for (int m = 0; m < _countMethods; m++) { if (!AchboxMethods[m].Checked) { continue; } var apntLines = new PointF[bars]; for (int iBar = 0; iBar < bars; iBar++) { apntLines[iBar].X = border + space + iBar * fScaleX; apntLines[iBar].Y = yBottom - (_afMethods[m, iBar] - min) * scaleY; } var pen = new Pen(LayoutColors.ColorSignalRed); switch ((InterpolationMethod)AchboxMethods[m].Tag) { case InterpolationMethod.Pessimistic: pen = _penPessimistic; break; case InterpolationMethod.Shortest: pen = _penShortest; break; case InterpolationMethod.Nearest: pen = _penNearest; break; case InterpolationMethod.Optimistic: pen = _penOptimistic; break; case InterpolationMethod.Random: pen = _penRandom; break; } g.DrawLines(pen, apntLines); } // Draws the average balance var apntBalance = new PointF[bars]; for (int bar = 0; bar < bars; bar++) { apntBalance[bar].X = border + space + bar * fScaleX; apntBalance[bar].Y = yBottom - (_afBalance[bar] - min) * scaleY; } g.DrawLines(_penBalance, apntBalance); // Coordinate axes g.DrawLine(new Pen(LayoutColors.ColorChartFore), border + space - 1, yTop - space, border + space - 1, yBottom); g.DrawLine(new Pen(LayoutColors.ColorChartFore), border + space, yBottom, xRight, yBottom); // Balance label float fBalanceY = yBottom - (_afBalance[bars - 1] - min) * scaleY; g.DrawLine(new Pen(LayoutColors.ColorChartCross), border + space, fBalanceY, xRight - space, fBalanceY); var szBalance = new Size(labelWidth + space, Font.Height + 2); var point = new Point(xRight - space + 2, (int)(fBalanceY - Font.Height / 2.0 - 1)); var rec = new Rectangle(point, szBalance); string sBalance = ((int)_afBalance[bars - 1]).ToString(CultureInfo.InvariantCulture); g.FillRectangle(new SolidBrush(LayoutColors.ColorLabelBack), rec); g.DrawRectangle(new Pen(LayoutColors.ColorChartCross), rec); g.DrawString(sBalance, Font, new SolidBrush(LayoutColors.ColorLabelText), rec, stringFormatCaption); // Scanning note var fontNote = new Font(Font.FontFamily, Font.Size - 1); if (Configs.Autoscan && !Data.IsIntrabarData) { g.DrawString(Language.T("Load intrabar data"), fontNote, Brushes.Red, border + space, fCaptionHeight - 2); } else if (Backtester.IsScanPerformed) { g.DrawString(Language.T("Scanned") + " MQ " + Data.ModellingQuality.ToString("N2") + "%", fontNote, Brushes.LimeGreen, border + space, fCaptionHeight - 2); } // Scanned bars if (Data.IntraBars != null && Data.IsIntrabarData && Backtester.IsScanPerformed) { g.DrawLine(new Pen(LayoutColors.ColorChartFore), border + space - 1, yBottom, border + space - 1, yBottom + 8); DataPeriods dataPeriod = Data.Period; Color color = Data.PeriodColor[Data.Period]; int iFromBar = Data.FirstBar; for (int bar = Data.FirstBar; bar < Data.Bars; bar++) { if (Data.IntraBarsPeriods[bar] != dataPeriod || bar == Data.Bars - 1) { int xStart = (int)((iFromBar - Data.FirstBar) * fScaleX) + border + space; int xEnd = (int)((bar - Data.FirstBar) * fScaleX) + border + space; iFromBar = bar; dataPeriod = Data.IntraBarsPeriods[bar]; Data.GradientPaint(g, new RectangleF(xStart, yBottom + 3, xEnd - xStart + 2, 5), color, 60); color = Data.PeriodColor[Data.IntraBarsPeriods[bar]]; } } } }
/// <summary> /// Panel Slot Paint /// </summary> void PnlSlot_Paint(object sender, PaintEventArgs e) { Panel pnl = (Panel)sender; Graphics g = e.Graphics; int slot = (int)pnl.Tag; int width = pnl.ClientSize.Width; SlotTypes slotType = strategy.GetSlotType(slot); Color colorBackground = LayoutColors.ColorSlotBackground; Color colorCaptionText = LayoutColors.ColorSlotCaptionText; Color colorCaptionBackOpen = LayoutColors.ColorSlotCaptionBackOpen; Color colorCaptionBackOpenFilter = LayoutColors.ColorSlotCaptionBackOpenFilter; Color colorCaptionBackClose = LayoutColors.ColorSlotCaptionBackClose; Color colorCaptionBackCloseFilter = LayoutColors.ColorSlotCaptionBackCloseFilter; Color colorIndicatorNameText = LayoutColors.ColorSlotIndicatorText; Color colorLogicText = LayoutColors.ColorSlotLogicText; Color colorParamText = LayoutColors.ColorSlotParamText; Color colorValueText = LayoutColors.ColorSlotValueText; Color colorDash = LayoutColors.ColorSlotDash; // Caption string stringCaptionText = string.Empty; Color colorCaptionBack = LayoutColors.ColorSignalRed; switch (slotType) { case SlotTypes.Open: stringCaptionText = Language.T("Opening Point of the Position"); colorCaptionBack = colorCaptionBackOpen; break; case SlotTypes.OpenFilter: stringCaptionText = Language.T("Opening Logic Condition"); colorCaptionBack = colorCaptionBackOpenFilter; break; case SlotTypes.Close: stringCaptionText = Language.T("Closing Point of the Position"); colorCaptionBack = colorCaptionBackClose; break; case SlotTypes.CloseFilter: stringCaptionText = Language.T("Closing Logic Condition"); colorCaptionBack = colorCaptionBackCloseFilter; break; default: break; } Pen penBorder = new Pen(Data.GetGradientColor(colorCaptionBack, -LayoutColors.DepthCaption), border); Font fontCaptionText = new Font(Font.FontFamily, 9); float fCaptionHeight = (float)Math.Max(fontCaptionText.Height, 18); float fCaptionWidth = width; Brush brushCaptionText = new SolidBrush(colorCaptionText); StringFormat stringFormatCaption = new StringFormat(); stringFormatCaption.LineAlignment = StringAlignment.Center; stringFormatCaption.Trimming = StringTrimming.EllipsisCharacter; stringFormatCaption.FormatFlags = StringFormatFlags.NoWrap; stringFormatCaption.Alignment = StringAlignment.Center; RectangleF rectfCaption = new RectangleF(0, 0, fCaptionWidth, fCaptionHeight); Data.GradientPaint(g, rectfCaption, colorCaptionBack, LayoutColors.DepthCaption); if (showRemoveSlotButtons && slot != strategy.OpenSlot && slot != strategy.CloseSlot) { int iButtonDimentions = (int)fCaptionHeight - 2; int iButtonX = width - iButtonDimentions - 1; abtnRemoveSlot[slot].Size = new Size(iButtonDimentions, iButtonDimentions); abtnRemoveSlot[slot].Location = new Point(iButtonX, 1); float fCaptionTextWidth = g.MeasureString(stringCaptionText, fontCaptionText).Width; float fCaptionTextX = (float)Math.Max((fCaptionWidth - fCaptionTextWidth) / 2f, 0); PointF pfCaptionText = new PointF(fCaptionTextX, 0); SizeF sfCaptionText = new SizeF(iButtonX - fCaptionTextX, fCaptionHeight); rectfCaption = new RectangleF(pfCaptionText, sfCaptionText); stringFormatCaption.Alignment = StringAlignment.Near; } g.DrawString(stringCaptionText, fontCaptionText, brushCaptionText, rectfCaption, stringFormatCaption); // Border g.DrawLine(penBorder, 1, fCaptionHeight, 1, pnl.Height); g.DrawLine(penBorder, pnl.Width - border + 1, fCaptionHeight, pnl.Width - border + 1, pnl.Height); g.DrawLine(penBorder, 0, pnl.Height - border + 1, pnl.Width, pnl.Height - border + 1); // Paints the panel RectangleF rectfPanel = new RectangleF(border, fCaptionHeight, pnl.Width - 2 * border, pnl.Height - fCaptionHeight - border); Data.GradientPaint(g, rectfPanel, colorBackground, LayoutColors.DepthControl); int iVPosition = (int)fCaptionHeight + 3; // Padlock image if (showPadlockImg) { if (strategy.Slot[slot].SlotStatus == StrategySlotStatus.Locked) { g.DrawImage(Properties.Resources.padlock_img, 1, 1, 16, 16); } else if (strategy.Slot[slot].SlotStatus == StrategySlotStatus.Open) { g.DrawImage(Properties.Resources.open_padlock, 1, 1, 16, 16); } else if (strategy.Slot[slot].SlotStatus == StrategySlotStatus.Linked) { g.DrawImage(Properties.Resources.linked, 1, 1, 16, 16); } } // Indicator name StringFormat stringFormatIndicatorName = new StringFormat(); stringFormatIndicatorName.Alignment = StringAlignment.Center; stringFormatIndicatorName.LineAlignment = StringAlignment.Center; stringFormatIndicatorName.FormatFlags = StringFormatFlags.NoWrap; Font fontIndicator = new Font(Font.FontFamily, 11f, FontStyle.Regular); Brush brushIndName = new SolidBrush(colorIndicatorNameText); float fIndNameHeight = fontIndicator.Height; float fGroupWidth = 0; if (Configs.UseLogicalGroups && (slotType == SlotTypes.OpenFilter || slotType == SlotTypes.CloseFilter)) { string sLogicalGroup = "[" + strategy.Slot[slot].LogicalGroup + "]"; fGroupWidth = g.MeasureString(sLogicalGroup, fontIndicator).Width; RectangleF rectGroup = new RectangleF(0, iVPosition, fGroupWidth, fIndNameHeight); g.DrawString(sLogicalGroup, fontIndicator, brushIndName, rectGroup, stringFormatIndicatorName); } stringFormatIndicatorName.Trimming = StringTrimming.EllipsisCharacter; string sIndicatorName = strategy.Slot[slot].IndicatorName; float fIndicatorWidth = g.MeasureString(sIndicatorName, fontIndicator).Width; RectangleF rectIndName; if (width >= 2 * fGroupWidth + fIndicatorWidth) { rectIndName = new RectangleF(0, iVPosition, width, fIndNameHeight); } else { rectIndName = new RectangleF(fGroupWidth, iVPosition, width - fGroupWidth, fIndNameHeight); } g.DrawString(sIndicatorName, fontIndicator, brushIndName, rectIndName, stringFormatIndicatorName); iVPosition += (int)fIndNameHeight; if (slotMinMidMax == SlotSizeMinMidMax.min) { return; } // Logic StringFormat stringFormatLogic = new StringFormat(); stringFormatLogic.Alignment = StringAlignment.Center; stringFormatLogic.LineAlignment = StringAlignment.Center; stringFormatLogic.Trimming = StringTrimming.EllipsisCharacter; stringFormatLogic.FormatFlags = StringFormatFlags.NoClip; float padding = space; if (strategy.Slot[slot].IndParam.ListParam[0].Enabled) { string sValue = strategy.Slot[slot].IndParam.ListParam[0].Text; Font fontLogic = new Font(Font.FontFamily, 10.5f, FontStyle.Regular); SizeF sizeValue = g.MeasureString(sValue, fontLogic, (int)(width - 2 * padding), stringFormatLogic); RectangleF rectValue = new RectangleF(padding, iVPosition, width - 2 * padding, sizeValue.Height); Brush brushLogic = new SolidBrush(colorLogicText); g.DrawString(sValue, fontLogic, brushLogic, rectValue, stringFormatLogic); iVPosition += (int)sizeValue.Height; } if (slotMinMidMax == SlotSizeMinMidMax.mid) { return; } // Parameters StringFormat stringFormat = new StringFormat(); stringFormat.Trimming = StringTrimming.EllipsisCharacter; stringFormat.FormatFlags = StringFormatFlags.NoWrap; Font fontParam = new Font(Font.FontFamily, 9f, FontStyle.Regular); Font fontValue = new Font(Font.FontFamily, 9f, FontStyle.Regular); Brush brushParam = new SolidBrush(colorParamText); Brush brushValue = new SolidBrush(colorValueText); Pen penDash = new Pen(colorDash); // Find Maximum width of the strings float maxParamWidth = 0; float maxValueWidth = 0; for (int i = 1; i < 5; i++) { if (!strategy.Slot[slot].IndParam.ListParam[i].Enabled) { continue; } string sParam = strategy.Slot[slot].IndParam.ListParam[i].Caption; string sValue = strategy.Slot[slot].IndParam.ListParam[i].Text; SizeF sizeParam = g.MeasureString(sParam, fontParam); SizeF sizeValue = g.MeasureString(sValue, fontValue); if (maxParamWidth < sizeParam.Width) { maxParamWidth = sizeParam.Width; } if (maxValueWidth < sizeValue.Width) { maxValueWidth = sizeValue.Width; } } foreach (NumericParam numericParam in strategy.Slot[slot].IndParam.NumParam) { if (!numericParam.Enabled) { continue; } string sParam = numericParam.Caption; string sValue = numericParam.ValueToString; SizeF sizeParam = g.MeasureString(sParam, fontParam); SizeF sizeValue = g.MeasureString(sValue, fontValue); if (maxParamWidth < sizeParam.Width) { maxParamWidth = sizeParam.Width; } if (maxValueWidth < sizeValue.Width) { maxValueWidth = sizeValue.Width; } } foreach (CheckParam checkParam in strategy.Slot[slot].IndParam.CheckParam) { if (!checkParam.Enabled) { continue; } string param = checkParam.Caption; string value = checkParam.Checked ? "Yes" : "No"; SizeF sizeParam = g.MeasureString(param, fontParam); SizeF sizeValue = g.MeasureString(value, fontValue); if (maxParamWidth < sizeParam.Width) { maxParamWidth = sizeParam.Width; } if (maxValueWidth < sizeValue.Width) { maxValueWidth = sizeValue.Width; } } // Padding Param Padding Dash Padding Value Padding float dashWidth = 5; float necessaryWidth = 4 * padding + maxParamWidth + maxValueWidth + dashWidth; if (width > necessaryWidth) { // 2*Padding Param Padding Dash Padding Value 2*Padding padding = (float)Math.Max((pnl.ClientSize.Width - maxParamWidth - maxValueWidth - dashWidth) / 6, padding); } else { padding = 2; } float tabParam = 2 * padding; float tabDash = tabParam + maxParamWidth + padding; float tabValue = tabDash + dashWidth + padding; // List Params for (int i = 1; i < 5; i++) { if (!strategy.Slot[slot].IndParam.ListParam[i].Enabled) { continue; } string sParam = strategy.Slot[slot].IndParam.ListParam[i].Caption; string sValue = strategy.Slot[slot].IndParam.ListParam[i].Text; PointF pointParam = new PointF(tabParam, iVPosition); PointF pointDash1 = new PointF(tabDash, iVPosition + fontParam.Height / 2 + 2); PointF pointDash2 = new PointF(tabDash + dashWidth, iVPosition + fontParam.Height / 2 + 2); PointF pointValue = new PointF(tabValue, iVPosition); SizeF sizefValue = new SizeF(Math.Max(width - tabValue, 0), fontValue.Height + 2); RectangleF rectfValue = new RectangleF(pointValue, sizefValue); g.DrawString(sParam, fontParam, brushParam, pointParam); g.DrawLine(penDash, pointDash1, pointDash2); g.DrawString(sValue, fontValue, brushValue, rectfValue, stringFormat); iVPosition += fontValue.Height; } // Num Params foreach (NumericParam numericParam in strategy.Slot[slot].IndParam.NumParam) { if (!numericParam.Enabled) { continue; } string sParam = numericParam.Caption; string sValue = numericParam.ValueToString; PointF pointParam = new PointF(tabParam, iVPosition); PointF pointDash1 = new PointF(tabDash, iVPosition + fontParam.Height / 2 + 2); PointF pointDash2 = new PointF(tabDash + dashWidth, iVPosition + fontParam.Height / 2 + 2); PointF pointValue = new PointF(tabValue, iVPosition); SizeF sizefValue = new SizeF(Math.Max(width - tabValue, 0), fontValue.Height + 2); RectangleF rectfValue = new RectangleF(pointValue, sizefValue); g.DrawString(sParam, fontParam, brushParam, pointParam); g.DrawLine(penDash, pointDash1, pointDash2); g.DrawString(sValue, fontValue, brushValue, rectfValue, stringFormat); iVPosition += fontValue.Height; } // Check Params foreach (CheckParam checkParam in strategy.Slot[slot].IndParam.CheckParam) { if (!checkParam.Enabled) { continue; } string param = checkParam.Caption; string salue = checkParam.Checked ? "Yes" : "No"; PointF pointParam = new PointF(tabParam, iVPosition); PointF pointDash1 = new PointF(tabDash, iVPosition + fontParam.Height / 2 + 2); PointF pointDash2 = new PointF(tabDash + dashWidth, iVPosition + fontParam.Height / 2 + 2); PointF pointValue = new PointF(tabValue, iVPosition); SizeF sizefValue = new SizeF(Math.Max(width - tabValue, 0), fontValue.Height + 2); RectangleF rectfValue = new RectangleF(pointValue, sizefValue); g.DrawString(param, fontParam, brushParam, pointParam); g.DrawLine(penDash, pointDash1, pointDash2); g.DrawString(salue, fontValue, brushValue, rectfValue, stringFormat); iVPosition += fontValue.Height; } return; }
/// <summary> /// Sets the chart parameters /// </summary> public void InitChart() { // Chart Title _strChartTitle = Language.T("Trade Distribution Chart"); _font = new Font(Font.FontFamily, 9); _captionHeight = Math.Max(_font.Height, 18); _rectfCaption = new RectangleF(0, 0, ClientSize.Width, _captionHeight); _rectSubHeader = new RectangleF(0, _captionHeight, ClientSize.Width, _captionHeight); _sfCaption = 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); if (_isNotPaint) { return; } _yTop = (int)(2 * _captionHeight + Space + 1); _yBottom = ClientSize.Height - 2 * Space - 1 - Border; _xAxisY = _yBottom - 3 - _font.Height; Graphics g = CreateGraphics(); _labelWidthY = (int) Math.Max(g.MeasureString(_yAxisMin.ToString(CultureInfo.InvariantCulture), Font).Width, g.MeasureString(_yAxisMax.ToString(CultureInfo.InvariantCulture), Font).Width); _labelWidthX = (int) Math.Max(g.MeasureString(_xAxisMin.ToString(CultureInfo.InvariantCulture), Font).Width, g.MeasureString(_xAxisMax.ToString(CultureInfo.InvariantCulture), Font).Width); g.Dispose(); _labelWidthY = Math.Max(_labelWidthY, 30); _labelWidthX += 3; _xLeft = Border + Space; _xRight = ClientSize.Width - Border - Space - _labelWidthY; _xScale = (_xRight - 2 * Space - Border) / (float)_chartBars; _countLabelsX = Math.Min((_xRight - _xLeft) / _labelWidthX, 20); _deltaX = (float)Math.Max(Math.Round((_xAxisMax - _xAxisMin) / (float)_countLabelsX), 10); _stepX = (int)Math.Ceiling(_deltaX / 10) * 10; _countLabelsX = (int)Math.Ceiling((_xAxisMax - _xAxisMin) / (float)_stepX); _xAxisMax = _xAxisMin + _countLabelsX * _stepX; // difference from Y Axis for Small_Balance_Chart: // prefer minimums because histogram counts are usually small, less than 10 _countLabelsY = Math.Min((_xAxisY - _yTop) / 20, 20); _deltaY = (float)Math.Round((_yAxisMax - _yAxisMin) / (float)_countLabelsY); // protect against deltaY infinity and stepY = Number.min _stepY = (float.IsInfinity(_deltaY)) ? 20 : (int)_deltaY; // protect against dividing by zero in case of no counts _stepY = (_stepY == 0) ? 1 : _stepY; _countLabelsY = (int)Math.Ceiling((_yAxisMax - _yAxisMin) / (float)_stepY); // protect against dividing by zero in case of no counts _countLabelsY = (_countLabelsY == 0) ? 5 : _countLabelsY; // protect against dividing by zero in case of no counts _yAxisMax = (_yAxisMax == 0) ? 5 : _yAxisMax; _yScale = (_xAxisY - _yTop) / (_countLabelsY * (float)_stepY); // Context button colors. ButtonsColorBack = LayoutColors.ColorCaptionBack; ButtonColorFore = LayoutColors.ColorCaptionText; ContextMenuColorBack = LayoutColors.ColorControlBack; ContextMenuColorFore = LayoutColors.ColorControlText; }
/// <summary> /// Sets the chart params /// </summary> public void InitChart() { if (!Data.IsData || !Data.IsResult || Data.Bars <= Data.FirstBar) { return; } firstBar = Data.FirstBar; bars = Data.Bars; chartBars = Data.Bars - firstBar; int iMaxBalance = Configs.AccountInMoney ? (int)Backtester.MaxMoneyBalance : Backtester.MaxBalance; int iMinBalance = Configs.AccountInMoney ? (int)Backtester.MinMoneyBalance : Backtester.MinBalance; int iMaxEquity = Configs.AccountInMoney ? (int)Backtester.MaxMoneyEquity : Backtester.MaxEquity; int iMinEquity = Configs.AccountInMoney ? (int)Backtester.MinMoneyEquity : Backtester.MinEquity; if (Configs.AdditionalStatistics) { int iMaxLongBalance = Configs.AccountInMoney ? (int)Backtester.MaxLongMoneyBalance : Backtester.MaxLongBalance; int iMinLongBalance = Configs.AccountInMoney ? (int)Backtester.MinLongMoneyBalance : Backtester.MinLongBalance; int iMaxShortBalance = Configs.AccountInMoney ? (int)Backtester.MaxShortMoneyBalance : Backtester.MaxShortBalance; int iMinShortBalance = Configs.AccountInMoney ? (int)Backtester.MinShortMoneyBalance : Backtester.MinShortBalance; int iMaxLSBalance = Math.Max(iMaxLongBalance, iMaxShortBalance); int iMinLSBalance = Math.Min(iMinLongBalance, iMinShortBalance); maximum = Math.Max(Math.Max(iMaxBalance, iMaxEquity), iMaxLSBalance) + 1; minimum = Math.Min(Math.Min(iMinBalance, iMinEquity), iMinLSBalance) - 1; } else { maximum = Math.Max(iMaxBalance, iMaxEquity) + 1; minimum = Math.Min(iMinBalance, iMinEquity) - 1; } YTop = border + space; YBottom = ClientSize.Height - border - space; XLeft = border; XRight = ClientSize.Width - border - space; XScale = (XRight - XLeft) / (float)chartBars; YScale = (YBottom - YTop) / (float)(maximum - minimum); penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); apntBalance = new PointF[chartBars]; apntEquity = new PointF[chartBars]; if (Configs.AdditionalStatistics) { apntLongBalance = new PointF[chartBars]; apntShortBalance = new PointF[chartBars]; } int index = 0; for (int iBar = firstBar; iBar < bars; iBar++) { apntBalance[index].X = XLeft + index * XScale; apntEquity[index].X = XLeft + index * XScale; if (Configs.AccountInMoney) { apntBalance[index].Y = (float)(YBottom - (Backtester.MoneyBalance(iBar) - minimum) * YScale); apntEquity[index].Y = (float)(YBottom - (Backtester.MoneyEquity(iBar) - minimum) * YScale); } else { apntBalance[index].Y = YBottom - (Backtester.Balance(iBar) - minimum) * YScale; apntEquity[index].Y = YBottom - (Backtester.Equity(iBar) - minimum) * YScale; } if (Configs.AdditionalStatistics) { apntLongBalance[index].X = XLeft + index * XScale; apntShortBalance[index].X = XLeft + index * XScale; if (Configs.AccountInMoney) { apntLongBalance[index].Y = (float)(YBottom - (Backtester.LongMoneyBalance(iBar) - minimum) * YScale); apntShortBalance[index].Y = (float)(YBottom - (Backtester.ShortMoneyBalance(iBar) - minimum) * YScale); } else { apntLongBalance[index].Y = YBottom - (Backtester.LongBalance(iBar) - minimum) * YScale; apntShortBalance[index].Y = YBottom - (Backtester.ShortBalance(iBar) - minimum) * YScale; } } index++; } }
/// <summary> /// Paints the journal /// </summary> protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; int hScrll = -HScrollBar.Value; var size = new Size(_visibalWidth, _rowHeight); var sf = new StringFormat { Alignment = StringAlignment.Center }; // Caption background var rectfCaption = new RectangleF(0, 0, ClientSize.Width, 2 * _rowHeight); Data.GradientPaint(g, rectfCaption, LayoutColors.ColorCaptionBack, LayoutColors.DepthCaption); var colorBack = LayoutColors.ColorControlBack; var brushCaptionText = new SolidBrush(LayoutColors.ColorCaptionText); var brushEvenRowBack = new SolidBrush(LayoutColors.ColorEvenRowBack); var brushRowText = new SolidBrush(LayoutColors.ColorControlText); var penLines = new Pen(LayoutColors.ColorJournalLines); var penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), Border); var font = new Font(Font.FontFamily, 9); // Print the journal caption string caption = Language.T("Positions During the Bar") + (Configs.AccountInMoney ? " [" + Configs.AccountCurrency + "]" : " [" + Language.T("pips") + "]"); g.DrawString(caption, font, brushCaptionText, new RectangleF(Point.Empty, size), sf); g.SetClip(new RectangleF(Border, _rowHeight, ClientSize.Width - 2 * Border, _rowHeight)); if (Configs.AccountInMoney) { for (int i = 0; i < _columns; i++) { g.DrawString(_titlesMoney[i], font, brushCaptionText, hScrll + (_xScaled[i] + _xScaled[i + 1]) / 2, _rowHeight, sf); } } else { for (int i = 0; i < _columns; i++) { g.DrawString(_titlesPips[i], font, brushCaptionText, hScrll + (_xScaled[i] + _xScaled[i + 1]) / 2, _rowHeight, sf); } } g.ResetClip(); // Paints the journal's data field var rectField = new RectangleF(Border, 2 * _rowHeight, ClientSize.Width - 2 * Border, ClientSize.Height - 2 * _rowHeight - Border); g.FillRectangle(new SolidBrush(colorBack), rectField); size = new Size(ClientSize.Width - VScrollBar.Width - 2 * Border, _rowHeight); // Prints the journal data for (int pos = _firstPos; pos < _firstPos + _shownPos; pos++) { int row = pos - _firstPos; int y = (row + 2) * _rowHeight; var point = new Point(Border, y); // Even row if (Math.Abs(row % 2f - 0) > 0.0001) { g.FillRectangle(brushEvenRowBack, new Rectangle(point, size)); } // Draw the position icon int iImgY = y + (int)Math.Floor((_rowHeight - 16) / 2.0); g.DrawImage(_positionIcons[pos - _firstPos], hScrll + 2, iImgY, 16, 16); // Prints the data g.DrawString(_journalData[row, 0], font, brushRowText, hScrll + (16 + _xScaled[1]) / 2, (row + 2) * _rowHeight, sf); for (int i = 1; i < _columns; i++) { g.DrawString(_journalData[row, i], font, brushRowText, hScrll + (_xScaled[i] + _xScaled[i + 1]) / 2, (row + 2) * _rowHeight, sf); } } for (int i = 1; i < _columns; i++) { g.DrawLine(penLines, _xScaled[i] + hScrll, 2 * _rowHeight, _xScaled[i] + hScrll, ClientSize.Height); } // Border g.DrawLine(penBorder, 1, 2 * _rowHeight, 1, ClientSize.Height); g.DrawLine(penBorder, ClientSize.Width - Border + 1, 2 * _rowHeight, ClientSize.Width - Border + 1, ClientSize.Height); g.DrawLine(penBorder, 0, ClientSize.Height - Border + 1, ClientSize.Width, ClientSize.Height - Border + 1); }
/// <summary> /// Panel Slot Paint /// </summary> private void PnlSlotPaint(object sender, PaintEventArgs e) { var pnl = (ContextPanel)sender; Graphics g = e.Graphics; var slot = (int)pnl.Tag; int width = pnl.ClientSize.Width; SlotTypes slotType = _strategy.GetSlotType(slot); Color colorBackground = LayoutColors.ColorSlotBackground; Color colorCaptionText = LayoutColors.ColorSlotCaptionText; Color colorCaptionBackOpen = LayoutColors.ColorSlotCaptionBackOpen; Color colorCaptionBackOpenFilter = LayoutColors.ColorSlotCaptionBackOpenFilter; Color colorCaptionBackClose = LayoutColors.ColorSlotCaptionBackClose; Color colorCaptionBackCloseFilter = LayoutColors.ColorSlotCaptionBackCloseFilter; Color colorIndicatorNameText = LayoutColors.ColorSlotIndicatorText; Color colorLogicText = LayoutColors.ColorSlotLogicText; Color colorParamText = LayoutColors.ColorSlotParamText; Color colorValueText = LayoutColors.ColorSlotValueText; Color colorDash = LayoutColors.ColorSlotDash; // Caption string stringCaptionText = string.Empty; Color colorCaptionBack = LayoutColors.ColorSignalRed; switch (slotType) { case SlotTypes.Open: stringCaptionText = Language.T("Opening Point of the Position"); colorCaptionBack = colorCaptionBackOpen; break; case SlotTypes.OpenFilter: stringCaptionText = Language.T("Opening Logic Condition"); colorCaptionBack = colorCaptionBackOpenFilter; break; case SlotTypes.Close: stringCaptionText = Language.T("Closing Point of the Position"); colorCaptionBack = colorCaptionBackClose; break; case SlotTypes.CloseFilter: stringCaptionText = Language.T("Closing Logic Condition"); colorCaptionBack = colorCaptionBackCloseFilter; break; } var penBorder = new Pen(Data.GetGradientColor(colorCaptionBack, -LayoutColors.DepthCaption), Border); var fontCaptionText = new Font(Font.FontFamily, 9); float captionHeight = Math.Max(fontCaptionText.Height, 18); float captionWidth = width; Brush brushCaptionText = new SolidBrush(colorCaptionText); var stringFormatCaption = new StringFormat { LineAlignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter, FormatFlags = StringFormatFlags.NoWrap, Alignment = StringAlignment.Center }; var rectfCaption = new RectangleF(0, 0, captionWidth, captionHeight); Data.GradientPaint(g, rectfCaption, colorCaptionBack, LayoutColors.DepthCaption); if (ShowRemoveSlotButtons && slot != _strategy.OpenSlot && slot != _strategy.CloseSlot) { int buttonDimentions = (int)captionHeight - 2; int buttonX = width - buttonDimentions - 1; float captionTextWidth = g.MeasureString(stringCaptionText, fontCaptionText).Width; float captionTextX = Math.Max((captionWidth - captionTextWidth) / 2f, 0); var pfCaptionText = new PointF(captionTextX, 0); var sfCaptionText = new SizeF(buttonX - captionTextX, captionHeight); rectfCaption = new RectangleF(pfCaptionText, sfCaptionText); stringFormatCaption.Alignment = StringAlignment.Near; } g.DrawString(stringCaptionText, fontCaptionText, brushCaptionText, rectfCaption, stringFormatCaption); // Border g.DrawLine(penBorder, 1, captionHeight, 1, pnl.Height); g.DrawLine(penBorder, pnl.Width - Border + 1, captionHeight, pnl.Width - Border + 1, pnl.Height); g.DrawLine(penBorder, 0, pnl.Height - Border + 1, pnl.Width, pnl.Height - Border + 1); // Paints the panel var rectfPanel = new RectangleF(Border, captionHeight, pnl.Width - 2 * Border, pnl.Height - captionHeight - Border); Data.GradientPaint(g, rectfPanel, colorBackground, LayoutColors.DepthControl); int vPosition = (int)captionHeight + 3; // Padlock image if (ShowPadlockImg) { if (_strategy.Slot[slot].SlotStatus == StrategySlotStatus.Locked) { g.DrawImage(Resources.padlock_img, 1, 1, 16, 16); } else if (_strategy.Slot[slot].SlotStatus == StrategySlotStatus.Open) { g.DrawImage(Resources.open_padlock, 1, 1, 16, 16); } else if (_strategy.Slot[slot].SlotStatus == StrategySlotStatus.Linked) { g.DrawImage(Resources.linked, 1, 1, 16, 16); } } // Indicator name var stringFormatIndicatorName = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center, FormatFlags = StringFormatFlags.NoWrap }; var fontIndicator = new Font(Font.FontFamily, 11f, FontStyle.Regular); Brush brushIndName = new SolidBrush(colorIndicatorNameText); float indNameHeight = fontIndicator.Height; float fGroupWidth = 0; if (Configs.UseLogicalGroups && (slotType == SlotTypes.OpenFilter || slotType == SlotTypes.CloseFilter)) { string sLogicalGroup = "[" + _strategy.Slot[slot].LogicalGroup + "]"; fGroupWidth = g.MeasureString(sLogicalGroup, fontIndicator).Width; var rectGroup = new RectangleF(0, vPosition, fGroupWidth, indNameHeight); g.DrawString(sLogicalGroup, fontIndicator, brushIndName, rectGroup, stringFormatIndicatorName); } stringFormatIndicatorName.Trimming = StringTrimming.EllipsisCharacter; string indicatorName = _strategy.Slot[slot].IndicatorName; float nameWidth = g.MeasureString(indicatorName, fontIndicator).Width; RectangleF rectIndName = width >= 2 * fGroupWidth + nameWidth ? new RectangleF(0, vPosition, width, indNameHeight) : new RectangleF(fGroupWidth, vPosition, width - fGroupWidth, indNameHeight); g.DrawString(indicatorName, fontIndicator, brushIndName, rectIndName, stringFormatIndicatorName); vPosition += (int)indNameHeight; if (slotType == SlotTypes.OpenFilter || slotType == SlotTypes.CloseFilter) { pnl.CloseButton.ColorBack = colorCaptionBack; pnl.CloseButton.ColorFore = colorCaptionText; pnl.CloseButton.Visible = ShowRemoveSlotButtons; } if (SlotMinMidMax == SlotSizeMinMidMax.min) { return; } // Logic var stringFormatLogic = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter, FormatFlags = StringFormatFlags.NoClip }; float padding = Space; if (_strategy.Slot[slot].IndParam.ListParam[0].Enabled) { string value = _strategy.Slot[slot].IndParam.ListParam[0].Text; var fontLogic = new Font(Font.FontFamily, 10.5f, FontStyle.Regular); SizeF sizeValue = g.MeasureString(value, fontLogic, (int)(width - 2 * padding), stringFormatLogic); var rectValue = new RectangleF(padding, vPosition, width - 2 * padding, sizeValue.Height); Brush brushLogic = new SolidBrush(colorLogicText); g.DrawString(value, fontLogic, brushLogic, rectValue, stringFormatLogic); vPosition += (int)sizeValue.Height; } if (SlotMinMidMax == SlotSizeMinMidMax.mid) { return; } // Parameters var stringFormat = new StringFormat { Trimming = StringTrimming.EllipsisCharacter, FormatFlags = StringFormatFlags.NoWrap }; var fontParam = new Font(Font.FontFamily, 9f, FontStyle.Regular); var fontValue = new Font(Font.FontFamily, 9f, FontStyle.Regular); Brush brushParam = new SolidBrush(colorParamText); Brush brushValue = new SolidBrush(colorValueText); var penDash = new Pen(colorDash); // Find Maximum width of the strings float maxParamWidth = 0; float maxValueWidth = 0; for (int i = 1; i < 5; i++) { if (!_strategy.Slot[slot].IndParam.ListParam[i].Enabled) { continue; } string caption = _strategy.Slot[slot].IndParam.ListParam[i].Caption; string value = _strategy.Slot[slot].IndParam.ListParam[i].Text; SizeF sizeParam = g.MeasureString(caption, fontParam); SizeF sizeValue = g.MeasureString(value, fontValue); if (maxParamWidth < sizeParam.Width) { maxParamWidth = sizeParam.Width; } if (maxValueWidth < sizeValue.Width) { maxValueWidth = sizeValue.Width; } } foreach (NumericParam numericParam in _strategy.Slot[slot].IndParam.NumParam) { if (!numericParam.Enabled) { continue; } string caption = numericParam.Caption; string value = numericParam.ValueToString; SizeF sizeParam = g.MeasureString(caption, fontParam); SizeF sizeValue = g.MeasureString(value, fontValue); if (maxParamWidth < sizeParam.Width) { maxParamWidth = sizeParam.Width; } if (maxValueWidth < sizeValue.Width) { maxValueWidth = sizeValue.Width; } } foreach (CheckParam checkParam in _strategy.Slot[slot].IndParam.CheckParam) { if (!checkParam.Enabled) { continue; } string param = checkParam.Caption; string value = checkParam.Checked ? "Yes" : "No"; SizeF sizeParam = g.MeasureString(param, fontParam); SizeF sizeValue = g.MeasureString(value, fontValue); if (maxParamWidth < sizeParam.Width) { maxParamWidth = sizeParam.Width; } if (maxValueWidth < sizeValue.Width) { maxValueWidth = sizeValue.Width; } } // Padding Parameter Padding Dash Padding Value Padding const float dashWidth = 5; float necessaryWidth = 4 * padding + maxParamWidth + maxValueWidth + dashWidth; padding = width > necessaryWidth ? Math.Max((pnl.ClientSize.Width - maxParamWidth - maxValueWidth - dashWidth) / 6, padding) : 2; float tabParam = 2 * padding; float tabDash = tabParam + maxParamWidth + padding; float tabValue = tabDash + dashWidth + padding; // List Parameters for (int i = 1; i < 5; i++) { if (!_strategy.Slot[slot].IndParam.ListParam[i].Enabled) { continue; } string caption = _strategy.Slot[slot].IndParam.ListParam[i].Caption; string value = _strategy.Slot[slot].IndParam.ListParam[i].Text; var pointParam = new PointF(tabParam, vPosition); var pointDash1 = new PointF(tabDash, vPosition + fontParam.Height / 2 + 2); var pointDash2 = new PointF(tabDash + dashWidth, vPosition + fontParam.Height / 2 + 2); var pointValue = new PointF(tabValue, vPosition); var sizefValue = new SizeF(Math.Max(width - tabValue, 0), fontValue.Height + 2); var rectfValue = new RectangleF(pointValue, sizefValue); g.DrawString(caption, fontParam, brushParam, pointParam); g.DrawLine(penDash, pointDash1, pointDash2); g.DrawString(value, fontValue, brushValue, rectfValue, stringFormat); vPosition += fontValue.Height; } // Num Parameters foreach (NumericParam numericParam in _strategy.Slot[slot].IndParam.NumParam) { if (!numericParam.Enabled) { continue; } string caption = numericParam.Caption; string value = numericParam.ValueToString; var pointParam = new PointF(tabParam, vPosition); var pointDash1 = new PointF(tabDash, vPosition + fontParam.Height / 2 + 2); var pointDash2 = new PointF(tabDash + dashWidth, vPosition + fontParam.Height / 2 + 2); var pointValue = new PointF(tabValue, vPosition); var sizefValue = new SizeF(Math.Max(width - tabValue, 0), fontValue.Height + 2); var rectfValue = new RectangleF(pointValue, sizefValue); g.DrawString(caption, fontParam, brushParam, pointParam); g.DrawLine(penDash, pointDash1, pointDash2); g.DrawString(value, fontValue, brushValue, rectfValue, stringFormat); vPosition += fontValue.Height; } // Check Parameters foreach (CheckParam checkParam in _strategy.Slot[slot].IndParam.CheckParam) { if (!checkParam.Enabled) { continue; } string param = checkParam.Caption; string salue = checkParam.Checked ? "Yes" : "No"; var pointParam = new PointF(tabParam, vPosition); var pointDash1 = new PointF(tabDash, vPosition + fontParam.Height / 2 + 2); var pointDash2 = new PointF(tabDash + dashWidth, vPosition + fontParam.Height / 2 + 2); var pointValue = new PointF(tabValue, vPosition); var sizefValue = new SizeF(Math.Max(width - tabValue, 0), fontValue.Height + 2); var rectfValue = new RectangleF(pointValue, sizefValue); g.DrawString(param, fontParam, brushParam, pointParam); g.DrawLine(penDash, pointDash1, pointDash2); g.DrawString(salue, fontValue, brushValue, rectfValue, stringFormat); vPosition += fontValue.Height; } }
/// <summary> /// Paints panel pnlInfo /// </summary> private void PnlInfoPaint(object sender, PaintEventArgs e) { // ---------------------------------------------------------------------+ // | Way points description | // |--------------------------------------------------------------------+ // | Number | Description | Price | Direction | Lots | Position | Order | // |--------------------------------------------------------------------+ //xp0 xp1 xp2 xp3 xp4 xp5 xp6 xp7 Graphics g = e.Graphics; g.Clear(LayoutColors.ColorControlBack); if (!Data.IsData || !Data.IsResult) { return; } var pnl = (Panel)sender; string ff = Data.FF; // Format modifier to print the floats var size = new Size(_aiX[_columns] - _aiX[0], _infoRowHeight); var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Near }; // Caption background var pntStart = new PointF(0, 0); SizeF szfCaption = new Size(pnl.ClientSize.Width, 2 * _infoRowHeight); var rectfCaption = new RectangleF(pntStart, szfCaption); Data.GradientPaint(g, rectfCaption, LayoutColors.ColorCaptionBack, LayoutColors.DepthCaption); // Caption Text var stringFormat = new StringFormat { LineAlignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter, FormatFlags = StringFormatFlags.NoWrap, Alignment = StringAlignment.Near }; string stringCaptionText = Language.T("Way Points Description"); float captionWidth = Math.Min(_pnlInfo.ClientSize.Width, _aiX[_columns] - _aiX[0]); float fCaptionTextWidth = g.MeasureString(stringCaptionText, _fontInfo).Width; float fCaptionTextX = Math.Max((captionWidth - fCaptionTextWidth) / 2f, 0); var pfCaptionText = new PointF(fCaptionTextX, 0); var sfCaptionText = new SizeF(captionWidth - fCaptionTextX, _infoRowHeight); rectfCaption = new RectangleF(pfCaptionText, sfCaptionText); // First caption raw g.DrawString(stringCaptionText, _fontInfo, _brushCaptionText, rectfCaption, stringFormat); // Second caption raw for (int i = 0; i < _columns; i++) { g.DrawString(_asTitles[i], _fontInfo, _brushCaptionText, (_aiX[i] + _aiX[i + 1]) / 2f, _infoRowHeight, sf); } Brush brush = new SolidBrush(LayoutColors.ColorControlText); for (int pnt = 0; pnt < Backtester.WayPoints(_barCurrent); pnt++) { int y = (pnt + 2) * _infoRowHeight; var point = new Point(_aiX[0], y); // Even row if (Math.Abs(pnt % 2f - 0) > 0.00001) { g.FillRectangle(_brushEvenRow, new Rectangle(point, size)); } int positionNumber = Backtester.WayPoint(_barCurrent, pnt).PosNumb; WayPointType wpType = Backtester.WayPoint(_barCurrent, pnt).WPType; PosDirection posDirection = Backtester.PosFromNumb(positionNumber).PosDir; double posLots = Backtester.PosFromNumb(positionNumber).PosLots; int ordNumber = Backtester.WayPoint(_barCurrent, pnt).OrdNumb; g.DrawString((pnt + 1).ToString(CultureInfo.InvariantCulture), _fontInfo, brush, (_aiX[0] + _aiX[1]) / 2f, y, sf); g.DrawString(Language.T(WayPoint.WPTypeToString(wpType)), _fontInfo, brush, _aiX[1] + 2, y); g.DrawString(Backtester.WayPoint(_barCurrent, pnt).Price.ToString(ff), _fontInfo, brush, (_aiX[3] + _aiX[2]) / 2f, y, sf); if (positionNumber > -1) { g.DrawString(Language.T(posDirection.ToString()), _fontInfo, brush, (_aiX[4] + _aiX[3]) / 2f, y, sf); g.DrawString(posLots.ToString(CultureInfo.InvariantCulture), _fontInfo, brush, (_aiX[5] + _aiX[4]) / 2f, y, sf); g.DrawString((positionNumber + 1).ToString(CultureInfo.InvariantCulture), _fontInfo, brush, (_aiX[6] + _aiX[5]) / 2f, y, sf); } if (ordNumber > -1) { g.DrawString((ordNumber + 1).ToString(CultureInfo.InvariantCulture), _fontInfo, brush, (_aiX[7] + _aiX[6]) / 2f, y, sf); } } // Vertical lines var penLine = new Pen(LayoutColors.ColorJournalLines); for (int i = 1; i < _columns; i++) { g.DrawLine(penLine, _aiX[i], 2 * _infoRowHeight, _aiX[i], ClientSize.Height - Border); } // Border var penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), Border); g.DrawLine(penBorder, 1, 2 * _infoRowHeight, 1, pnl.ClientSize.Height); g.DrawLine(penBorder, pnl.ClientSize.Width - Border + 1, 2 * _infoRowHeight, pnl.ClientSize.Width - Border + 1, pnl.ClientSize.Height); g.DrawLine(penBorder, 0, pnl.ClientSize.Height - Border + 1, pnl.ClientSize.Width, pnl.ClientSize.Height - Border + 1); }
/// <summary> /// Repaint the panel Info /// </summary> private void PnlInfoPaint(object sender, PaintEventArgs e) { // +------------------------------------------------------+ // | Data | // |------------------- ----------------------------------+ // | Period | Bars | From | Until | Cover | % | Label | // |------------------------------------------------------+ //xp0 xp1 xp2 xp3 xp4 xp5 xp6 xp7 Graphics g = e.Graphics; g.Clear(LayoutColors.ColorControlBack); if (!Data.IsData || !Data.IsResult) { return; } var pnl = (Panel)sender; const int border = 2; const int xp0 = border; const int xp1 = 80; const int xp2 = 140; const int xp3 = 200; const int xp4 = 260; const int xp5 = 320; const int xp6 = 370; int xp7 = pnl.ClientSize.Width - border; var size = new Size(xp7 - xp0, _infoRowHeight); var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Near }; // Caption background var pntStart = new PointF(0, 0); SizeF szfCaption = new Size(pnl.ClientSize.Width - 0, 2 * _infoRowHeight); var rectfCaption = new RectangleF(pntStart, szfCaption); Data.GradientPaint(g, rectfCaption, LayoutColors.ColorCaptionBack, LayoutColors.DepthCaption); // Caption Text var stringFormatCaption = new StringFormat { LineAlignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter, FormatFlags = StringFormatFlags.NoWrap, Alignment = StringAlignment.Near }; string stringCaptionText = Language.T("Intrabar Data"); float captionWidth = Math.Min(InfoPanel.ClientSize.Width, xp7 - xp0); float captionTextWidth = g.MeasureString(stringCaptionText, _fontInfo).Width; float captionTextX = Math.Max((captionWidth - captionTextWidth) / 2f, 0); var pfCaptionText = new PointF(captionTextX, 0); var sfCaptionText = new SizeF(captionWidth - captionTextX, _infoRowHeight); rectfCaption = new RectangleF(pfCaptionText, sfCaptionText); Brush brush = new SolidBrush(LayoutColors.ColorCaptionText); // First caption row g.DrawString(stringCaptionText, _fontInfo, brush, rectfCaption, stringFormatCaption); // Second title row g.DrawString(Language.T("Period"), _fontInfo, brush, (xp1 + xp0) / 2f, _infoRowHeight, sf); g.DrawString(Language.T("Bars"), _fontInfo, brush, (xp2 + xp1) / 2f, _infoRowHeight, sf); g.DrawString(Language.T("From"), _fontInfo, brush, (xp3 + xp2) / 2f, _infoRowHeight, sf); g.DrawString(Language.T("Until"), _fontInfo, brush, (xp4 + xp3) / 2f, _infoRowHeight, sf); g.DrawString(Language.T("Coverage"), _fontInfo, brush, (xp5 + xp4) / 2f, _infoRowHeight, sf); g.DrawString("%", _fontInfo, brush, (xp6 + xp5) / 2f, _infoRowHeight, sf); g.DrawString(Language.T("Label"), _fontInfo, brush, (xp7 + xp6) / 2f, _infoRowHeight, sf); brush = new SolidBrush(LayoutColors.ColorControlText); int allPeriods = Enum.GetValues(typeof(DataPeriods)).Length; for (int period = 0; period <= allPeriods; period++) { int y = (period + 2) * _infoRowHeight; var point = new Point(xp0, y); if (Math.Abs(period % 2f - 0) > 0.0001) { g.FillRectangle(new SolidBrush(LayoutColors.ColorEvenRowBack), new Rectangle(point, size)); } } // Tick statistics if (_isTickDataFile) { g.DrawString(Language.T("Tick"), _fontInfo, brush, (xp1 + xp0) / 2, 2 * _infoRowHeight, sf); if (Data.IsTickData && Configs.UseTickData) { int firstBarWithTicks = -1; int lastBarWithTicks = -1; int tickBars = 0; for (int b = 0; b < Data.Bars; b++) { if (firstBarWithTicks == -1 && Data.TickData[b] != null) { firstBarWithTicks = b; } if (Data.TickData[b] != null) { lastBarWithTicks = b; tickBars++; } } double percentage = 100d * tickBars / Data.Bars; int y = 2 * _infoRowHeight; string ticks = (Data.Ticks > 999999) ? (Data.Ticks / 1000).ToString(CultureInfo.InvariantCulture) + "K" : Data.Ticks.ToString(CultureInfo.InvariantCulture); g.DrawString(ticks, _fontInfo, brush, (xp2 + xp1) / 2, y, sf); g.DrawString((firstBarWithTicks + 1).ToString(CultureInfo.InvariantCulture), _fontInfo, brush, (xp3 + xp2) / 2, y, sf); g.DrawString((lastBarWithTicks + 1).ToString(CultureInfo.InvariantCulture), _fontInfo, brush, (xp4 + xp3) / 2, y, sf); g.DrawString(tickBars.ToString(CultureInfo.InvariantCulture), _fontInfo, brush, (xp5 + xp4) / 2, y, sf); g.DrawString(percentage.ToString("F2"), _fontInfo, brush, (xp6 + xp5) / 2, y, sf); var rectf = new RectangleF(xp6 + 10, y + 4, xp7 - xp6 - 20, 9); Data.GradientPaint(g, rectf, Data.PeriodColor[DataPeriods.min1], 60); rectf = new RectangleF(xp6 + 10, y + 7, xp7 - xp6 - 20, 3); Data.GradientPaint(g, rectf, Data.PeriodColor[DataPeriods.day], 60); } } for (int prd = 0; prd < allPeriods; prd++) { int startY = _isTickDataFile ? 3 : 2; int y = (prd + startY) * _infoRowHeight; var period = (DataPeriods)Enum.GetValues(typeof(DataPeriods)).GetValue(prd); int intraBars = Data.IntraBars == null || !Data.IsIntrabarData ? 0 : Data.IntraBars[prd]; int fromBar = 0; int untilBar = 0; int coveredBars = 0; double percentage = 0; bool isMultyAreas = false; if (intraBars > 0) { bool isFromBarFound = false; bool isUntilBarFound = false; untilBar = Data.Bars; for (int bar = 0; bar < Data.Bars; bar++) { if (!isFromBarFound && Data.IntraBarsPeriods[bar] == period) { fromBar = bar; isFromBarFound = true; } if (isFromBarFound && !isUntilBarFound && (Data.IntraBarsPeriods[bar] != period || bar == Data.Bars - 1)) { if (bar < Data.Bars - 1) { isUntilBarFound = true; untilBar = bar; } else { untilBar = Data.Bars; } coveredBars = untilBar - fromBar; } if (isFromBarFound && isUntilBarFound && Data.IntraBarsPeriods[bar] == period) { isMultyAreas = true; coveredBars++; } } if (isFromBarFound) { percentage = 100d * coveredBars / Data.Bars; fromBar++; } else { fromBar = 0; untilBar = 0; coveredBars = 0; percentage = 0; } } else if (period == Data.Period) { intraBars = Data.Bars; fromBar = 1; untilBar = Data.Bars; coveredBars = Data.Bars; percentage = 100; } g.DrawString(Data.DataPeriodToString(period), _fontInfo, brush, (xp1 + xp0) / 2, y, sf); if (coveredBars > 0 || period == Data.Period) { g.DrawString(intraBars.ToString(CultureInfo.InvariantCulture), _fontInfo, brush, (xp2 + xp1) / 2, y, sf); g.DrawString(fromBar.ToString(CultureInfo.InvariantCulture), _fontInfo, brush, (xp3 + xp2) / 2, y, sf); g.DrawString(untilBar.ToString(CultureInfo.InvariantCulture), _fontInfo, brush, (xp4 + xp3) / 2, y, sf); g.DrawString(coveredBars.ToString(CultureInfo.InvariantCulture) + (isMultyAreas ? "*" : ""), _fontInfo, brush, (xp5 + xp4) / 2, y, sf); g.DrawString(percentage.ToString("F2"), _fontInfo, brush, (xp6 + xp5) / 2, y, sf); var rectf = new RectangleF(xp6 + 10, y + 4, xp7 - xp6 - 20, 9); Data.GradientPaint(g, rectf, Data.PeriodColor[period], 60); } } var penLine = new Pen(LayoutColors.ColorJournalLines); g.DrawLine(penLine, xp1, 2 * _infoRowHeight, xp1, pnl.ClientSize.Height); g.DrawLine(penLine, xp2, 2 * _infoRowHeight, xp2, pnl.ClientSize.Height); g.DrawLine(penLine, xp3, 2 * _infoRowHeight, xp3, pnl.ClientSize.Height); g.DrawLine(penLine, xp4, 2 * _infoRowHeight, xp4, pnl.ClientSize.Height); g.DrawLine(penLine, xp5, 2 * _infoRowHeight, xp5, pnl.ClientSize.Height); g.DrawLine(penLine, xp6, 2 * _infoRowHeight, xp6, pnl.ClientSize.Height); // Border var penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); g.DrawLine(penBorder, 1, 2 * _infoRowHeight, 1, pnl.ClientSize.Height); g.DrawLine(penBorder, pnl.ClientSize.Width - border + 1, 2 * _infoRowHeight, pnl.ClientSize.Width - border + 1, pnl.ClientSize.Height); g.DrawLine(penBorder, 0, pnl.ClientSize.Height - border + 1, pnl.ClientSize.Width, pnl.ClientSize.Height - border + 1); }
/// <summary> /// Prepare the parameters /// </summary> private void SetUpPaintData() { // Panel caption _captionText = Language.T("Indicator Chart"); _captionFont = new Font(Font.FontFamily, 9); _captionHeight = Math.Max(_captionFont.Height, 18); _captionWidth = ClientSize.Width; _captionBrush = new SolidBrush(LayoutColors.ColorCaptionText); _captionRectangle = new RectangleF(0, 0, _captionWidth, _captionHeight); _captionStringFormat = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter, FormatFlags = StringFormatFlags.NoWrap }; if (!Data.IsData || !Data.IsResult || Data.Bars <= StatsBuffer.FirstBar) { return; } _xLeft = Space; _xRight = ClientSize.Width - Space; _yTop = (int)_captionHeight + Space; _yBottom = ClientSize.Height - _scrollBar.Height - Space; _yPriceBottom = _yBottom; _separateIndicatorsCount = 0; _separateIndicatorsChartHeight = 0; _indicatorSlots = new int[Configs.MaxEntryFilters + Configs.MaxExitFilters + 2]; _penFore = new Pen(LayoutColors.ColorChartFore); _penVolume = new Pen(LayoutColors.ColorVolume); _penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), Border); for (int slot = StatsBuffer.Strategy.Slots - 1; slot >= 0; slot--) { if (StatsBuffer.Strategy.Slot[slot].SeparatedChart) { _indicatorSlots[_separateIndicatorsCount++] = slot; } } if (_separateIndicatorsCount > 0) { _separateIndicatorsChartHeight = (_yBottom - _yTop) / (2 + _separateIndicatorsCount); _yPriceBottom = _yBottom - _separateIndicatorsCount * _separateIndicatorsChartHeight; } _maxPrice = double.MinValue; _minPrice = double.MaxValue; _maxVolume = int.MinValue; for (int bar = _chartFirstBar; bar <= _chartLastBar; 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 = (_yPriceBottom - _yTop) / (_maxPrice - _minPrice); _scaleYVol = _maxVolume > 0 ? ((_yPriceBottom - _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 = _chartFirstBar; bar <= _chartLastBar; bar++) { _x[index] = (bar - _chartFirstBar) * _chartBarWidth + _xLeft; _yOpen[index] = (int)(_yPriceBottom - (Data.Open[bar] - _minPrice) * _scaleY); _yHigh[index] = (int)(_yPriceBottom - (Data.High[bar] - _minPrice) * _scaleY); _yLow[index] = (int)(_yPriceBottom - (Data.Low[bar] - _minPrice) * _scaleY); _yClose[index] = (int)(_yPriceBottom - (Data.Close[bar] - _minPrice) * _scaleY); _yVolume[index] = (int)(_yPriceBottom - Data.Volume[bar] * _scaleYVol); // Draw position lots if (StatsBuffer.IsPos(bar)) { var posHight = (int)(Math.Max(StatsBuffer.SummaryLots(bar) * 2, 2)); int yPos = _yPriceBottom - posHight; switch (StatsBuffer.SummaryDir(bar)) { case PosDirection.Long: _rectPosition[index] = new Rectangle(_x[index], yPos, 1, posHight); _brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeLong); break; case PosDirection.Short: _rectPosition[index] = new Rectangle(_x[index], yPos, 1, posHight); _brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeShort); break; case PosDirection.Closed: _rectPosition[index] = new Rectangle(_x[index], yPos - 2, 1, 2); _brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeClose); break; } } else { // There is no position _rectPosition[index] = Rectangle.Empty; _brushPosition[index] = new SolidBrush(LayoutColors.ColorChartBack); } index++; } // Indicators in the chart int slots = StatsBuffer.Strategy.Slots; _isSeparatedChart = new bool[slots]; _componentLenght = 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 slot = 0; slot < slots; slot++) { _isSeparatedChart[slot] = StatsBuffer.Strategy.Slot[slot].SeparatedChart; int count = StatsBuffer.Strategy.Slot[slot].Component.Length; _componentLenght[slot] = count; _chartType[slot] = new IndChartType[count]; _chartLine[slot] = new Point[count][]; _chartDot[slot] = new Rectangle[count][]; _chartLevel[slot] = new Rectangle[count][]; _chartValue[slot] = new double[count][]; _chartPen[slot] = new Pen[count][]; _chartBrush[slot] = new Brush[count]; } for (int slot = 0; slot < slots; slot++) { if (_isSeparatedChart[slot]) { continue; } for (int comp = 0; comp < _componentLenght[slot]; comp++) { _chartType[slot][comp] = StatsBuffer.Strategy.Slot[slot].Component[comp].ChartType; switch (StatsBuffer.Strategy.Slot[slot].Component[comp].ChartType) { case IndChartType.Line: case IndChartType.CloudUp: case IndChartType.CloudDown: _chartBrush[slot][comp] = new SolidBrush(StatsBuffer.Strategy.Slot[slot].Component[comp].ChartColor); _chartLine[slot][comp] = new Point[_chartLastBar - _chartFirstBar + 1]; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; int x = (bar - _chartFirstBar) * _chartBarWidth + _xLeft; var y = (int)(_yPriceBottom - (value - _minPrice) * _scaleY); if (Math.Abs(value - 0) < 0.0001) { _chartLine[slot][comp][bar - _chartFirstBar] = _chartLine[slot][comp][Math.Max(bar - _chartFirstBar - 1, 0)]; } else { _chartLine[slot][comp][bar - _chartFirstBar] = new Point(x, y); } } break; case IndChartType.Dot: _chartBrush[slot][comp] = new SolidBrush(StatsBuffer.Strategy.Slot[slot].Component[comp].ChartColor); _chartDot[slot][comp] = new Rectangle[_chartLastBar - _chartFirstBar + 1]; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; int x = (bar - _chartFirstBar) * _chartBarWidth + _xLeft; var y = (int)(_yPriceBottom - (value - _minPrice) * _scaleY); _chartDot[slot][comp][bar - _chartFirstBar] = new Rectangle(x, y, 1, 1); } break; case IndChartType.Level: _chartBrush[slot][comp] = new SolidBrush(StatsBuffer.Strategy.Slot[slot].Component[comp].ChartColor); _chartLevel[slot][comp] = new Rectangle[_chartLastBar - _chartFirstBar + 1]; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; int x = (bar - _chartFirstBar) * _chartBarWidth + _xLeft; var y = (int)(_yPriceBottom - (value - _minPrice) * _scaleY); _chartLevel[slot][comp][bar - _chartFirstBar] = new Rectangle(x, y, _chartBarWidth, 1); } break; } } } // Separate indicators _yIndTop = new int[_separateIndicatorsCount]; _yIndBottom = new int[_separateIndicatorsCount]; _maxValues = new double[_separateIndicatorsCount]; _minValues = new double[_separateIndicatorsCount]; _scales = new double[_separateIndicatorsCount]; for (int ind = 0; ind < _separateIndicatorsCount; ind++) { _yIndTop[ind] = _yBottom - (ind + 1) * _separateIndicatorsChartHeight + 1; _yIndBottom[ind] = _yBottom - ind * _separateIndicatorsChartHeight - 1; _maxValues[ind] = double.MinValue; _minValues[ind] = double.MaxValue; int slot = _indicatorSlots[ind]; for (int comp = 0; comp < _componentLenght[slot]; comp++) { if (StatsBuffer.Strategy.Slot[slot].Component[comp].ChartType != IndChartType.NoChart) { for ( int bar = Math.Max(_chartFirstBar, StatsBuffer.Strategy.Slot[slot].Component[comp].FirstBar); bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; if (value > _maxValues[ind]) { _maxValues[ind] = value; } if (value < _minValues[ind]) { _minValues[ind] = value; } } } } _maxValues[ind] = Math.Max(_maxValues[ind], StatsBuffer.Strategy.Slot[slot].MaxValue); _minValues[ind] = Math.Min(_minValues[ind], StatsBuffer.Strategy.Slot[slot].MinValue); foreach (double specialValue in StatsBuffer.Strategy.Slot[slot].SpecValue) { if (Math.Abs(specialValue - 0) < 0.0001) { _maxValues[ind] = Math.Max(_maxValues[ind], 0); _minValues[ind] = Math.Min(_minValues[ind], 0); } } _scales[ind] = (_yIndBottom[ind] - _yIndTop[ind] - 2) / (Math.Max(_maxValues[ind] - _minValues[ind], 0.0001f)); // Indicator chart for (int comp = 0; comp < StatsBuffer.Strategy.Slot[slot].Component.Length; comp++) { _chartType[slot][comp] = StatsBuffer.Strategy.Slot[slot].Component[comp].ChartType; switch (_chartType[slot][comp]) { case IndChartType.Line: _chartBrush[slot][comp] = new SolidBrush(StatsBuffer.Strategy.Slot[slot].Component[comp].ChartColor); _chartLine[slot][comp] = new Point[_chartLastBar - _chartFirstBar + 1]; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; int x = (bar - _chartFirstBar) * _chartBarWidth + _xLeft; var y = (int)(_yIndBottom[ind] - 1 - (value - _minValues[ind]) * _scales[ind]); _chartLine[slot][comp][bar - _chartFirstBar] = new Point(x, y); } break; case IndChartType.Histogram: _chartValue[slot][comp] = new double[_chartLastBar - _chartFirstBar + 1]; _chartPen[slot][comp] = new Pen[_chartLastBar - _chartFirstBar + 1]; for (int bar = _chartFirstBar; bar <= _chartLastBar; bar++) { double value = StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar]; _chartValue[slot][comp][bar - _chartFirstBar] = value; if (value > StatsBuffer.Strategy.Slot[slot].Component[comp].Value[bar - 1]) { _chartPen[slot][comp][bar - _chartFirstBar] = _penGreen; } else { _chartPen[slot][comp][bar - _chartFirstBar] = _penRed; } } break; } } } }
/// <summary> /// Sets the panel colors /// </summary> private void SetColors() { _colorCaptionBack = LayoutColors.ColorCaptionBack; _brushCaption = new SolidBrush(LayoutColors.ColorCaptionText); _penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), Border); }
/// <summary> /// Sets the chart params /// </summary> public void InitChart() { // Chart Title strChartTitle = Language.T("Balance / Equity Chart") + " [" + (Configs.AccountInMoney ? Configs.AccountCurrency + "]" : Language.T("pips") + "]"); 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); if (isNotPaint) { return; } YTop = (int)captionHeight + 2 * space + 1; YBottom = ClientSize.Height - 2 * space - 1 - border; 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 + space; XRight = ClientSize.Width - border - space - labelWidth; XScale = (XRight - 2 * space - border) / (float)chartBars; countLabels = (int)Math.Max((YBottom - YTop) / 20, 1); delta = (float)Math.Max(Math.Round((maximum - minimum) / (float)countLabels), 10); step = (int)Math.Ceiling(delta / 10) * 10; countLabels = (int)Math.Ceiling((maximum - minimum) / (float)step); maximum = minimum + countLabels * step; YScale = (YBottom - YTop) / (countLabels * (float)step); apntBalance = new PointF[chartBars]; apntEquity = new PointF[chartBars]; if (Configs.AdditionalStatistics) { apntLongBalance = new PointF[chartBars]; apntShortBalance = new PointF[chartBars]; } apntClosePrice = new PointF[chartBars]; // Close Price if (showPriceLine) { YPriceScale = (float)((YBottom - YTop) / (dataMaxPrice - dataMinPrice)); } int index = 0; for (int bar = firstBar; bar < bars; bar++) { apntBalance[index].X = XLeft + index * XScale; apntEquity[index].X = XLeft + index * XScale; if (Configs.AccountInMoney) { apntBalance[index].Y = (float)(YBottom - (backtesterMoneyBalance[bar] - minimum) * YScale); apntEquity[index].Y = (float)(YBottom - (backtesterMoneyEquity[bar] - minimum) * YScale); } else { apntBalance[index].Y = YBottom - (backtesterBalance[bar] - minimum) * YScale; apntEquity[index].Y = YBottom - (backtesterEquity[bar] - minimum) * YScale; } if (Configs.AdditionalStatistics) { apntLongBalance[index].X = XLeft + index * XScale; apntShortBalance[index].X = XLeft + index * XScale; if (Configs.AccountInMoney) { apntLongBalance[index].Y = (float)(YBottom - (backtesterLongMoneyBalance[bar] - minimum) * YScale); apntShortBalance[index].Y = (float)(YBottom - (backtesterShortMoneyBalance[bar] - minimum) * YScale); } else { apntLongBalance[index].Y = YBottom - (backtesterLongBalance[bar] - minimum) * YScale; apntShortBalance[index].Y = YBottom - (backtesterShortBalance[bar] - minimum) * YScale; } } if (showPriceLine) { apntClosePrice[index].X = XLeft + index * XScale; apntClosePrice[index].Y = YBottom - (float)(dataClose[bar] - dataMinPrice) * YPriceScale; } index++; } // Margin Call if (marginCallBar >= firstBar) { XMarginCallBar = XLeft + (marginCallBar - firstBar) * XScale; } else { XMarginCallBar = 0; } //OOS if (isOOS && barOOS > firstBar) { XOOSBar = XLeft + (barOOS - firstBar) * XScale; } else { XOOSBar = 0; } YBalance = YBottom - (balance - minimum) * YScale; isHideScanningLine = false; modellingQuolity = " MQ " + Data.ModellingQuality.ToString("N2") + "%"; }
/// <summary> /// Sets the chart parameters /// </summary> public void InitChart() { // Chart Title _chartTitle = Language.T("Balance / Equity Chart") + " [" + (Configs.AccountInMoney ? Configs.AccountCurrency + "]" : Language.T("pips") + "]"); _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); if (_isNotPaint) { return; } _yTop = (int)_captionHeight + 2 * Space + 1; _yBottom = ClientSize.Height - 2 * Space - 1 - Border; Graphics g = CreateGraphics(); float widthMinimum = g.MeasureString(_data.Minimum.ToString(CultureInfo.InvariantCulture), Font).Width; float widthMaximum = g.MeasureString(_data.Maximum.ToString(CultureInfo.InvariantCulture), Font).Width; _labelWidth = (int)Math.Max(widthMinimum, widthMaximum); _labelWidth = Math.Max(_labelWidth, 30); g.Dispose(); _xLeft = Border + Space; _xRight = ClientSize.Width - Border - Space - _labelWidth; _xScale = (_xRight - 2 * Space - Border) / (float)_chartBars; _countLabels = (int)Math.Max((_yBottom - _yTop) / 20.0, 1); _delta = (float)Math.Max(Math.Round((_data.Maximum - _data.Minimum) / (float)_countLabels), 10); _labelStep = (int)Math.Ceiling(_delta / 10) * 10; _countLabels = (int)Math.Ceiling((_data.Maximum - _data.Minimum) / (float)_labelStep); _yScale = (_yBottom - _yTop) / (_countLabels * (float)_labelStep); _balancePoints = new PointF[_chartBars]; _equityPoints = new PointF[_chartBars]; if (Configs.AdditionalStatistics) { _longBalancePoints = new PointF[_chartBars]; _shortBalancePoints = new PointF[_chartBars]; } _closePricePoints = new PointF[_chartBars]; // Close Price if (_showPriceLine) { _yPriceScale = (float)((_yBottom - _yTop) / (_data.DataMaxPrice - _data.DataMinPrice)); } for (int bar = _data.FirstBar; bar < _data.Bars; bar++) { int index = bar - _data.FirstBar; _balancePoints[index].X = _xLeft + index * _xScale; _equityPoints[index].X = _xLeft + index * _xScale; if (Configs.AccountInMoney) { _balancePoints[index].Y = (float)(_yBottom - (_data.MoneyBalance[bar] - _data.Minimum) * _yScale); _equityPoints[index].Y = (float)(_yBottom - (_data.MoneyEquity[bar] - _data.Minimum) * _yScale); } else { _balancePoints[index].Y = _yBottom - (_data.Balance[bar] - _data.Minimum) * _yScale; _equityPoints[index].Y = _yBottom - (_data.Equity[bar] - _data.Minimum) * _yScale; } if (Configs.AdditionalStatistics) { _longBalancePoints[index].X = _xLeft + index * _xScale; _shortBalancePoints[index].X = _xLeft + index * _xScale; if (Configs.AccountInMoney) { _longBalancePoints[index].Y = (float)(_yBottom - (_data.LongMoneyBalance[bar] - _data.Minimum) * _yScale); _shortBalancePoints[index].Y = (float)(_yBottom - (_data.ShortMoneyBalance[bar] - _data.Minimum) * _yScale); } else { _longBalancePoints[index].Y = _yBottom - (_data.LongBalance[bar] - _data.Minimum) * _yScale; _shortBalancePoints[index].Y = _yBottom - (_data.ShortBalance[bar] - _data.Minimum) * _yScale; } } if (_showPriceLine) { _closePricePoints[index].X = _xLeft + index * _xScale; _closePricePoints[index].Y = _yBottom - (float)(_data.ClosePrice[bar] - _data.DataMinPrice) * _yPriceScale; } } // Margin Call _xMarginCallBar = _data.MarginCallBar >= _data.FirstBar ? _xLeft + (_data.MarginCallBar - _data.FirstBar) * _xScale : 0; //OOS if (IsOOS && OOSBar > _data.FirstBar) { _xOOSBar = _xLeft + (OOSBar - _data.FirstBar) * _xScale; } else { _xOOSBar = 0; } _yBalance = _yBottom - (_data.NetBalance - _data.Minimum) * _yScale; _isHideScanningLine = false; _data.ModellingQuolity = " MQ " + Data.ModellingQuality.ToString("N2") + "%"; ButtonsColorBack = LayoutColors.ColorCaptionBack; ButtonColorFore = LayoutColors.ColorCaptionText; ContextMenuColorBack = LayoutColors.ColorControlBack; ContextMenuColorFore = LayoutColors.ColorControlText; }
/// <summary> /// Initialize the form and controls /// </summary> public Bar_Explorer(int iBarNumber) { pnlChart = new Panel(); pnlInfo = new Panel(); toolTip = new ToolTip(); bar = iBarNumber < Data.FirstBar ? Data.FirstBar : iBarNumber; this.Text = Language.T("Bar Explorer"); this.BackColor = LayoutColors.ColorFormBack; this.FormBorderStyle = FormBorderStyle.FixedDialog; this.Icon = Data.Icon; this.MaximizeBox = false; this.MinimizeBox = false; this.ShowInTaskbar = false; fontInfo = new Font(Font.FontFamily, 9); infoRowHeight = (int)Math.Max(fontInfo.Height, 18); barInfo = Language.T("Bar") + ": " + (bar + 1).ToString() + " " + Data.Time[bar].ToString(Data.DF) + " " + Data.Time[bar].ToString("HH:mm") + "; " + Language.T("Interpolation method") + ": " + Backtester.InterpolationMethodToString(); pnlChart.Parent = this; pnlChart.Paint += new PaintEventHandler(PnlChart_Paint); pnlInfo.Parent = this; pnlInfo.Paint += new PaintEventHandler(PnlInfo_Paint); btnNavigate = new Button[4]; string [] btnNavigateText = new string [4] { "< !", "<", ">", "! >" }; string[] btnNavigateTips = new string [4] { Language.T("Previous ambiguous bar."), Language.T("Previous bar."), Language.T("Next bar."), Language.T("Next ambiguous bar.") }; for (int i = 0; i < 4; i++) { btnNavigate[i] = new Button(); btnNavigate[i].Parent = this; btnNavigate[i].Text = btnNavigateText[i]; btnNavigate[i].Name = btnNavigateText[i]; btnNavigate[i].Click += new EventHandler(BtnNavigate_Click); btnNavigate[i].MouseWheel += new MouseEventHandler(Bar_Explorer_MouseWheel); btnNavigate[i].UseVisualStyleBackColor = true; toolTip.SetToolTip(btnNavigate[i], btnNavigateTips[i]); } btnNavigate[0].Enabled = Backtester.AmbiguousBars > 0; btnNavigate[3].Enabled = Backtester.AmbiguousBars > 0; nudGo = new NumericUpDown(); nudGo.Parent = this; nudGo.TextAlign = HorizontalAlignment.Center; nudGo.BeginInit(); nudGo.Minimum = Data.FirstBar + 1; nudGo.Maximum = Data.Bars; nudGo.Increment = 1; nudGo.Value = bar + 1; nudGo.EndInit(); btnGo = new Button(); btnGo.Parent = this; btnGo.Name = "Go"; btnGo.Text = Language.T("Go"); btnGo.UseVisualStyleBackColor = true; btnGo.Click += new EventHandler(BtnNavigate_Click); btnGo.MouseWheel += new MouseEventHandler(Bar_Explorer_MouseWheel); toolTip.SetToolTip(btnGo, Language.T("Go to the chosen bar.")); //Button Close btnClose = new Button(); btnClose.Parent = this; btnClose.Text = Language.T("Close"); btnClose.DialogResult = DialogResult.Cancel; btnClose.UseVisualStyleBackColor = true; // Colors brushRed = new SolidBrush(LayoutColors.ColorSignalRed); brushCaptionBack = new SolidBrush(LayoutColors.ColorCaptionBack); brushCaptionText = new SolidBrush(LayoutColors.ColorCaptionText); brushEvenRow = new SolidBrush(LayoutColors.ColorEvenRowBack); brushBack = new SolidBrush(LayoutColors.ColorControlBack); brushGridText = new SolidBrush(LayoutColors.ColorChartFore); brushBarWhite = new SolidBrush(LayoutColors.ColorBarWhite); brushBarBlack = new SolidBrush(LayoutColors.ColorBarBlack); brushTradeLong = new SolidBrush(LayoutColors.ColorTradeLong); brushTradeShort = new SolidBrush(LayoutColors.ColorTradeShort); brushTradeClose = new SolidBrush(LayoutColors.ColorTradeClose); penGrid = new Pen(LayoutColors.ColorChartGrid); penGrid.DashStyle = DashStyle.Dash; penGrid.DashPattern = new float[] { 4, 2 }; penGridSolid = new Pen(LayoutColors.ColorChartGrid); penAxes = new Pen(LayoutColors.ColorChartFore); penCross = new Pen(LayoutColors.ColorChartCross); penBarBorder = new Pen(LayoutColors.ColorBarBorder); colorBarWight1 = Data.GetGradientColor(LayoutColors.ColorBarWhite, 30); colorBarWight2 = Data.GetGradientColor(LayoutColors.ColorBarWhite, -30); colorBarBlack1 = Data.GetGradientColor(LayoutColors.ColorBarBlack, 30); colorBarBlack2 = Data.GetGradientColor(LayoutColors.ColorBarBlack, -30); colorLongTrade1 = Data.GetGradientColor(LayoutColors.ColorTradeLong, 30); colorLongTrade2 = Data.GetGradientColor(LayoutColors.ColorTradeLong, -30); colorShortTrade1 = Data.GetGradientColor(LayoutColors.ColorTradeShort, 30); colorShortTrade2 = Data.GetGradientColor(LayoutColors.ColorTradeShort, -30); colorClosedTrade1 = Data.GetGradientColor(LayoutColors.ColorTradeClose, 30); colorClosedTrade2 = Data.GetGradientColor(LayoutColors.ColorTradeClose, -30); SetJournalPoints(); return; }
/// <summary> /// Paints panel pnlInfo /// </summary> void PnlInfo_Paint(object sender, PaintEventArgs e) { // ---------------------------------------------------------------------+ // | Way points description | // |--------------------------------------------------------------------+ // | Number | Description | Price | Direction | Lots | Position | Order | // |--------------------------------------------------------------------+ //xp0 xp1 xp2 xp3 xp4 xp5 xp6 xp7 Graphics g = e.Graphics; g.Clear(LayoutColors.ColorControlBack); if (!Data.IsData || !Data.IsResult) { return; } Panel pnl = (Panel)sender; Brush brush = Brushes.White; string FF = Data.FF; // Format modifier to print the floats Size size = new Size(aiX[columns] - aiX[0], infoRowHeight); StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Near; // Caption background PointF pntStart = new PointF(0, 0); SizeF szfCaption = new Size(pnl.ClientSize.Width, 2 * infoRowHeight); RectangleF rectfCaption = new RectangleF(pntStart, szfCaption); Data.GradientPaint(g, rectfCaption, LayoutColors.ColorCaptionBack, LayoutColors.DepthCaption); // Caption Text StringFormat stringFormatCaption = new StringFormat(); stringFormatCaption.LineAlignment = StringAlignment.Center; stringFormatCaption.Trimming = StringTrimming.EllipsisCharacter; stringFormatCaption.FormatFlags = StringFormatFlags.NoWrap; stringFormatCaption.Alignment = StringAlignment.Near; string stringCaptionText = Language.T("Way Points Description"); float fCaptionWidth = (float)Math.Min(pnlInfo.ClientSize.Width, aiX[columns] - aiX[0]); float fCaptionTextWidth = g.MeasureString(stringCaptionText, fontInfo).Width; float fCaptionTextX = (float)Math.Max((fCaptionWidth - fCaptionTextWidth) / 2f, 0); PointF pfCaptionText = new PointF(fCaptionTextX, 0); SizeF sfCaptionText = new SizeF(fCaptionWidth - fCaptionTextX, infoRowHeight); rectfCaption = new RectangleF(pfCaptionText, sfCaptionText); // First caption raw g.DrawString(stringCaptionText, fontInfo, brushCaptionText, rectfCaption, stringFormatCaption); // Second caption raw for (int i = 0; i < columns; i++) { g.DrawString(asTitles[i], fontInfo, brushCaptionText, (aiX[i] + aiX[i + 1]) / 2, infoRowHeight, sf); } brush = new SolidBrush(LayoutColors.ColorControlText); for (int pnt = 0; pnt < Backtester.WayPoints(bar); pnt++) { int y = (pnt + 2) * infoRowHeight; Point point = new Point(aiX[0], y); // Even row if (pnt % 2f != 0) { g.FillRectangle(brushEvenRow, new Rectangle(point, size)); } int positionNumber = Backtester.WayPoint(bar, pnt).PosNumb; WayPointType wpType = Backtester.WayPoint(bar, pnt).WPType; PosDirection posDirection = Backtester.PosFromNumb(positionNumber).PosDir; double posLots = Backtester.PosFromNumb(positionNumber).PosLots; int ordNumber = Backtester.WayPoint(bar, pnt).OrdNumb; g.DrawString((pnt + 1).ToString(), fontInfo, brush, (aiX[0] + aiX[1]) / 2, y, sf); g.DrawString(Language.T(Way_Point.WPTypeToString(wpType)), fontInfo, brush, aiX[1] + 2, y); g.DrawString(Backtester.WayPoint(bar, pnt).Price.ToString(FF), fontInfo, brush, (aiX[3] + aiX[2]) / 2, y, sf); if (positionNumber > -1) { g.DrawString(Language.T(posDirection.ToString()), fontInfo, brush, (aiX[4] + aiX[3]) / 2, y, sf); g.DrawString(posLots.ToString(), fontInfo, brush, (aiX[5] + aiX[4]) / 2, y, sf); g.DrawString((positionNumber + 1).ToString(), fontInfo, brush, (aiX[6] + aiX[5]) / 2, y, sf); } if (ordNumber > -1) { g.DrawString((ordNumber + 1).ToString(), fontInfo, brush, (aiX[7] + aiX[6]) / 2, y, sf); } } // Vertical lines Pen penLine = new Pen(LayoutColors.ColorJournalLines); for (int i = 1; i < columns; i++) { g.DrawLine(penLine, aiX[i], 2 * infoRowHeight, aiX[i], ClientSize.Height - border); } // Border Pen penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); g.DrawLine(penBorder, 1, 2 * infoRowHeight, 1, pnl.ClientSize.Height); g.DrawLine(penBorder, pnl.ClientSize.Width - border + 1, 2 * infoRowHeight, pnl.ClientSize.Width - border + 1, pnl.ClientSize.Height); g.DrawLine(penBorder, 0, pnl.ClientSize.Height - border + 1, pnl.ClientSize.Width, pnl.ClientSize.Height - border + 1); return; }
/// <summary> /// Initialize the form and controls /// </summary> public BarExplorer(int barNumber) { _pnlChart = new Panel(); _pnlInfo = new Panel(); _toolTip = new ToolTip(); _barCurrent = barNumber < Data.FirstBar ? Data.FirstBar : barNumber; Text = Language.T("Bar Explorer"); BackColor = LayoutColors.ColorFormBack; FormBorderStyle = FormBorderStyle.FixedDialog; Icon = Data.Icon; MaximizeBox = false; MinimizeBox = false; ShowInTaskbar = false; _fontInfo = new Font(Font.FontFamily, 9); _infoRowHeight = Math.Max(_fontInfo.Height, 18); _barInfo = Language.T("Bar") + ": " + (_barCurrent + 1) + " " + Data.Time[_barCurrent].ToString(Data.DF) + " " + Data.Time[_barCurrent].ToString("HH:mm") + "; " + Language.T("Interpolation method") + ": " + Backtester.InterpolationMethodToString(); _pnlChart.Parent = this; _pnlChart.Paint += PnlChartPaint; _pnlInfo.Parent = this; _pnlInfo.Paint += PnlInfoPaint; BtnsNavigate = new Button[6]; var btnNavigateText = new[] { "< !", "<<", "<", ">", ">>", "! >" }; var btnNavigateTips = new[] { Language.T("Previous ambiguous bar."), Language.T("Previous deal."), Language.T("Previous bar."), Language.T("Next bar."), Language.T("Next deal."), Language.T("Next ambiguous bar.") }; for (int i = 0; i < 6; i++) { BtnsNavigate[i] = new Button { Parent = this, Text = btnNavigateText[i], Name = btnNavigateText[i] }; BtnsNavigate[i].Click += BtnNavigateClick; BtnsNavigate[i].MouseWheel += BarExplorerMouseWheel; BtnsNavigate[i].KeyUp += BtnNavigateKeyUp; BtnsNavigate[i].UseVisualStyleBackColor = true; _toolTip.SetToolTip(BtnsNavigate[i], btnNavigateTips[i]); } BtnsNavigate[0].Enabled = Backtester.AmbiguousBars > 0; BtnsNavigate[1].Enabled = Backtester.PositionsTotal > 0; BtnsNavigate[4].Enabled = Backtester.PositionsTotal > 0; BtnsNavigate[5].Enabled = Backtester.AmbiguousBars > 0; NUDGo = new NumericUpDown { Parent = this, TextAlign = HorizontalAlignment.Center }; NUDGo.BeginInit(); NUDGo.Minimum = Data.FirstBar + 1; NUDGo.Maximum = Data.Bars; NUDGo.Increment = 1; NUDGo.Value = _barCurrent + 1; NUDGo.KeyUp += BtnNavigateKeyUp; NUDGo.EndInit(); BtnGo = new Button { Parent = this, Name = "Go", Text = Language.T("Go"), UseVisualStyleBackColor = true }; BtnGo.Click += BtnNavigateClick; BtnGo.MouseWheel += BarExplorerMouseWheel; BtnGo.KeyUp += BtnNavigateKeyUp; _toolTip.SetToolTip(BtnGo, Language.T("Go to the chosen bar.")); //Button Close BtnClose = new Button { Parent = this, Text = Language.T("Close"), DialogResult = DialogResult.Cancel, UseVisualStyleBackColor = true }; // Colors _brushRed = new SolidBrush(LayoutColors.ColorSignalRed); _brushCaptionText = new SolidBrush(LayoutColors.ColorCaptionText); _brushEvenRow = new SolidBrush(LayoutColors.ColorEvenRowBack); _brushGridText = new SolidBrush(LayoutColors.ColorChartFore); _penGrid = new Pen(LayoutColors.ColorChartGrid) { DashStyle = DashStyle.Dash, DashPattern = new float[] { 4, 2 } }; _penAxes = new Pen(LayoutColors.ColorChartFore); _penCross = new Pen(LayoutColors.ColorChartCross); _penBarBorder = new Pen(LayoutColors.ColorBarBorder); _colorBarWight1 = Data.GetGradientColor(LayoutColors.ColorBarWhite, 30); _colorBarWight2 = Data.GetGradientColor(LayoutColors.ColorBarWhite, -30); _colorBarBlack1 = Data.GetGradientColor(LayoutColors.ColorBarBlack, 30); _colorBarBlack2 = Data.GetGradientColor(LayoutColors.ColorBarBlack, -30); _colorLongTrade1 = Data.GetGradientColor(LayoutColors.ColorTradeLong, 30); _colorLongTrade2 = Data.GetGradientColor(LayoutColors.ColorTradeLong, -30); _colorShortTrade1 = Data.GetGradientColor(LayoutColors.ColorTradeShort, 30); _colorShortTrade2 = Data.GetGradientColor(LayoutColors.ColorTradeShort, -30); _colorClosedTrade1 = Data.GetGradientColor(LayoutColors.ColorTradeClose, 30); _colorClosedTrade2 = Data.GetGradientColor(LayoutColors.ColorTradeClose, -30); SetJournalPoints(); }
/// <summary> /// Panel properties Paint /// </summary> private void PnlPropertiesPaint(object sender, PaintEventArgs e) { var pnl = (Panel)sender; Graphics g = e.Graphics; int width = pnl.ClientSize.Width; Color colorCaptionBack = LayoutColors.ColorSlotCaptionBackAveraging; Color colorCaptionText = LayoutColors.ColorSlotCaptionText; Color colorBackground = LayoutColors.ColorSlotBackground; Color colorLogicText = LayoutColors.ColorSlotLogicText; Color colorDash = LayoutColors.ColorSlotDash; // Caption string stringCaptionText = Language.T("Strategy Properties"); var fontCaptionText = new Font(Font.FontFamily, 9); float captionHeight = Math.Max(fontCaptionText.Height, 18); float captionWidth = width; Brush brushCaptionText = new SolidBrush(colorCaptionText); var stringFormatCaption = new StringFormat { LineAlignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter, FormatFlags = StringFormatFlags.NoWrap, Alignment = StringAlignment.Center }; var rectfCaption = new RectangleF(0, 0, captionWidth, captionHeight); Data.GradientPaint(g, rectfCaption, colorCaptionBack, LayoutColors.DepthCaption); g.DrawString(stringCaptionText, fontCaptionText, brushCaptionText, rectfCaption, stringFormatCaption); // Border var penBorder = new Pen(Data.GetGradientColor(colorCaptionBack, -LayoutColors.DepthCaption), Border); g.DrawLine(penBorder, 1, captionHeight, 1, pnl.Height); g.DrawLine(penBorder, pnl.Width - Border + 1, captionHeight, pnl.Width - Border + 1, pnl.Height); g.DrawLine(penBorder, 0, pnl.Height - Border + 1, pnl.Width, pnl.Height - Border + 1); // Paint the panel's background var rectfPanel = new RectangleF(Border, captionHeight, pnl.Width - 2 * Border, pnl.Height - captionHeight - Border); Data.GradientPaint(g, rectfPanel, colorBackground, LayoutColors.DepthControl); int vPosition = (int)captionHeight + 2; // Padlock image if (ShowPadlockImg) { if (_strategy.PropertiesStatus == StrategySlotStatus.Locked) { g.DrawImage(Resources.padlock_img, 1, 1, 16, 16); } else if (_strategy.PropertiesStatus == StrategySlotStatus.Open) { g.DrawImage(Resources.open_padlock, 1, 1, 16, 16); } else if (_strategy.PropertiesStatus == StrategySlotStatus.Linked) { g.DrawImage(Resources.linked, 1, 1, 16, 16); } } var stringFormat = new StringFormat { Trimming = StringTrimming.EllipsisCharacter, FormatFlags = StringFormatFlags.NoWrap }; var fontParam = new Font(Font.FontFamily, 9f, FontStyle.Regular); var fontValue = new Font(Font.FontFamily, 9f, FontStyle.Regular); Brush brushParam = new SolidBrush(colorLogicText); Brush brushValue = new SolidBrush(colorLogicText); var penDash = new Pen(colorDash); string strPermaSL = _strategy.UsePermanentSL ? (Data.Strategy.PermanentSLType == PermanentProtectionType.Absolute ? "(Abs) " : "") + _strategy.PermanentSL.ToString(CultureInfo.InvariantCulture) : Language.T("None"); string strPermaTP = _strategy.UsePermanentTP ? (Data.Strategy.PermanentTPType == PermanentProtectionType.Absolute ? "(Abs) " : "") + _strategy.PermanentTP.ToString(CultureInfo.InvariantCulture) : Language.T("None"); string strBreakEven = _strategy.UseBreakEven ? _strategy.BreakEven.ToString(CultureInfo.InvariantCulture) : Language.T("None"); if (SlotMinMidMax == SlotSizeMinMidMax.min) { string param = Language.T(_strategy.SameSignalAction.ToString()) + "; " + Language.T(_strategy.OppSignalAction.ToString()) + "; " + "SL-" + strPermaSL + "; " + "TP-" + strPermaTP + "; " + "BE-" + strBreakEven; SizeF sizeParam = g.MeasureString(param, fontParam); float maxParamWidth = sizeParam.Width; // Padding Param Padding Dash Padding Value Padding float padding = Space; float necessaryWidth = 2 * padding + maxParamWidth; padding = width > necessaryWidth?Math.Max((pnl.ClientSize.Width - maxParamWidth) / 2, padding) : 2; float tabParam = padding; var pointParam = new PointF(tabParam, vPosition); g.DrawString(param, fontParam, brushParam, pointParam); } else { // Find Maximum width of the strings var asParams = new[] { Language.T("Same direction signal"), Language.T("Opposite direction signal"), Language.T("Permanent Stop Loss"), Language.T("Permanent Take Profit"), Language.T("Break Even") }; var asValues = new[] { Language.T(_strategy.SameSignalAction.ToString()), Language.T(_strategy.OppSignalAction.ToString()), strPermaSL, strPermaTP, strBreakEven }; float maxParamWidth = 0; foreach (string param in asParams) { if (g.MeasureString(param, fontParam).Width > maxParamWidth) { maxParamWidth = g.MeasureString(param, fontParam).Width; } } float maxValueWidth = 0; foreach (string value in asValues) { if (g.MeasureString(value, fontParam).Width > maxValueWidth) { maxValueWidth = g.MeasureString(value, fontParam).Width; } } // Padding Param Padding Dash Padding Value Padding float padding = Space; const float dashWidth = 5; float necessaryWidth = 4 * padding + maxParamWidth + maxValueWidth + dashWidth; padding = width > necessaryWidth ? Math.Max((pnl.ClientSize.Width - maxParamWidth - maxValueWidth - dashWidth) / 6, padding) : 2; float tabParam = 2 * padding; float tabDash = tabParam + maxParamWidth + padding; float tabValue = tabDash + dashWidth + padding; // Same direction string parameter = Language.T("Same direction signal"); string text = Language.T(_strategy.SameSignalAction.ToString()); var pointParam = new PointF(tabParam, vPosition); var pointDash1 = new PointF(tabDash, vPosition + fontParam.Height / 2 + 2); var pointDash2 = new PointF(tabDash + dashWidth, vPosition + fontParam.Height / 2 + 2); var pointValue = new PointF(tabValue, vPosition); var sizefValue = new SizeF(Math.Max(width - tabValue, 0), fontValue.Height + 2); var rectfValue = new RectangleF(pointValue, sizefValue); g.DrawString(parameter, fontParam, brushParam, pointParam); g.DrawLine(penDash, pointDash1, pointDash2); g.DrawString(text, fontValue, brushValue, rectfValue, stringFormat); vPosition += fontValue.Height + 2; // Opposite direction parameter = Language.T("Opposite direction signal"); text = Language.T(_strategy.OppSignalAction.ToString()); pointParam = new PointF(tabParam, vPosition); pointDash1 = new PointF(tabDash, vPosition + fontParam.Height / 2 + 2); pointDash2 = new PointF(tabDash + dashWidth, vPosition + fontParam.Height / 2 + 2); pointValue = new PointF(tabValue, vPosition); sizefValue = new SizeF(Math.Max(width - tabValue, 0), fontValue.Height + 2); rectfValue = new RectangleF(pointValue, sizefValue); g.DrawString(parameter, fontParam, brushParam, pointParam); g.DrawLine(penDash, pointDash1, pointDash2); g.DrawString(text, fontValue, brushValue, rectfValue, stringFormat); vPosition += fontValue.Height + 2; // Permanent Stop Loss parameter = Language.T("Permanent Stop Loss"); text = strPermaSL; pointParam = new PointF(tabParam, vPosition); pointDash1 = new PointF(tabDash, vPosition + fontParam.Height / 2 + 2); pointDash2 = new PointF(tabDash + dashWidth, vPosition + fontParam.Height / 2 + 2); pointValue = new PointF(tabValue, vPosition); sizefValue = new SizeF(Math.Max(width - tabValue, 0), fontValue.Height + 2); rectfValue = new RectangleF(pointValue, sizefValue); g.DrawString(parameter, fontParam, brushParam, pointParam); g.DrawLine(penDash, pointDash1, pointDash2); g.DrawString(text, fontValue, brushValue, rectfValue, stringFormat); vPosition += fontValue.Height + 2; // Permanent Take Profit parameter = Language.T("Permanent Take Profit"); text = strPermaTP; pointParam = new PointF(tabParam, vPosition); pointDash1 = new PointF(tabDash, vPosition + fontParam.Height / 2 + 2); pointDash2 = new PointF(tabDash + dashWidth, vPosition + fontParam.Height / 2 + 2); pointValue = new PointF(tabValue, vPosition); sizefValue = new SizeF(Math.Max(width - tabValue, 0), fontValue.Height + 2); rectfValue = new RectangleF(pointValue, sizefValue); g.DrawString(parameter, fontParam, brushParam, pointParam); g.DrawLine(penDash, pointDash1, pointDash2); g.DrawString(text, fontValue, brushValue, rectfValue, stringFormat); vPosition += fontValue.Height; // Break Even parameter = Language.T("Break Even"); text = strBreakEven; pointParam = new PointF(tabParam, vPosition); pointDash1 = new PointF(tabDash, vPosition + fontParam.Height / 2 + 2); pointDash2 = new PointF(tabDash + dashWidth, vPosition + fontParam.Height / 2 + 2); pointValue = new PointF(tabValue, vPosition); sizefValue = new SizeF(Math.Max(width - tabValue, 0), fontValue.Height + 2); rectfValue = new RectangleF(pointValue, sizefValue); g.DrawString(parameter, fontParam, brushParam, pointParam); g.DrawLine(penDash, pointDash1, pointDash2); g.DrawString(text, fontValue, brushValue, rectfValue, stringFormat); } }
/// <summary> /// Paints panel pnlChart /// </summary> private void PnlChartPaint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clear(LayoutColors.ColorChartBack); if (!Data.IsData || !Data.IsResult) { return; } var pnl = (Panel)sender; int width = pnl.ClientSize.Width; // Caption background var pntStart = new PointF(0, 0); SizeF szfCaption = new Size(width, _infoRowHeight); var rectfCaption = new RectangleF(pntStart, szfCaption); Data.GradientPaint(g, rectfCaption, LayoutColors.ColorCaptionBack, LayoutColors.DepthCaption); // Caption Text var stringFormat = new StringFormat { LineAlignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter, FormatFlags = StringFormatFlags.NoWrap, Alignment = StringAlignment.Center }; string stringCaptionText = Language.T("Price Route Inside the Bar"); rectfCaption = new RectangleF(Border, 0, pnl.ClientSize.Width - 2 * Border, _infoRowHeight); g.DrawString(stringCaptionText, _fontInfo, _brushCaptionText, rectfCaption, stringFormat); // Paint the panel background var rectClient = new RectangleF(0, _infoRowHeight, pnl.ClientSize.Width, pnl.Height - _infoRowHeight); Data.GradientPaint(g, rectClient, LayoutColors.ColorChartBack, LayoutColors.DepthControl); // Paint bar info var rectBarInfo = new RectangleF(Border, _infoRowHeight + 1, pnl.ClientSize.Width - 2 * Border, _infoRowHeight); g.DrawString(_barInfo, _fontInfo, _brushGridText, rectBarInfo, stringFormat); // Searching the min and the max price and volume width = pnl.ClientSize.Width - 2 * Border; double maxPrice = Data.High[_barCurrent]; double minPrice = Data.Low[_barCurrent]; const int space = 8; int spcRight = _szPrice.Width + 4; const int xLeft = Border + space; int xRight = width - spcRight; int yTop = 2 * _infoRowHeight + 6; int yBottom = pnl.ClientSize.Height - 22; int barPixels = _maxWayPoints < 10 ? 28 : _maxWayPoints < 15 ? 24 : 20; const int spcLeft = 3; int x = barPixels + spcLeft; int pointLeft = x + barPixels + 30; int pointRight = xRight - 20; int points = Backtester.WayPoints(_barCurrent); const int pointRadius = 3; // Grid var iCntLabels = (int)Math.Max((yBottom - yTop) / 30d, 1); double deltaPoint = (Data.InstrProperties.Digits == 5 || Data.InstrProperties.Digits == 3) ? Data.InstrProperties.Point * 100 : Data.InstrProperties.Point * 10; double delta = Math.Max(Math.Round((maxPrice - minPrice) / iCntLabels, Data.InstrProperties.Point < 0.001 ? 3 : 1), deltaPoint); minPrice = Math.Round(minPrice, Data.InstrProperties.Point < 0.001f ? 3 : 1) - Data.InstrProperties.Point * 10; minPrice -= delta; maxPrice += delta; iCntLabels = (int)Math.Ceiling((maxPrice - minPrice) / delta); maxPrice = minPrice + iCntLabels * delta; double scaleY = (yBottom - yTop) / (iCntLabels * delta); var yOpen = (int)(yBottom - (Data.Open[_barCurrent] - minPrice) * scaleY); var yHigh = (int)(yBottom - (Data.High[_barCurrent] - minPrice) * scaleY); var yLow = (int)(yBottom - (Data.Low[_barCurrent] - minPrice) * scaleY); var yClose = (int)(yBottom - (Data.Close[_barCurrent] - minPrice) * scaleY); // Find the price distance double priceDistance = 0; for (int point = 1; point < points; point++) { priceDistance += Math.Abs(Backtester.WayPoint(_barCurrent, point).Price - Backtester.WayPoint(_barCurrent, point - 1).Price); } double dPriceForAPixel = (pointRight - pointLeft) / priceDistance; // Points X var aiPointX = new int[points]; aiPointX[0] = pointLeft; for (int point = 1; point < points - 1; point++) { var iDistance = (int) (Math.Abs(Backtester.WayPoint(_barCurrent, point).Price - Backtester.WayPoint(_barCurrent, point - 1).Price) * dPriceForAPixel); aiPointX[point] = aiPointX[point - 1] + iDistance; } aiPointX[points - 1] = pointRight; for (int point = 1; point < points - 1; point++) { if (aiPointX[point] - aiPointX[point - 1] < barPixels + 1) { aiPointX[point] = aiPointX[point - 1] + barPixels + 1; } } for (int point = points - 2; point > 0; point--) { if (aiPointX[point + 1] - aiPointX[point] < barPixels + 1) { aiPointX[point] = aiPointX[point + 1] - barPixels - 1; } } // Find coordinates of the Way Points var pntWay = new Point[points]; for (int point = 0; point < points; point++) { var pointY = (int)(yBottom - (Backtester.WayPoint(_barCurrent, point).Price - minPrice) * scaleY); pntWay[point] = new Point(aiPointX[point], pointY); } // Horizontal grid and Price labels for (double label = minPrice; label <= maxPrice + Data.InstrProperties.Point; label += delta) { var labelY = (int)(yBottom - (label - minPrice) * scaleY); g.DrawString(label.ToString(Data.FF), Font, _brushGridText, xRight, labelY - Font.Height / 2 - 1); g.DrawLine(_penGrid, Border + space, labelY, xRight, labelY); } // Vertical Grid g.DrawLine(_penGrid, x + barPixels / 2 - 1, yTop, x + barPixels / 2 - 1, yBottom + 2); for (int point = 0; point < points; point++) { var pt1 = new Point(pntWay[point].X, yTop); var pt2 = new Point(pntWay[point].X, yBottom + 2); var pt3 = new Point(pntWay[point].X - 5, yBottom + 4); g.DrawLine(_penGrid, pt1, pt2); g.DrawString((point + 1).ToString(CultureInfo.InvariantCulture), Font, _brushGridText, pt3); } // Bar Number string barNumber = (_barCurrent + 1).ToString(CultureInfo.InvariantCulture); int stringX = x + barPixels / 2 - 1 - g.MeasureString(barNumber, Font).ToSize().Width / 2; Brush barBrush = Backtester.BackTestEval(_barCurrent) == BacktestEval.Ambiguous ? _brushRed : _brushGridText; g.DrawString(barNumber, Font, barBrush, stringX, yBottom + 4); // Draw the bar g.DrawLine(_penBarBorder, x + barPixels / 2 - 1, yLow, x + barPixels / 2 - 1, yHigh); if (yClose < yOpen) // White bar { var rect = new Rectangle(x, yClose, barPixels - 2, yOpen - yClose); var lgBrush = new LinearGradientBrush(rect, _colorBarWight1, _colorBarWight2, 5f); g.FillRectangle(lgBrush, rect); g.DrawRectangle(_penBarBorder, x, yClose, barPixels - 2, yOpen - yClose); } else if (yClose > yOpen) // Black bar { var rect = new Rectangle(x, yOpen, barPixels - 2, yClose - yOpen); var lgBrush = new LinearGradientBrush(rect, _colorBarBlack1, _colorBarBlack2, 5f); g.FillRectangle(lgBrush, rect); g.DrawRectangle(_penBarBorder, x, yOpen, barPixels - 2, yClose - yOpen); } else // Cross { g.DrawLine(_penBarBorder, x, yClose, x + barPixels - 2, yClose); } // Draw cancelled orders for (int orderIndex = 0; orderIndex < Backtester.Orders(_barCurrent); orderIndex++) { int ordNumber = Backtester.OrdNumb(_barCurrent, orderIndex); Order order = Backtester.OrdFromNumb(ordNumber); if (order.OrdStatus != OrderStatus.Cancelled) { continue; } if (order.OrdPrice > Data.High[_barCurrent] || order.OrdPrice < Data.Low[_barCurrent]) { continue; } int d = barPixels / 2 - 1; int x1 = x + d; int x2 = x + barPixels - 2; var yDeal = (int)(yBottom - (order.OrdPrice - minPrice) * scaleY); var pen = new Pen(LayoutColors.ColorChartGrid, 2); if (order.OrdDir == OrderDirection.Buy) { g.DrawLine(pen, x, yDeal, x1, yDeal); g.DrawLine(pen, x1, yDeal, x2, yDeal - d); g.DrawLine(pen, x2 + 1, yDeal - d + 1, x1 + d / 2 + 1, yDeal - d + 1); g.DrawLine(pen, x2, yDeal - d, x2, yDeal - d / 2); } else if (order.OrdDir == OrderDirection.Sell) { g.DrawLine(pen, x, yDeal + 1, x1 + 1, yDeal + 1); g.DrawLine(pen, x1, yDeal, x2, yDeal + d); g.DrawLine(pen, x1 + d / 2 + 1, yDeal + d, x2, yDeal + d); g.DrawLine(pen, x2, yDeal + d, x2, yDeal + d / 2 + 1); } } // Draw the deals on the bar for (int pos = 0; pos < Backtester.Positions(_barCurrent); pos++) { if (Backtester.PosTransaction(_barCurrent, pos) == Transaction.Transfer) { continue; } var yDeal = (int)(yBottom - (Backtester.PosOrdPrice(_barCurrent, pos) - minPrice) * scaleY); if (Backtester.PosDir(_barCurrent, pos) == PosDirection.Long || Backtester.PosDir(_barCurrent, pos) == PosDirection.Short) { int d = barPixels / 2 - 1; int x1 = x + d; int x2 = x + barPixels - 2; if (Backtester.OrdFromNumb(Backtester.PosOrdNumb(_barCurrent, pos)).OrdDir == OrderDirection.Buy) { // Buy var pen = new Pen(LayoutColors.ColorTradeLong, 2); g.DrawLine(pen, x, yDeal, x1, yDeal); g.DrawLine(pen, x1, yDeal, x2, yDeal - d); g.DrawLine(pen, x2 + 1, yDeal - d + 1, x1 + d / 2 + 1, yDeal - d + 1); g.DrawLine(pen, x2, yDeal - d, x2, yDeal - d / 2); } else { // Sell var pen = new Pen(LayoutColors.ColorTradeShort, 2); g.DrawLine(pen, x, yDeal + 1, x1 + 1, yDeal + 1); g.DrawLine(pen, x1, yDeal, x2, yDeal + d); g.DrawLine(pen, x1 + d / 2 + 1, yDeal + d, x2, yDeal + d); g.DrawLine(pen, x2, yDeal + d, x2, yDeal + d / 2 + 1); } } else if (Backtester.PosDir(_barCurrent, pos) == PosDirection.Closed) { // Close position int d = barPixels / 2 - 1; int x1 = x + d; int x2 = x + barPixels - 3; var pen = new Pen(LayoutColors.ColorTradeClose, 2); g.DrawLine(pen, x, yDeal, x1, yDeal); g.DrawLine(pen, x1, yDeal + d / 2, x2, yDeal - d / 2); g.DrawLine(pen, x1, yDeal - d / 2, x2, yDeal + d / 2); } } // Draw position lots for (int point = 0; point < points; point++) { int posNumber = Backtester.WayPoint(_barCurrent, point).PosNumb; if (posNumber == -1) { continue; } Position position = Backtester.PosFromNumb(posNumber); double posLots = position.PosLots; PosDirection posDirection = position.PosDir; WayPointType wpType = Backtester.WayPoint(_barCurrent, point).WPType; var hight = (int)(Math.Max(posLots * 2, 2)); int lenght = barPixels; int posX = pntWay[point].X - (barPixels - 1) / 2; int posY = yBottom - hight; if (point < points - 1) { lenght = pntWay[point + 1].X - pntWay[point].X + 1; } if (posDirection == PosDirection.Long) { // Long var rect = new Rectangle(posX - 1, posY - 1, lenght, hight + 2); var lgBrush = new LinearGradientBrush(rect, _colorLongTrade1, _colorLongTrade2, LinearGradientMode.Vertical); rect = new Rectangle(posX - 1, posY, lenght, hight); g.FillRectangle(lgBrush, rect); } else if (posDirection == PosDirection.Short) { // Short var rect = new Rectangle(posX - 1, posY - 1, lenght, hight + 2); var lgBrush = new LinearGradientBrush(rect, _colorShortTrade1, _colorShortTrade2, LinearGradientMode.Vertical); rect = new Rectangle(posX - 1, posY, lenght, hight); g.FillRectangle(lgBrush, rect); } else if (posDirection == PosDirection.Closed && wpType == WayPointType.Exit) { // Closed var rect = new Rectangle(posX - 1, yBottom - 2, barPixels + 1, 2); var lgBrush = new LinearGradientBrush(rect, _colorClosedTrade1, _colorClosedTrade2, LinearGradientMode.Vertical); rect = new Rectangle(posX, yBottom - 2, barPixels - 1, 2); g.FillRectangle(lgBrush, rect); } } // Draw the Beziers for (int point = 1; point < points; point++) { Point ptKnot1 = pntWay[point - 1]; Point ptKnot2 = pntWay[point]; int ctrlX1 = (ptKnot1.X + ptKnot2.X) / 2; int ctrlX2 = (ptKnot1.X + ptKnot2.X) / 2; int ctrlY1 = ptKnot1.Y; int ctrlY2 = ptKnot2.Y; if (point > 1) { if (pntWay[point - 2].Y > pntWay[point - 1].Y && pntWay[point - 1].Y > pntWay[point].Y || pntWay[point - 2].Y < pntWay[point - 1].Y && pntWay[point - 1].Y < pntWay[point].Y) { ctrlY1 = (pntWay[point - 1].Y + pntWay[point].Y) / 2; } } if (point < points - 1) { if (pntWay[point - 1].Y > pntWay[point].Y && pntWay[point].Y > pntWay[point + 1].Y || pntWay[point - 1].Y < pntWay[point].Y && pntWay[point].Y < pntWay[point + 1].Y) { ctrlY2 = (pntWay[point - 1].Y + pntWay[point].Y) / 2; } } if (point == 1) { ctrlX1 = ptKnot1.X; ctrlY1 = ptKnot1.Y; } if (point == points - 1) { ctrlX2 = ptKnot2.X; ctrlY2 = ptKnot2.Y; } var ptControl1 = new Point(ctrlX1, ctrlY1); var ptControl2 = new Point(ctrlX2, ctrlY2); g.DrawBezier(_penCross, ptKnot1, ptControl1, ptControl2, ptKnot2); } // Draw the WayPoints Brush brushWeyPnt = new SolidBrush(LayoutColors.ColorChartBack); for (int point = 0; point < points; point++) { g.FillEllipse(brushWeyPnt, pntWay[point].X - pointRadius, pntWay[point].Y - pointRadius, 2 * pointRadius, 2 * pointRadius); g.DrawEllipse(_penCross, pntWay[point].X - pointRadius, pntWay[point].Y - pointRadius, 2 * pointRadius, 2 * pointRadius); } // Draw O, H, L, C labels for (int point = 0; point < points; point++) { WayPointType wpType = Backtester.WayPoint(_barCurrent, point).WPType; if (wpType != WayPointType.Open && wpType != WayPointType.High && wpType != WayPointType.Low && wpType != WayPointType.Close) { continue; } string label = "?"; switch (wpType) { case WayPointType.Open: label = "O"; break; case WayPointType.High: label = "H"; break; case WayPointType.Low: label = "L"; break; case WayPointType.Close: label = "C"; break; } int xPoint = pntWay[point].X; int yPoint = pntWay[point].Y - Font.Height - 3; var stringFormatLabel = new StringFormat { Alignment = StringAlignment.Center }; g.DrawString(label, Font, _brushGridText, xPoint, yPoint, stringFormatLabel); } // Draw the deals on the route for (int point = 0; point < points; point++) { int posNumber = Backtester.WayPoint(_barCurrent, point).PosNumb; int ordNumber = Backtester.WayPoint(_barCurrent, point).OrdNumb; if (posNumber < 0 || ordNumber < 0) { continue; } PosDirection posDirection = Backtester.PosFromNumb(posNumber).PosDir; OrderDirection ordDirection = Backtester.OrdFromNumb(ordNumber).OrdDir; WayPointType wpType = Backtester.WayPoint(_barCurrent, point).WPType; if (wpType == WayPointType.None || wpType == WayPointType.Open || wpType == WayPointType.High || wpType == WayPointType.Low || wpType == WayPointType.Close) { continue; } int yDeal = pntWay[point].Y; if (posDirection == PosDirection.Long || posDirection == PosDirection.Short || wpType == WayPointType.Cancel) { int d = barPixels / 2 - 1; x = pntWay[point].X - d; int x1 = pntWay[point].X; int x2 = x + barPixels - 2; if (ordDirection == OrderDirection.Buy) { // Buy var pen = new Pen(LayoutColors.ColorTradeLong, 2); if (wpType == WayPointType.Cancel) { pen = new Pen(LayoutColors.ColorChartGrid, 2); } g.DrawLine(pen, x, yDeal, x1, yDeal); g.DrawLine(pen, x1, yDeal, x2, yDeal - d); g.DrawLine(pen, x2 + 1, yDeal - d + 1, x1 + d / 2 + 1, yDeal - d + 1); g.DrawLine(pen, x2, yDeal - d, x2, yDeal - d / 2); } else { // Sell var pen = new Pen(LayoutColors.ColorTradeShort, 2); if (wpType == WayPointType.Cancel) { pen = new Pen(LayoutColors.ColorChartGrid, 2); } g.DrawLine(pen, x, yDeal + 1, x1 + 1, yDeal + 1); g.DrawLine(pen, x1, yDeal, x2, yDeal + d); g.DrawLine(pen, x1 + d / 2 + 1, yDeal + d, x2, yDeal + d); g.DrawLine(pen, x2, yDeal + d, x2, yDeal + d / 2 + 1); } } if (posDirection == PosDirection.Closed) { // Close position int d = barPixels / 2 - 1; x = pntWay[point].X - d; int x1 = pntWay[point].X; int x2 = x + barPixels - 3; var pen = new Pen(LayoutColors.ColorTradeClose, 2); g.DrawLine(pen, x, yDeal, x1, yDeal); g.DrawLine(pen, x1, yDeal + d / 2, x2, yDeal - d / 2); g.DrawLine(pen, x1, yDeal - d / 2, x2, yDeal + d / 2); } } // Coordinate axes g.DrawLine(_penAxes, xLeft, yTop - 4, xLeft, yBottom); // Vertical left line g.DrawLine(_penAxes, xLeft, yBottom, xRight, yBottom); // Border var penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), Border); g.DrawLine(penBorder, 1, _infoRowHeight, 1, pnl.ClientSize.Height); g.DrawLine(penBorder, pnl.ClientSize.Width - Border + 1, _infoRowHeight, pnl.ClientSize.Width - Border + 1, pnl.ClientSize.Height); g.DrawLine(penBorder, 0, pnl.ClientSize.Height - Border + 1, pnl.ClientSize.Width, pnl.ClientSize.Height - Border + 1); }
/// <summary> /// Paints the journal /// </summary> protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; int iHScrll = -HScrollBar.Value; var sf = new StringFormat { Alignment = StringAlignment.Center }; // Caption background var rectfCaption = new RectangleF(0, 0, ClientSize.Width, 2 * _rowHeight); Data.GradientPaint(g, rectfCaption, LayoutColors.ColorCaptionBack, LayoutColors.DepthCaption); var font = new Font(Font.FontFamily, 9); Color colorBack = LayoutColors.ColorControlBack; var brushCaptionText = new SolidBrush(LayoutColors.ColorCaptionText); var brushEvenRowBack = new SolidBrush(LayoutColors.ColorEvenRowBack); var brushSelectedRowBack = new SolidBrush(LayoutColors.ColorSelectedRowBack); var brushSelectedRowText = new SolidBrush(LayoutColors.ColorSelectedRowText); var brushRowText = new SolidBrush(LayoutColors.ColorControlText); var brushWarningBack = new SolidBrush(LayoutColors.ColorWarningRowBack); var brushWarningText = new SolidBrush(LayoutColors.ColorWarningRowText); var penLines = new Pen(LayoutColors.ColorJournalLines); var penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), Border); // Print the journal caption string unit = Configs.AccountInMoney ? " [" + Configs.AccountCurrency + "]" : " [" + Language.T("pips") + "]"; string accUnit = " [" + Configs.AccountCurrency + "]"; g.SetClip(new RectangleF(Border, 0, ClientSize.Width - 2 * Border, 2 * _rowHeight)); g.DrawString(Language.T("Market Data"), font, brushCaptionText, iHScrll + (_xScaled[8] + _xScaled[0]) / 2, 0, sf); g.DrawString(Language.T("Summary") + unit, font, brushCaptionText, iHScrll + (_xScaled[14] + _xScaled[8]) / 2, 0, sf); g.DrawString(Language.T("Account") + unit, font, brushCaptionText, iHScrll + (_xScaled[16] + _xScaled[14]) / 2, 0, sf); g.DrawString(Language.T("Margin") + accUnit, font, brushCaptionText, iHScrll + (_xScaled[18] + _xScaled[16]) / 2, 0, sf); g.DrawString(Language.T("Backtest"), font, brushCaptionText, iHScrll + (_xScaled[19] + _xScaled[18]) / 2, 0, sf); if (Configs.AccountInMoney) { for (int i = 0; i < _columns; i++) { g.DrawString(_titlesInMoney[i], font, brushCaptionText, iHScrll + (_xScaled[i] + _xScaled[i + 1]) / 2, _rowHeight, sf); } } else { for (int i = 0; i < _columns; i++) { g.DrawString(_titlesInPips[i], font, brushCaptionText, iHScrll + (_xScaled[i] + _xScaled[i + 1]) / 2, _rowHeight, sf); } } g.ResetClip(); var rectField = new RectangleF(Border, 2 * _rowHeight, ClientSize.Width - 2 * Border, ClientSize.Height - 2 * _rowHeight - Border); g.FillRectangle(new SolidBrush(colorBack), rectField); var size = new Size(ClientSize.Width - VScrollBar.Width - 2 * Border, _rowHeight); // Prints the journal data for (int bar = _firstBar; bar < _firstBar + _shownBars; bar++) { int y = (bar - _firstBar + 2) * _rowHeight; var point = new Point(Border, y); // Even row if (Math.Abs((bar - _firstBar) % 2f - 0) > 0.0001) { g.FillRectangle(brushEvenRowBack, new Rectangle(point, size)); } // Warning row bool isWarningRow = false; if (_journalData[bar - _firstBar, _columns - 1] == Language.T("Ambiguous")) { g.FillRectangle(brushWarningBack, new Rectangle(point, size)); isWarningRow = true; } // Selected row Brush brush; if (bar - _firstBar == _selectedRow) { g.FillRectangle(brushSelectedRowBack, new Rectangle(point, size)); brush = brushSelectedRowText; } else { brush = isWarningRow ? brushWarningText : brushRowText; } int index = bar - _firstBar; // Draw the position icon int imgY = y + (int)Math.Floor((_rowHeight - 16) / 2.0); g.DrawImage(_positionIcons[index], iHScrll + 2, imgY, 16, 16); // Prints the data g.DrawString(_journalData[index, 0], font, brush, iHScrll + (16 + _xScaled[1]) / 2, (index + 2) * _rowHeight, sf); for (int i = 1; i < _columns; i++) { g.DrawString(_journalData[index, i], font, brush, iHScrll + (_xScaled[i] + _xScaled[i + 1]) / 2, (index + 2) * _rowHeight, sf); } } // Vertical grid lines for (int i = 1; i < _columns; i++) { if (i == 8 || i == 14 || i == 16 || i == 18) { var rectfSeparator = new RectangleF(_xScaled[i] + iHScrll, (float)(_rowHeight / 2.0), 1, (float)(3 * _rowHeight / 2.0)); Data.GradientPaint(g, rectfSeparator, LayoutColors.ColorCaptionBack, -2 * LayoutColors.DepthCaption); } g.DrawLine(penLines, _xScaled[i] + iHScrll, 2 * _rowHeight, _xScaled[i] + iHScrll, ClientSize.Height); } // Borders g.DrawLine(penBorder, 1, 2 * _rowHeight, 1, ClientSize.Height); g.DrawLine(penBorder, ClientSize.Width - Border + 1, 2 * _rowHeight, ClientSize.Width - Border + 1, ClientSize.Height); g.DrawLine(penBorder, 0, ClientSize.Height - Border + 1, ClientSize.Width, ClientSize.Height - Border + 1); OnSelectedBarChange(new EventArgs()); }
/// <summary> /// Sets the panel colors /// </summary> public void SetColors() { colorCaptionBack = LayoutColors.ColorCaptionBack; brushCaption = new SolidBrush(LayoutColors.ColorCaptionText); penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); }
/// <summary> /// Sets the chart parameters /// </summary> private void InitChart(int width, int height) { Chart = new Bitmap(width, height); if (!Data.IsData || !Data.IsResult || Data.Bars <= Data.FirstBar) { return; } const int border = 1; const int space = 2; int maximum; int minimum; int firstBar = Data.FirstBar; int bars = Data.Bars; int chartBars = Data.Bars - firstBar; int maxBalance = Configs.AccountInMoney ? (int)Backtester.MaxMoneyBalance : Backtester.MaxBalance; int minBalance = Configs.AccountInMoney ? (int)Backtester.MinMoneyBalance : Backtester.MinBalance; int maxEquity = Configs.AccountInMoney ? (int)Backtester.MaxMoneyEquity : Backtester.MaxEquity; int minEquity = Configs.AccountInMoney ? (int)Backtester.MinMoneyEquity : Backtester.MinEquity; if (Configs.AdditionalStatistics) { int maxLongBalance = Configs.AccountInMoney ? (int)Backtester.MaxLongMoneyBalance : Backtester.MaxLongBalance; int minLongBalance = Configs.AccountInMoney ? (int)Backtester.MinLongMoneyBalance : Backtester.MinLongBalance; int maxShortBalance = Configs.AccountInMoney ? (int)Backtester.MaxShortMoneyBalance : Backtester.MaxShortBalance; int minShortBalance = Configs.AccountInMoney ? (int)Backtester.MinShortMoneyBalance : Backtester.MinShortBalance; int maxLSBalance = Math.Max(maxLongBalance, maxShortBalance); int minLSBalance = Math.Min(minLongBalance, minShortBalance); maximum = Math.Max(Math.Max(maxBalance, maxEquity), maxLSBalance) + 1; minimum = Math.Min(Math.Min(minBalance, minEquity), minLSBalance) - 1; } else { maximum = Math.Max(maxBalance, maxEquity) + 1; minimum = Math.Min(minBalance, minEquity) - 1; } const int yTop = border + space; int yBottom = height - border - space; const int xLeft = border; int xRight = width - border - space; float xScale = (xRight - xLeft) / (float)chartBars; float yScale = (yBottom - yTop) / (float)(maximum - minimum); var penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); var balancePoints = new PointF[chartBars]; var equityPoints = new PointF[chartBars]; var longBalancePoints = new PointF[chartBars]; var shortBalancePoints = new PointF[chartBars]; int index = 0; for (int bar = firstBar; bar < bars; bar++) { balancePoints[index].X = xLeft + index * xScale; equityPoints[index].X = xLeft + index * xScale; if (Configs.AccountInMoney) { balancePoints[index].Y = (float)(yBottom - (Backtester.MoneyBalance(bar) - minimum) * yScale); equityPoints[index].Y = (float)(yBottom - (Backtester.MoneyEquity(bar) - minimum) * yScale); } else { balancePoints[index].Y = yBottom - (Backtester.Balance(bar) - minimum) * yScale; equityPoints[index].Y = yBottom - (Backtester.Equity(bar) - minimum) * yScale; } if (Configs.AdditionalStatistics) { longBalancePoints[index].X = xLeft + index * xScale; shortBalancePoints[index].X = xLeft + index * xScale; if (Configs.AccountInMoney) { longBalancePoints[index].Y = (float)(yBottom - (Backtester.LongMoneyBalance(bar) - minimum) * yScale); shortBalancePoints[index].Y = (float)(yBottom - (Backtester.ShortMoneyBalance(bar) - minimum) * yScale); } else { longBalancePoints[index].Y = yBottom - (Backtester.LongBalance(bar) - minimum) * yScale; shortBalancePoints[index].Y = yBottom - (Backtester.ShortBalance(bar) - minimum) * yScale; } } index++; } Graphics g = Graphics.FromImage(Chart); // Paints the background by gradient var rectField = new RectangleF(1, 1, width - 2, height - 2); g.FillRectangle(new SolidBrush(LayoutColors.ColorChartBack), rectField); // Border g.DrawRectangle(penBorder, 0, 0, width - 1, height - 1); // Equity line g.DrawLines(new Pen(LayoutColors.ColorChartEquityLine), equityPoints); // Draw Long and Short balance if (Configs.AdditionalStatistics) { g.DrawLines(new Pen(Color.Red), shortBalancePoints); g.DrawLines(new Pen(Color.Green), longBalancePoints); } // Draw the balance line g.DrawLines(new Pen(LayoutColors.ColorChartBalanceLine), balancePoints); }
/// <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> /// Sets the chart params /// </summary> void InitChart(int width, int height) { chart = new Bitmap(width, height); if (!Data.IsData || !Data.IsResult || Data.Bars <= Data.FirstBar) { return; } int border = 1; int space = 2; int XLeft, XRight, YTop, YBottom; float XScale, YScale; int bars; int chartBars; int maximum; int minimum; int firstBar; Pen penBorder; PointF[] apntBalance; PointF[] apntEquity; PointF[] apntLongBalance; PointF[] apntShortBalance; firstBar = Data.FirstBar; bars = Data.Bars; chartBars = Data.Bars - firstBar; int iMaxBalance = Configs.AccountInMoney ? (int)Backtester.MaxMoneyBalance : Backtester.MaxBalance; int iMinBalance = Configs.AccountInMoney ? (int)Backtester.MinMoneyBalance : Backtester.MinBalance; int iMaxEquity = Configs.AccountInMoney ? (int)Backtester.MaxMoneyEquity : Backtester.MaxEquity; int iMinEquity = Configs.AccountInMoney ? (int)Backtester.MinMoneyEquity : Backtester.MinEquity; if (Configs.AdditionalStatistics) { int iMaxLongBalance = Configs.AccountInMoney ? (int)Backtester.MaxLongMoneyBalance : Backtester.MaxLongBalance; int iMinLongBalance = Configs.AccountInMoney ? (int)Backtester.MinLongMoneyBalance : Backtester.MinLongBalance; int iMaxShortBalance = Configs.AccountInMoney ? (int)Backtester.MaxShortMoneyBalance : Backtester.MaxShortBalance; int iMinShortBalance = Configs.AccountInMoney ? (int)Backtester.MinShortMoneyBalance : Backtester.MinShortBalance; int iMaxLSBalance = Math.Max(iMaxLongBalance, iMaxShortBalance); int iMinLSBalance = Math.Min(iMinLongBalance, iMinShortBalance); maximum = Math.Max(Math.Max(iMaxBalance, iMaxEquity), iMaxLSBalance) + 1; minimum = Math.Min(Math.Min(iMinBalance, iMinEquity), iMinLSBalance) - 1; } else { maximum = Math.Max(iMaxBalance, iMaxEquity) + 1; minimum = Math.Min(iMinBalance, iMinEquity) - 1; } YTop = border + space; YBottom = height - border - space; XLeft = border; XRight = width - border - space; XScale = (XRight - XLeft) / (float)chartBars; YScale = (YBottom - YTop) / (float)(maximum - minimum); penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); apntBalance = new PointF[chartBars]; apntEquity = new PointF[chartBars]; apntLongBalance = new PointF[chartBars]; apntShortBalance = new PointF[chartBars]; int index = 0; for (int iBar = firstBar; iBar < bars; iBar++) { apntBalance[index].X = XLeft + index * XScale; apntEquity[index].X = XLeft + index * XScale; if (Configs.AccountInMoney) { apntBalance[index].Y = (float)(YBottom - (Backtester.MoneyBalance(iBar) - minimum) * YScale); apntEquity[index].Y = (float)(YBottom - (Backtester.MoneyEquity(iBar) - minimum) * YScale); } else { apntBalance[index].Y = YBottom - (Backtester.Balance(iBar) - minimum) * YScale; apntEquity[index].Y = YBottom - (Backtester.Equity(iBar) - minimum) * YScale; } if (Configs.AdditionalStatistics) { apntLongBalance[index].X = XLeft + index * XScale; apntShortBalance[index].X = XLeft + index * XScale; if (Configs.AccountInMoney) { apntLongBalance[index].Y = (float)(YBottom - (Backtester.LongMoneyBalance(iBar) - minimum) * YScale); apntShortBalance[index].Y = (float)(YBottom - (Backtester.ShortMoneyBalance(iBar) - minimum) * YScale); } else { apntLongBalance[index].Y = YBottom - (Backtester.LongBalance(iBar) - minimum) * YScale; apntShortBalance[index].Y = YBottom - (Backtester.ShortBalance(iBar) - minimum) * YScale; } } index++; } Graphics g = Graphics.FromImage(chart); // Paints the background by gradient RectangleF rectField = new RectangleF(1, 1, width - 2, height - 2); g.FillRectangle(new SolidBrush(LayoutColors.ColorChartBack), rectField); // Border g.DrawRectangle(penBorder, 0, 0, width - 1, height - 1); // Equity line g.DrawLines(new Pen(LayoutColors.ColorChartEquityLine), apntEquity); // Draw Long and Short balance if (Configs.AdditionalStatistics) { g.DrawLines(new Pen(Color.Red), apntShortBalance); g.DrawLines(new Pen(Color.Green), apntLongBalance); } // Draw the balance line g.DrawLines(new Pen(LayoutColors.ColorChartBalanceLine), apntBalance); }
/// <summary> /// Paints panel pnlOptions /// </summary> private void PnlOptionsPaint(object sender, PaintEventArgs e) { var pnl = (Panel)sender; Graphics g = e.Graphics; const int border = 2; // Chart Title string str = Language.T("Interpolation Methods"); var font = new Font(Font.FontFamily, 9); var fCaptionHeight = (float)Math.Max(font.Height, 18); var rectfCaption = new RectangleF(0, 0, pnl.ClientSize.Width, fCaptionHeight); var stringFormatCaption = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; Data.GradientPaint(g, rectfCaption, LayoutColors.ColorCaptionBack, LayoutColors.DepthCaption); g.DrawString(str, Font, new SolidBrush(LayoutColors.ColorCaptionText), rectfCaption, stringFormatCaption); // Paint the panel background var rectClient = new RectangleF(border, fCaptionHeight, pnl.ClientSize.Width - 2 * border, pnl.Height - fCaptionHeight - border); Data.GradientPaint(g, rectClient, LayoutColors.ColorControlBack, LayoutColors.DepthControl); var penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border); g.DrawLine(penBorder, 1, fCaptionHeight, 1, pnl.ClientSize.Height); g.DrawLine(penBorder, pnl.ClientSize.Width - border + 1, fCaptionHeight, pnl.ClientSize.Width - border + 1, pnl.ClientSize.Height); g.DrawLine(penBorder, 0, pnl.ClientSize.Height - border + 1, pnl.ClientSize.Width, pnl.ClientSize.Height - border + 1); int positionX = (PnlOptions.ClientSize.Width - 10) / 3; const int positionY = 35; int num = 0; for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { if (num < _countMethods) { var pt1 = new Point(j * positionX + 10, i * 30 + positionY); var pt2 = new Point(j * positionX + 30, i * 30 + positionY); var pen = new Pen(Color.Red); switch ((InterpolationMethod)AchboxMethods[num].Tag) { case InterpolationMethod.Pessimistic: pen = new Pen(LayoutColors.ComparatorChartPessimisticLine); break; case InterpolationMethod.Shortest: pen = new Pen(LayoutColors.ComparatorChartShortestLine); break; case InterpolationMethod.Nearest: pen = new Pen(LayoutColors.ComparatorChartNearestLine); break; case InterpolationMethod.Optimistic: pen = new Pen(LayoutColors.ComparatorChartOptimisticLine); break; case InterpolationMethod.Random: var pntRnd1 = new Point(j * positionX + 10, i * 30 + positionY - 6); var pntRnd2 = new Point(j * positionX + 30, i * 30 + positionY - 6); var pntRnd3 = new Point(j * positionX + 10, i * 30 + positionY + 6); var pntRnd4 = new Point(j * positionX + 30, i * 30 + positionY + 6); var penRnd = new Pen(LayoutColors.ComparatorChartRandomBands, 2); Brush brushRnd = new SolidBrush(LayoutColors.ComparatorChartRandomArea); g.FillRectangle(brushRnd, new Rectangle(pntRnd1.X, pntRnd1.Y, pntRnd2.X - pntRnd1.X, pntRnd4.Y - pntRnd2.Y)); g.DrawLine(penRnd, pntRnd1, pntRnd2); g.DrawLine(penRnd, pntRnd3, pntRnd4); pen = new Pen(LayoutColors.ComparatorChartRandomLine); break; } pen.Width = 2; g.DrawLine(pen, pt1, pt2); } else { var pt1 = new Point(j * positionX + 10, i * 30 + positionY); var pt2 = new Point(j * positionX + 30, i * 30 + positionY); var pen = new Pen(LayoutColors.ComparatorChartBalanceLine) { Width = 3 }; g.DrawLine(pen, pt1, pt2); } num++; } } }