/// <summary>
        /// Exports the positions info in currency
        /// </summary>
        public void ExportPositionsInMoney()
        {
            string stage = String.Empty;

            if (Data.IsProgramBeta)
            {
                stage = " " + Language.T("Beta");
            }
            else if (Data.IsProgramRC)
            {
                stage = " " + "RC";
            }

            sb.Append("Forex Strategy Builder v" + Data.ProgramVersion + stage + Environment.NewLine);
            sb.Append("Strategy name: " + Data.Strategy.StrategyName + Environment.NewLine);
            sb.Append("Exported on " + DateTime.Now.ToString() + Environment.NewLine);
            sb.Append(Data.Symbol + " " + Data.PeriodString + "; Values in " + Configs.AccountCurrency + Environment.NewLine);

            sb.Append("Pos Numb\t");
            sb.Append("Bar Numb\t");
            sb.Append("Bar Opening Time\t");
            sb.Append("Direction\t");
            sb.Append("Amount\t");
            sb.Append("Transaction\t");
            sb.Append("Order Price\t");
            sb.Append("Price\t");
            sb.Append("Profit Loss\t");
            sb.Append("Floating P/L\t");
            sb.Append("Balance\t");
            sb.Append("Equity\t");
            sb.Append(Environment.NewLine);

            for (int iPos = 0; iPos < Backtester.PositionsTotal; iPos++)
            {
                Position position = Backtester.PosFromNumb(iPos);
                int      bar      = Backtester.PosCoordinates[iPos].Bar;
                sb.Append((position.PosNumb + 1).ToString() + "\t");
                sb.Append((bar + 1).ToString() + "\t");
                sb.Append((Data.Time[bar]).ToString() + "\t");
                sb.Append((position.PosDir).ToString() + "\t");
                sb.Append((position.PosDir == PosDirection.Long ? "" : "-") +
                          (position.PosLots * Data.InstrProperties.LotSize).ToString() + "\t");
                sb.Append((position.Transaction).ToString() + "\t");
                sb.Append((position.FormOrdPrice).ToString(FF) + "\t");
                sb.Append((position.PosPrice).ToString(FF) + "\t");
                sb.Append((position.MoneyProfitLoss).ToString("F2") + "\t");
                sb.Append((position.MoneyFloatingPL).ToString("F2") + "\t");
                sb.Append((position.MoneyBalance).ToString("F2") + "\t");
                sb.Append((position.MoneyEquity).ToString("F2") + "\t");
                sb.Append(Environment.NewLine);
            }

            string fileName = Data.Strategy.StrategyName + "-" + Data.Symbol.ToString() + "-" + Data.Period.ToString();

            SaveData(fileName);
            return;
        }
        /// <summary>
        /// Exports the positions info
        /// </summary>
        public void ExportPositions()
        {
            string stage = String.Empty;

            if (Data.IsProgramBeta)
            {
                stage = " " + Language.T("Beta");
            }
            else if (Data.IsProgramRC)
            {
                stage = " " + "RC";
            }

            sb.Append("Forex Strategy Builder v" + Data.ProgramVersion + stage + Environment.NewLine);
            sb.Append("Strategy name: " + Data.Strategy.StrategyName + Environment.NewLine);
            sb.Append("Exported on " + DateTime.Now.ToString() + Environment.NewLine);
            sb.Append(Data.Symbol + " " + Data.PeriodString + "; Values in pips" + Environment.NewLine);

            sb.Append("Pos Numb\t");
            sb.Append("Bar Numb\t");
            sb.Append("Bar Opening Time\t");
            sb.Append("Direction\t");
            sb.Append("Lots\t");
            sb.Append("Transaction\t");
            sb.Append("Order Price\t");
            sb.Append("Average Price\t");
            sb.Append("Profit Loss\t");
            sb.Append("Floating P/L\t");
            sb.Append("Balance\t");
            sb.Append("Equity\t");
            sb.Append(Environment.NewLine);

            for (int iPos = 0; iPos < Backtester.PositionsTotal; iPos++)
            {
                Position position = Backtester.PosFromNumb(iPos);
                int      bar      = Backtester.PosCoordinates[iPos].Bar;
                sb.Append((position.PosNumb + 1).ToString() + "\t");
                sb.Append((bar + 1).ToString() + "\t");
                sb.Append((Data.Time[bar]).ToString() + "\t");
                sb.Append((position.PosDir).ToString() + "\t");
                sb.Append((position.PosLots).ToString() + "\t");
                sb.Append((position.Transaction).ToString() + "\t");
                sb.Append((position.FormOrdPrice).ToString(FF) + "\t");
                sb.Append((position.PosPrice).ToString(FF) + "\t");
                sb.Append((Math.Round(position.ProfitLoss)).ToString() + "\t");
                sb.Append((Math.Round(position.FloatingPL)).ToString() + "\t");
                sb.Append((Math.Round(position.Balance)).ToString() + "\t");
                sb.Append((Math.Round(position.Equity)).ToString() + "\t");
                sb.Append(Environment.NewLine);
            }

            string fileName = Data.Strategy.StrategyName + "-" + Data.Symbol.ToString() + "-" + Data.Period.ToString();

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

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

                Position position = Backtester.PosFromNumb(pos - 1);
                TbxOutput.Text += "Position" + Environment.NewLine + "-----------------" +
                                  Environment.NewLine + position + Environment.NewLine;
            }
        }
        /// <summary>
        /// Updates the journal data from the backtester
        /// </summary>
        void UpdateJournalData()
        {
            asJournalData   = new string[shownPos, columns];
            aiPositionIcons = new Image[shownPos];

            for (int posIndex = firstPos; posIndex < firstPos + shownPos; posIndex++)
            {
                int posNumber = posIndex;

                if (!showTransfers)
                {
                    posNumber = aiPosNumber[posIndex];
                }

                int      row      = posIndex - firstPos;
                int      bar      = Backtester.PosCoordinates[posNumber].Bar;
                Position position = Backtester.PosFromNumb(posNumber);

                string posAmount;
                if (Configs.AccountInMoney)
                {
                    posAmount = (position.PosDir == PosDirection.Short ? "-" : "") +
                                (position.PosLots * Data.InstrProperties.LotSize).ToString();
                }
                else
                {
                    posAmount = position.PosLots.ToString();
                }

                string profitLoss;
                if (Configs.AccountInMoney)
                {
                    profitLoss = position.MoneyProfitLoss.ToString("F2");
                }
                else
                {
                    profitLoss = position.ProfitLoss.ToString("F2");
                }

                string floatingPL;
                if (Configs.AccountInMoney)
                {
                    floatingPL = position.MoneyFloatingPL.ToString("F2");
                }
                else
                {
                    floatingPL = position.FloatingPL.ToString("F2");
                }

                int p = 0;
                asJournalData[row, p++] = (posNumber + 1).ToString();
                asJournalData[row, p++] = (bar + 1).ToString();
                asJournalData[row, p++] = Data.Time[bar].ToString(Data.DF) + Data.Time[bar].ToString(" HH:mm");
                asJournalData[row, p++] = Language.T(position.Transaction.ToString());
                asJournalData[row, p++] = Language.T(position.PosDir.ToString());
                asJournalData[row, p++] = posAmount;
                asJournalData[row, p++] = position.FormOrdPrice.ToString(Data.FF);
                asJournalData[row, p++] = position.PosPrice.ToString(Data.FF);
                asJournalData[row, p++] = position.RequiredMargin.ToString("F2");

                // Charges
                if (Configs.AccountInMoney)
                {   // in currency
                    if (position.Transaction == Transaction.Open ||
                        position.Transaction == Transaction.Add ||
                        position.Transaction == Transaction.Reverse)
                    {
                        asJournalData[row, p++] = position.MoneySpread.ToString("F2");
                    }
                    else
                    {
                        asJournalData[row, p++] = "-";
                    }

                    if (position.Transaction == Transaction.Transfer)
                    {
                        asJournalData[row, p++] = position.MoneyRollover.ToString("F2");
                    }
                    else
                    {
                        asJournalData[row, p++] = "-";
                    }

                    if (position.Transaction == Transaction.Open ||
                        position.Transaction == Transaction.Close ||
                        position.Transaction == Transaction.Add ||
                        position.Transaction == Transaction.Reduce ||
                        position.Transaction == Transaction.Reverse)
                    {
                        asJournalData[row, p++] = position.MoneyCommission.ToString("F2");
                        asJournalData[row, p++] = position.MoneySlippage.ToString("F2");
                    }
                    else
                    {
                        asJournalData[row, p++] = "-";
                        asJournalData[row, p++] = "-";
                    }
                }
                else
                {   // In pips
                    if (position.Transaction == Transaction.Open ||
                        position.Transaction == Transaction.Add ||
                        position.Transaction == Transaction.Reverse)
                    {
                        asJournalData[row, p++] = position.Spread.ToString();
                    }
                    else
                    {
                        asJournalData[row, p++] = "-";
                    }

                    if (position.Transaction == Transaction.Transfer)
                    {
                        asJournalData[row, p++] = position.Rollover.ToString("F2");
                    }
                    else
                    {
                        asJournalData[row, p++] = "-";
                    }

                    if (position.Transaction == Transaction.Open ||
                        position.Transaction == Transaction.Close ||
                        position.Transaction == Transaction.Add ||
                        position.Transaction == Transaction.Reduce ||
                        position.Transaction == Transaction.Reverse)
                    {
                        asJournalData[row, p++] = position.Commission.ToString("F2");
                        asJournalData[row, p++] = position.Slippage.ToString();
                    }
                    else
                    {
                        asJournalData[row, p++] = "-";
                        asJournalData[row, p++] = "-";
                    }
                }

                // Profit Loss
                if (position.Transaction == Transaction.Close ||
                    position.Transaction == Transaction.Reduce ||
                    position.Transaction == Transaction.Reverse)
                {
                    asJournalData[row, p++] = profitLoss;
                }
                else
                {
                    asJournalData[row, p++] = "-";
                }

                // Floating Profit Loss
                if (position.PosNumb == Backtester.SummaryPosNumb(bar) &&
                    position.Transaction != Transaction.Close)
                {
                    asJournalData[row, p++] = floatingPL;  //Last position of the bar only
                }
                else
                {
                    asJournalData[row, p++] = "-";
                }

                // Balance / Equity
                if (Configs.AccountInMoney)
                {
                    asJournalData[row, p++] = position.MoneyBalance.ToString("F2");
                    asJournalData[row, p++] = position.MoneyEquity.ToString("F2");
                }
                else
                {
                    asJournalData[row, p++] = position.Balance.ToString("F2");
                    asJournalData[row, p++] = position.Equity.ToString("F2");
                }

                asJournalData[row, p++] = Language.T(Backtester.BackTestEval(bar));

                // Icons
                aiPositionIcons[row] = position.PositionIcon;
            }

            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;
        }
