/// <summary>
        /// Show position
        /// </summary>
        private void ShowOrder(string input)
        {
            const string pattern    = @"^ord (?<numb>\d+)$";
            var          expression = new Regex(pattern, RegexOptions.Compiled);
            Match        match      = expression.Match(input);

            if (match.Success)
            {
                int ord = int.Parse(match.Groups["numb"].Value);
                if (ord < 1 || ord > Backtester.OrdersTotal)
                {
                    return;
                }

                Order order = Backtester.OrdFromNumb(ord - 1);
                TbxOutput.Text += "Order" + Environment.NewLine + "-----------------" +
                                  Environment.NewLine + order + Environment.NewLine;
            }
        }
        /// <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);
        }
Example #3
0
        /// <summary>
        /// Updates the journal data from the backtester
        /// </summary>
        void UpdateJournalData()
        {
            if (!Data.IsResult)
            {
                return;
            }

            Order[] aOrders = new Order[orders];
            aiOrderIcons = new Image[orders];

            int ordIndex = 0;

            for (int point = 0; point < Backtester.WayPoints(selectedBar); point++)
            {
                int          iOrdNumber = Backtester.WayPoint(selectedBar, point).OrdNumb;
                WayPointType wpType     = Backtester.WayPoint(selectedBar, point).WPType;

                if (iOrdNumber == -1)
                {
                    continue;                   // There is no order
                }
                if (iOrdNumber < Backtester.OrdNumb(selectedBar, 0))
                {
                    continue;                                                  // For a transferred position
                }
                if (wpType == WayPointType.Add || wpType == WayPointType.Cancel ||
                    wpType == WayPointType.Entry || wpType == WayPointType.Exit ||
                    wpType == WayPointType.Reduce || wpType == WayPointType.Reverse)
                {
                    aOrders[ordIndex] = Backtester.OrdFromNumb(iOrdNumber);
                    ordIndex++;
                }
            }

            for (int ord = 0; ord < orders; ord++)
            {
                int  ordNumber  = Backtester.OrdNumb(selectedBar, ord);
                bool toIncluded = true;
                for (int i = 0; i < ordIndex; i++)
                {
                    if (ordNumber == aOrders[i].OrdNumb)
                    {
                        toIncluded = false;
                        break;
                    }
                }
                if (toIncluded)
                {
                    aOrders[ordIndex] = Backtester.OrdFromNumb(ordNumber);
                    ordIndex++;
                }
            }

            asJournalData = new string[orders, columns];

            for (int ord = firstOrd; ord < firstOrd + shownOrd; ord++)
            {
                int row = ord - firstOrd;

                string ordIF     = (aOrders[ord].OrdIF > 0 ? (aOrders[ord].OrdIF + 1).ToString() : "-");
                string ordPrice2 = (aOrders[ord].OrdPrice2 > 0 ? aOrders[ord].OrdPrice2.ToString(Data.FF) : "-");

                asJournalData[row, 0] = (aOrders[ord].OrdNumb + 1).ToString();
                asJournalData[row, 1] = Language.T(aOrders[ord].OrdDir.ToString());
                asJournalData[row, 2] = Language.T(aOrders[ord].OrdType.ToString());
                if (Configs.AccountInMoney)
                {
                    string sOrdAmount = (aOrders[ord].OrdDir == OrderDirection.Sell ? "-" : "") +
                                        (aOrders[ord].OrdLots * Data.InstrProperties.LotSize).ToString();
                    asJournalData[row, 3] = sOrdAmount;
                }
                else
                {
                    asJournalData[row, 3] = aOrders[ord].OrdLots.ToString();
                }
                asJournalData[row, 4] = aOrders[ord].OrdPrice.ToString(Data.FF);
                asJournalData[row, 5] = ordPrice2;
                asJournalData[row, 6] = Language.T(aOrders[ord].OrdStatus.ToString());
                asJournalData[row, 7] = aOrders[ord].OrdNote;

                // Icons
                aiOrderIcons[row] = aOrders[ord].OrderIcon;
            }

            return;
        }
Example #4
0
        /// <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);
        }