示例#6
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);
        }
        /// <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);
        }
示例#8
0
        /// <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);
        }
示例#9
0
        /// <summary>
        /// Exports the positions info in currency
        /// </summary>
        public void ExportPositionsInMoney(bool showTransfers)
        {
            string stage = String.Empty;

            if (Data.IsProgramBeta)
            {
                stage = " " + Language.T("Beta");
            }
            else if (Data.IsProgramRC)
            {
                stage = " " + "RC";
            }

            string ff = Data.FF; // Format modifier to print float numbers
            var    sb = new StringBuilder();

            sb.Append("Forex Strategy Builder v" + Data.ProgramVersion + stage + Environment.NewLine);
            sb.Append("Strategy name: " + Data.Strategy.StrategyName + Environment.NewLine);
            sb.Append("Exported on " + DateTime.Now + Environment.NewLine);
            sb.Append(Data.Symbol + " " + Data.PeriodString + "; Values in " + Configs.AccountCurrency +
                      Environment.NewLine);

            sb.Append("Pos Numb\t");
            sb.Append("Bar Numb\t");
            sb.Append("Bar Opening Time\t");
            sb.Append("Direction\t");
            sb.Append("Amount\t");
            sb.Append("Transaction\t");
            sb.Append("Order Price\t");
            sb.Append("Price\t");
            sb.Append("Profit Loss\t");
            sb.Append("Floating P/L\t");
            sb.Append("Balance\t");
            sb.Append("Equity\t");
            sb.Append(Environment.NewLine);

            for (int pos = 0; pos < Backtester.PositionsTotal; pos++)
            {
                Position position = Backtester.PosFromNumb(pos);
                int      bar      = Backtester.PosCoordinates[pos].Bar;

                if (!showTransfers && position.Transaction == Transaction.Transfer)
                {
                    continue;
                }

                sb.Append((position.PosNumb + 1) + "\t");
                sb.Append((bar + 1) + "\t");
                sb.Append(Data.Time[bar] + "\t");
                sb.Append(position.PosDir + "\t");
                sb.Append((position.PosDir == PosDirection.Long ? "" : "-") +
                          (position.PosLots * Data.InstrProperties.LotSize) + "\t");
                sb.Append(position.Transaction + "\t");
                sb.Append(position.FormOrdPrice.ToString(ff) + "\t");
                sb.Append(position.PosPrice.ToString(ff) + "\t");
                sb.Append(position.MoneyProfitLoss.ToString("F2") + "\t");
                sb.Append(position.MoneyFloatingPL.ToString("F2") + "\t");
                sb.Append(position.MoneyBalance.ToString("F2") + "\t");
                sb.Append(position.MoneyEquity.ToString("F2") + "\t");
                sb.Append(Environment.NewLine);
            }

            string fileName = Data.Strategy.StrategyName + "-" + Data.Symbol + "-" + Data.Period;

            SaveData(fileName, sb);
        }
示例#10
0
        /// <summary>
        /// Exports the positions info
        /// </summary>
        public void ExportPositions(bool showTransfers)
        {
            string stage = String.Empty;

            if (Data.IsProgramBeta)
            {
                stage = " " + Language.T("Beta");
            }
            else if (Data.IsProgramRC)
            {
                stage = " " + "RC";
            }

            string ff = Data.FF; // Format modifier to print float numbers
            var    sb = new StringBuilder();

            sb.Append("Forex Strategy Builder v" + Data.ProgramVersion + stage + Environment.NewLine);
            sb.Append("Strategy name: " + Data.Strategy.StrategyName + Environment.NewLine);
            sb.Append("Exported on " + DateTime.Now + Environment.NewLine);
            sb.Append(Data.Symbol + " " + Data.PeriodString + "; Values in pips" + Environment.NewLine);

            sb.Append("Pos Numb\t");
            sb.Append("Bar Numb\t");
            sb.Append("Bar Opening Time\t");
            sb.Append("Direction\t");
            sb.Append("Lots\t");
            sb.Append("Transaction\t");
            sb.Append("Order Price\t");
            sb.Append("Average Price\t");
            sb.Append("Profit Loss\t");
            sb.Append("Floating P/L\t");
            sb.Append("Balance\t");
            sb.Append("Equity\t");
            sb.Append(Environment.NewLine);

            for (int iPos = 0; iPos < Backtester.PositionsTotal; iPos++)
            {
                Position position = Backtester.PosFromNumb(iPos);
                int      bar      = Backtester.PosCoordinates[iPos].Bar;

                if (!showTransfers && position.Transaction == Transaction.Transfer)
                {
                    continue;
                }

                sb.Append((position.PosNumb + 1) + "\t");
                sb.Append((bar + 1) + "\t");
                sb.Append(Data.Time[bar] + "\t");
                sb.Append(position.PosDir + "\t");
                sb.Append(position.PosLots + "\t");
                sb.Append(position.Transaction + "\t");
                sb.Append(position.FormOrdPrice.ToString(ff) + "\t");
                sb.Append(position.PosPrice.ToString(ff) + "\t");
                sb.Append(Math.Round(position.ProfitLoss) + "\t");
                sb.Append(Math.Round(position.FloatingPL) + "\t");
                sb.Append(Math.Round(position.Balance) + "\t");
                sb.Append(Math.Round(position.Equity) + "\t");
                sb.Append(Environment.NewLine);
            }

            string fileName = Data.Strategy.StrategyName + "-" + Data.Symbol + "-" + Data.Period;

            SaveData(fileName, sb);
        }
示例#11
0
        /// <summary>
        /// Calculates the account statistics.
        /// </summary>
        public static void CalculateAccountStats()
        {
            maxBalance        = 0;
            minBalance        = 0;
            maxEquity         = 0;
            minEquity         = 0;
            maxEquityDrawdown = 0;
            maxDrawdown       = 0;

            maxMoneyBalance        = Configs.InitialAccount;
            minMoneyBalance        = Configs.InitialAccount;
            maxMoneyEquity         = Configs.InitialAccount;
            minMoneyEquity         = Configs.InitialAccount;
            maxMoneyEquityDrawdown = 0;
            maxMoneyDrawdown       = 0;

            barsInPosition         = 0;
            grossProfit            = 0;
            grossLoss              = 0;
            grossMoneyProfit       = 0;
            grossMoneyLoss         = 0;
            chargedSpread          = 0;
            chargedRollOver        = 0;
            chargedCommission      = 0;
            chargedSlippage        = 0;
            moneyChargedSpread     = 0;
            moneyChargedRollOver   = 0;
            moneyChargedCommission = 0;
            moneyChargedSlippage   = 0;
            ambiguousBars          = 0;
            unknownBars            = 0;
            balanceDrawdown        = new int[Bars];
            equityDrawdown         = new int[Bars];

            maxBalanceDate       = Time[0];
            minBalanceDate       = Time[0];
            maxMoneyBalanceDate  = Time[0];
            minMoneyBalanceDate  = Time[0];
            maxDrawdownDate      = Time[0];
            maxMoneyDrawdownDate = Time[0];

            equityPercentDrawdown      = 100;
            maxMoneyDrawdownPercent    = 0;
            moneyEquityPercentDrawdown = 0;
            winLossRatio = 0;

            winningTrades = 0;
            losingTrades  = 0;
            totalTrades   = 0;
            testedDays    = 0;

            for (int bar = FirstBar; bar < Bars; bar++)
            {
                double accountExchangeRate = AccountExchangeRate(Close[bar]);
                double pipsToMoney         = InstrProperties.Point * InstrProperties.LotSize / accountExchangeRate;

                // Balance
                double balance = session[bar].Summary.Balance;
                if (balance > maxBalance)
                {
                    maxBalance     = balance;
                    maxBalanceDate = Time[bar];
                }
                if (balance < minBalance)
                {
                    minBalance     = balance;
                    minBalanceDate = Time[bar];
                }

                // Money Balance
                double moneyBalance = session[bar].Summary.MoneyBalance;
                if (moneyBalance > maxMoneyBalance)
                {
                    maxMoneyBalance     = moneyBalance;
                    maxMoneyBalanceDate = Time[bar];
                }
                if (moneyBalance < minMoneyBalance)
                {
                    minMoneyBalance     = moneyBalance;
                    minMoneyBalanceDate = Time[bar];
                }

                // Equity
                double equity = session[bar].Summary.Equity;
                if (equity > maxEquity)
                {
                    maxEquity = equity;
                }
                if (equity < minEquity)
                {
                    minEquity = equity;
                }

                // Money Equity
                double moneyEquity = session[bar].Summary.MoneyEquity;
                if (moneyEquity > maxMoneyEquity)
                {
                    maxMoneyEquity = moneyEquity;
                }
                if (moneyEquity < minMoneyEquity)
                {
                    minMoneyEquity = moneyEquity;
                }

                // Maximum Drawdown
                if (maxBalance - balance > maxDrawdown)
                {
                    maxDrawdown     = maxBalance - balance;
                    maxDrawdownDate = Time[bar];
                }

                // Maximum Equity Drawdown
                if (maxEquity - equity > maxEquityDrawdown)
                {
                    maxEquityDrawdown = maxEquity - equity;

                    // In percents
                    if (maxEquity > 0)
                    {
                        equityPercentDrawdown = 100 * (maxEquityDrawdown / maxEquity);
                    }
                }

                // Maximum Money Drawdown
                if (maxMoneyBalance - MoneyBalance(bar) > maxMoneyDrawdown)
                {
                    maxMoneyDrawdown        = maxMoneyBalance - MoneyBalance(bar);
                    maxMoneyDrawdownPercent = 100 * (maxMoneyDrawdown / maxMoneyBalance);
                    maxMoneyDrawdownDate    = Time[bar];
                }

                // Maximum Money Equity Drawdown
                if (maxMoneyEquity - MoneyEquity(bar) > maxMoneyEquityDrawdown)
                {
                    maxMoneyEquityDrawdown = maxMoneyEquity - MoneyEquity(bar);

                    // Maximum Money Equity Drawdown in percents
                    if (100 * maxMoneyEquityDrawdown / maxMoneyEquity > moneyEquityPercentDrawdown)
                    {
                        moneyEquityPercentDrawdown = 100 * (maxMoneyEquityDrawdown / maxMoneyEquity);
                    }
                }

                // Drawdown
                balanceDrawdown[bar] = (int)Math.Round((maxBalance - balance));
                equityDrawdown[bar]  = (int)Math.Round((maxEquity - equity));

                // Bars in position
                if (session[bar].Positions > 0)
                {
                    barsInPosition++;
                }

                // Bar interpolation evaluation
                if (session[bar].BacktestEval == BacktestEval.Ambiguous)
                {
                    ambiguousBars++;
                }
                else if (session[bar].BacktestEval == BacktestEval.Unknown)
                {
                    unknownBars++;
                }

                // Margin Call bar
                if (!Configs.TradeUntilMarginCall && marginCallBar == 0 && session[bar].Summary.FreeMargin < 0)
                {
                    marginCallBar = bar;
                }
            }

            for (int pos = 0; pos < PositionsTotal; pos++)
            {   // Charged fees
                Position position = Backtester.PosFromNumb(pos);
                chargedSpread          += position.Spread;
                chargedRollOver        += position.Rollover;
                chargedCommission      += position.Commission;
                chargedSlippage        += position.Slippage;
                moneyChargedSpread     += position.MoneySpread;
                moneyChargedRollOver   += position.MoneyRollover;
                moneyChargedCommission += position.MoneyCommission;
                moneyChargedSlippage   += position.MoneySlippage;

                // Winning losing trades.
                if (position.Transaction == Transaction.Close ||
                    position.Transaction == Transaction.Reduce ||
                    position.Transaction == Transaction.Reverse)
                {
                    if (position.ProfitLoss > 0)
                    {
                        grossProfit      += position.ProfitLoss;
                        grossMoneyProfit += position.MoneyProfitLoss;
                        winningTrades++;
                    }
                    else if (position.ProfitLoss < 0)
                    {
                        grossLoss      += position.ProfitLoss;
                        grossMoneyLoss += position.MoneyProfitLoss;
                        losingTrades++;
                    }
                    totalTrades++;
                }
            }

            winLossRatio = (double)winningTrades / Math.Max((losingTrades + winningTrades), 1.0);

            executedOrders = 0;
            tradedLots     = 0;
            for (int ord = 0; ord < totalOrders; ord++)
            {
                if (OrdFromNumb(ord).OrdStatus == OrderStatus.Executed)
                {
                    executedOrders++;
                    tradedLots += OrdFromNumb(ord).OrdLots;
                }
            }

            testedDays = (Time[Bars - 1] - Time[FirstBar]).Days;
            if (testedDays < 1)
            {
                testedDays = 1;
            }

            if (Configs.AccountInMoney)
            {
                GenerateAccountStatsInMoney();
            }
            else
            {
                GenerateAccountStats();
            }

            if (Configs.AdditionalStatistics)
            {
                CalculateAdditionalStats();

                if (Configs.AccountInMoney)
                {
                    SetAdditioanlMoneyStats();
                }
                else
                {
                    SetAdditioanlStats();
                }
            }

            return;
        }
        /// <summary>
        /// Calculates the values of the stats parameters.
        /// </summary>
        static void CalculateAdditionalStats()
        {
            longBalance       = new double[Bars];
            shortBalance      = new double[Bars];
            longMoneyBalance  = new double[Bars];
            shortMoneyBalance = new double[Bars];

            maxLongMoneyBalance  = Configs.InitialAccount;
            minLongMoneyBalance  = Configs.InitialAccount;
            maxShortMoneyBalance = Configs.InitialAccount;
            minShortMoneyBalance = Configs.InitialAccount;
            maxLongBalance       = 0;
            minLongBalance       = 0;
            maxShortBalance      = 0;
            minShortBalance      = 0;

            maxLongBalanceDate        = Time[0];
            minLongBalanceDate        = Time[0];
            maxShortBalanceDate       = Time[0];
            minShortBalanceDate       = Time[0];
            maxLongMoneyBalanceDate   = Time[0];
            minLongMoneyBalanceDate   = Time[0];
            maxShortMoneyBalanceDate  = Time[0];
            minShortMoneyBalanceDate  = Time[0];
            maxLongDrawdownDate       = Time[0];
            maxShortDrawdownDate      = Time[0];
            maxLongMoneyDrawdownDate  = Time[0];
            maxShortMoneyDrawdownDate = Time[0];

            grossLongProfit       = 0;
            grossLongLoss         = 0;
            grossShortProfit      = 0;
            grossShortLoss        = 0;
            grossLongMoneyProfit  = 0;
            grossLongMoneyLoss    = 0;
            grossShortMoneyProfit = 0;
            grossShortMoneyLoss   = 0;

            maxLongDrawdown              = 0;
            maxShortDrawdown             = 0;
            maxLongMoneyDrawdown         = 0;
            maxShortMoneyDrawdown        = 0;
            maxShortDrawdown             = 0;
            maxLongMoneyDrawdown         = 0;
            maxShortMoneyDrawdown        = 0;
            maxLongMoneyDrawdownPercent  = 0;
            maxShortMoneyDrawdownPercent = 0;

            barsWithPos      = 0;
            barsWithLongPos  = 0;
            barsWithShortPos = 0;

            winningLongTrades  = 0;
            winningShortTrades = 0;
            losingLongTrades   = 0;
            losingShortTrades  = 0;

            totalLongTrades  = 0;
            totalShortTrades = 0;

            maxLongWin        = 0;
            maxShortWin       = 0;
            maxLongMoneyWin   = 0;
            maxShortMoneyWin  = 0;
            maxLongLoss       = 0;
            maxShortLoss      = 0;
            maxLongMoneyLoss  = 0;
            maxShortMoneyLoss = 0;

            for (int bar = 0; bar < FirstBar; bar++)
            {
                longBalance[bar]       = 0;
                shortBalance[bar]      = 0;
                longMoneyBalance[bar]  = Configs.InitialAccount;
                shortMoneyBalance[bar] = Configs.InitialAccount;
            }

            for (int bar = Data.FirstBar; bar < Bars; bar++)
            {
                double accountExchangeRate = AccountExchangeRate(Close[bar]);
                double pipsToMoney         = InstrProperties.Point * InstrProperties.LotSize / accountExchangeRate;

                longBalance[bar]       = longBalance[bar - 1];
                shortBalance[bar]      = shortBalance[bar - 1];
                longMoneyBalance[bar]  = longMoneyBalance[bar - 1];
                shortMoneyBalance[bar] = shortMoneyBalance[bar - 1];

                bool isLong  = false;
                bool isShort = false;
                for (int pos = 0; pos < Positions(bar); pos++)
                {
                    if (PosDir(bar, pos) == PosDirection.Long)
                    {
                        isLong = true;
                    }

                    if (PosDir(bar, pos) == PosDirection.Short)
                    {
                        isShort = true;
                    }

                    double positionProfitLoss      = PosProfitLoss(bar, pos);
                    double positionMoneyProfitLoss = PosMoneyProfitLoss(bar, pos);

                    if (PosTransaction(bar, pos) == Transaction.Close ||
                        PosTransaction(bar, pos) == Transaction.Reduce ||
                        PosTransaction(bar, pos) == Transaction.Reverse)
                    {
                        if (OrdFromNumb(PosOrdNumb(bar, pos)).OrdDir == OrderDirection.Sell)
                        {   // Closing long position
                            longBalance[bar]      += positionProfitLoss;
                            longMoneyBalance[bar] += positionMoneyProfitLoss;

                            if (positionProfitLoss > 0)
                            {
                                grossLongProfit      += positionProfitLoss;
                                grossLongMoneyProfit += positionMoneyProfitLoss;
                                winningLongTrades++;
                                if (positionProfitLoss > maxLongWin)
                                {
                                    maxLongWin = positionProfitLoss;
                                }
                                if (positionMoneyProfitLoss > maxLongMoneyWin)
                                {
                                    maxLongMoneyWin = positionMoneyProfitLoss;
                                }
                            }
                            if (positionProfitLoss < 0)
                            {
                                grossLongLoss      += positionProfitLoss;
                                grossLongMoneyLoss += positionMoneyProfitLoss;
                                losingLongTrades++;
                                if (positionProfitLoss < maxLongLoss)
                                {
                                    maxLongLoss = positionProfitLoss;
                                }
                                if (positionMoneyProfitLoss < maxLongMoneyLoss)
                                {
                                    maxLongMoneyLoss = positionMoneyProfitLoss;
                                }
                            }

                            totalLongTrades++;
                        }
                        if (OrdFromNumb(PosOrdNumb(bar, pos)).OrdDir == OrderDirection.Buy)
                        {   // Closing short position
                            shortBalance[bar]      += positionProfitLoss;
                            shortMoneyBalance[bar] += positionMoneyProfitLoss;

                            if (positionProfitLoss > 0)
                            {
                                grossShortProfit      += positionProfitLoss;
                                grossShortMoneyProfit += positionMoneyProfitLoss;
                                winningShortTrades++;
                                if (positionProfitLoss > maxShortWin)
                                {
                                    maxShortWin = positionProfitLoss;
                                }
                                if (positionMoneyProfitLoss > maxShortMoneyWin)
                                {
                                    maxShortMoneyWin = positionMoneyProfitLoss;
                                }
                            }
                            if (positionProfitLoss < 0)
                            {
                                grossShortLoss      += positionProfitLoss;
                                grossShortMoneyLoss += positionMoneyProfitLoss;
                                losingShortTrades++;
                                if (positionProfitLoss < maxShortLoss)
                                {
                                    maxShortLoss = positionProfitLoss;
                                }
                                if (positionMoneyProfitLoss < maxShortMoneyLoss)
                                {
                                    maxShortMoneyLoss = positionMoneyProfitLoss;
                                }
                            }

                            totalShortTrades++;
                        }
                    }
                }

                barsWithPos      += (isLong || isShort) ? 1 : 0;
                barsWithLongPos  += isLong  ? 1 : 0;
                barsWithShortPos += isShort ? 1 : 0;

                if (maxLongBalance < longBalance[bar])
                {
                    maxLongBalance     = longBalance[bar];
                    maxLongBalanceDate = Time[bar];
                }
                if (minLongBalance > longBalance[bar])
                {
                    minLongBalance     = longBalance[bar];
                    minLongBalanceDate = Time[bar];
                }
                if (maxShortBalance < shortBalance[bar])
                {
                    maxShortBalance     = shortBalance[bar];
                    maxShortBalanceDate = Time[bar];
                }
                if (minShortBalance > shortBalance[bar])
                {
                    minShortBalance     = shortBalance[bar];
                    minShortBalanceDate = Time[bar];
                }
                if (maxLongMoneyBalance < longMoneyBalance[bar])
                {
                    maxLongMoneyBalance     = longMoneyBalance[bar];
                    maxLongMoneyBalanceDate = Time[bar];
                }
                if (minLongMoneyBalance > longMoneyBalance[bar])
                {
                    minLongMoneyBalance     = longMoneyBalance[bar];
                    minLongMoneyBalanceDate = Time[bar];
                }
                if (maxShortMoneyBalance < shortMoneyBalance[bar])
                {
                    maxShortMoneyBalance     = shortMoneyBalance[bar];
                    maxShortMoneyBalanceDate = Time[bar];
                }
                if (minShortMoneyBalance > shortMoneyBalance[bar])
                {
                    minShortMoneyBalance     = shortMoneyBalance[bar];
                    minShortMoneyBalanceDate = Time[bar];
                }

                // Maximum Drawdown
                if (maxLongBalance - longBalance[bar] > maxLongDrawdown)
                {
                    maxLongDrawdown     = maxLongBalance - longBalance[bar];
                    maxLongDrawdownDate = Time[bar];
                }

                if (maxLongMoneyBalance - longMoneyBalance[bar] > maxLongMoneyDrawdown)
                {
                    maxLongMoneyDrawdown        = maxLongMoneyBalance - longMoneyBalance[bar];
                    maxLongMoneyDrawdownPercent = 100 * maxLongMoneyDrawdown / maxLongMoneyBalance;
                    maxLongMoneyDrawdownDate    = Time[bar];
                }

                if (maxShortBalance - shortBalance[bar] > maxShortDrawdown)
                {
                    maxShortDrawdown     = maxShortBalance - shortBalance[bar];
                    maxShortDrawdownDate = Time[bar];
                }

                if (maxShortMoneyBalance - shortMoneyBalance[bar] > maxShortMoneyDrawdown)
                {
                    maxShortMoneyDrawdown        = maxShortMoneyBalance - shortMoneyBalance[bar];
                    maxShortMoneyDrawdownPercent = 100 * maxShortMoneyDrawdown / maxShortMoneyBalance;
                    maxShortMoneyDrawdownDate    = Time[bar];
                }
            }

            // Holding period returns
            AHPR      = 0;
            AHPRLong  = 0;
            AHPRShort = 0;

            double[] HPR      = new double[totalTrades];
            double[] HPRLong  = new double[totalLongTrades];
            double[] HPRShort = new double[totalShortTrades];

            double totalHPR      = 0;
            double totalHPRLong  = 0;
            double totalHPRShort = 0;

            double startBalance      = Configs.InitialAccount;
            double startBalanceLong  = Configs.InitialAccount;
            double startBalanceShort = Configs.InitialAccount;

            int count  = 0;
            int countL = 0;
            int countS = 0;

            for (int pos = 0; pos < PositionsTotal; pos++)
            {   // Charged fees
                Position position = Backtester.PosFromNumb(pos);
                // Winning losing trades.
                if (position.Transaction == Transaction.Close ||
                    position.Transaction == Transaction.Reduce ||
                    position.Transaction == Transaction.Reverse)
                {
                    if (OrdFromNumb(position.FormOrdNumb).OrdDir == OrderDirection.Sell)
                    {  // Closing long position
                        HPRLong[countL] = 1 + position.MoneyProfitLoss / startBalanceLong;
                        totalHPRLong   += HPRLong[countL];
                        countL++;
                        startBalanceLong += position.MoneyProfitLoss;
                    }
                    if (OrdFromNumb(position.FormOrdNumb).OrdDir == OrderDirection.Buy)
                    {  // Closing short position
                        HPRShort[countS] = 1 + position.MoneyProfitLoss / startBalanceShort;
                        totalHPRShort   += HPRShort[countS];
                        countS++;
                        startBalanceShort += position.MoneyProfitLoss;
                    }
                    HPR[count] = 1 + position.MoneyProfitLoss / startBalance;
                    totalHPR  += HPR[count];
                    count++;
                    startBalance += position.MoneyProfitLoss;
                }
            }

            double averageHPR      = totalHPR / totalTrades;
            double averageHPRLong  = totalHPRLong / totalLongTrades;
            double averageHPRShort = totalHPRShort / totalShortTrades;

            AHPR      = 100 * (averageHPR - 1);
            AHPRLong  = 100 * (averageHPRLong - 1);
            AHPRShort = 100 * (averageHPRShort - 1);

            GHPR      = 100 * (Math.Pow((NetMoneyBalance / Configs.InitialAccount), (1f / totalTrades)) - 1);
            GHPRLong  = 100 * (Math.Pow((NetLongMoneyBalance / Configs.InitialAccount), (1f / totalLongTrades)) - 1);
            GHPRShort = 100 * (Math.Pow((NetShortMoneyBalance / Configs.InitialAccount), (1f / totalShortTrades)) - 1);

            // Sharpe Ratio
            sharpeRatio      = 0;
            sharpeRatioLong  = 0;
            sharpeRatioShort = 0;

            double sumPow      = 0;
            double sumPowLong  = 0;
            double sumPowShort = 0;

            for (int i = 0; i < totalTrades; i++)
            {
                sumPow += Math.Pow((HPR[i] - averageHPR), 2);
            }
            for (int i = 0; i < totalLongTrades; i++)
            {
                sumPowLong += Math.Pow((HPRLong[i] - averageHPRLong), 2);
            }
            for (int i = 0; i < totalShortTrades; i++)
            {
                sumPowShort += Math.Pow((HPRShort[i] - averageHPRShort), 2);
            }

            double stDev      = Math.Sqrt(sumPow / (totalTrades - 1));
            double stDevLong  = Math.Sqrt(sumPowLong / (totalLongTrades - 1));
            double stDevShort = Math.Sqrt(sumPowShort / (totalShortTrades - 1));

            sharpeRatio      = (averageHPR - 1) / stDev;
            sharpeRatioLong  = (averageHPRLong - 1) / stDevLong;
            sharpeRatioShort = (averageHPRShort - 1) / stDevShort;
        }