Class Backtester
Inheritance: Data
        /// <summary>
        /// This event handler deals with the results of the background operation.
        /// </summary>
        private void BgWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (Data.IsIntrabarData || Configs.UseTickData && Data.IsTickData || Data.Period == DataPeriods.min1)
            {
                Backtester.Scan();
            }

            if (!CompactMode)
            {
                ShowScanningResult();
            }
            CompleteScanning();

            if (_warningMessage != string.Empty && Configs.CheckData)
            {
                MessageBox.Show(_warningMessage + Environment.NewLine + Environment.NewLine +
                                Language.T("The data is probably incomplete and the scanning may not be reliable!") +
                                Environment.NewLine +
                                Language.T("You can try also \"Cut Off Bad Data\"."),
                                Language.T("Scanner"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }

            if (CompactMode)
            {
                Close();
            }
        }
示例#2
0
        public static void ExportStrategyToIndicator()
        {
            StringBuilder sbLong  = new StringBuilder();
            StringBuilder sbShort = new StringBuilder();

            for (int iBar = Data.FirstBar; iBar < Data.Bars; iBar++)
            {
                for (int iPos = 0; iPos < Backtester.Positions(iBar); iPos++)
                {
                    if (Backtester.PosDir(iBar, iPos) == PosDirection.Long)
                    {
                        sbLong.AppendLine("				\""+ Data.Time[iBar].ToString() + "\",");
                    }

                    if (Backtester.PosDir(iBar, iPos) == PosDirection.Short)
                    {
                        sbShort.AppendLine("				\""+ Data.Time[iBar].ToString() + "\",");
                    }
                }
            }

            string strategy = Properties.Resources.StrategyToIndicator;

            strategy = strategy.Replace("#MODIFIED#", DateTime.Now.ToString());
            strategy = strategy.Replace("#INSTRUMENT#", Data.Symbol);
            strategy = strategy.Replace("#BASEPERIOD#", Data.DataPeriodToString(Data.Period));
            strategy = strategy.Replace("#STARTDATE#", Data.Time[Data.FirstBar].ToString());
            strategy = strategy.Replace("#ENDDATE#", Data.Time[Data.Bars - 1].ToString());

            strategy = strategy.Replace("#PERIODMINUTES#", ((int)Data.Period).ToString());
            strategy = strategy.Replace("#LISTLONG#", sbLong.ToString());
            strategy = strategy.Replace("#LISTSHORT#", sbShort.ToString());

            SaveFileDialog savedlg = new SaveFileDialog();

            savedlg.InitialDirectory = Data.SourceFolder;
            savedlg.AddExtension     = true;
            savedlg.Title            = Language.T("Custom Indicators");
            savedlg.Filter           = Language.T("Custom Indicators") + " (*.cs)|*.cs";

            if (savedlg.ShowDialog() == DialogResult.OK)
            {
                strategy = strategy.Replace("#INDICATORNAME#", Path.GetFileNameWithoutExtension(savedlg.FileName));
                StreamWriter sw = new StreamWriter(savedlg.FileName);
                try
                {
                    sw.Write(strategy);
                }
                catch (Exception exc)
                {
                    MessageBox.Show(exc.Message, Language.T("Custom Indicators"));
                }
                finally
                {
                    sw.Close();
                }
            }

            return;
        }
示例#3
0
        /// <summary>
        /// This event handler deals with the results of the background operation.
        /// </summary>
        void BgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (Data.IsIntrabarData ||
                Configs.UseTickData && Data.IsTickData ||
                Data.Period == DataPeriods.min1)
            {
                Backtester.Scan();
            }

            ShowScanningResult();

            if (warningMessage != string.Empty && Configs.CheckData)
            {
                MessageBox.Show(warningMessage + Environment.NewLine + Environment.NewLine +
                                Language.T("Probably the data is incomplete and the scanning may not be reliable!") + Environment.NewLine +
                                Language.T("You can try also \"Cut Off Bad Data\"."),
                                Language.T("Scanner"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }

            progressBar.Style = ProgressBarStyle.Blocks;

            if (isCompactMode)
            {
                Close();
            }

            return;
        }
示例#4
0
        /// <summary>
        /// Sets the navigation buttons
        /// </summary>
        private void SetBtnNavigate()
        {
            // Buttons "Ambiguous"
            if (Backtester.AmbiguousBars > 0)
            {
                bool isButtonAmbiguous = false;
                for (int i = Data.FirstBar; i < _barCurrent; i++)
                {
                    if (Backtester.BackTestEval(i) == BacktestEval.Ambiguous)
                    {
                        isButtonAmbiguous = true;
                        break;
                    }
                }
                BtnsNavigate[0].Enabled = isButtonAmbiguous;

                isButtonAmbiguous = false;
                for (int i = _barCurrent + 1; i < Data.Bars; i++)
                {
                    if (Backtester.BackTestEval(i) == BacktestEval.Ambiguous)
                    {
                        isButtonAmbiguous = true;
                        break;
                    }
                }
                BtnsNavigate[5].Enabled = isButtonAmbiguous;
            }

            // Buttons "Deals"
            if (Backtester.PositionsTotal > 0)
            {
                bool isButtonDeal = false;
                for (int i = Data.FirstBar; i < _barCurrent; i++)
                {
                    if (Backtester.Positions(i) > 0)
                    {
                        isButtonDeal = true;
                        break;
                    }
                }
                BtnsNavigate[1].Enabled = isButtonDeal;

                isButtonDeal = false;
                for (int i = _barCurrent + 1; i < Data.Bars; i++)
                {
                    if (Backtester.Positions(i) > 0)
                    {
                        isButtonDeal = true;
                        break;
                    }
                }
                BtnsNavigate[4].Enabled = isButtonDeal;
            }

            BtnsNavigate[2].Enabled = _barCurrent > Data.FirstBar;
            BtnsNavigate[3].Enabled = _barCurrent < Data.Bars - 1;

            BtnsNavigate[0].ForeColor = BtnsNavigate[0].Enabled ? Color.Red : BtnsNavigate[2].ForeColor;
            BtnsNavigate[5].ForeColor = BtnsNavigate[5].Enabled ? Color.Red : BtnsNavigate[2].ForeColor;
        }
        /// <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;
        }
示例#6
0
        /// <summary>
        /// Calculates the strategy.
        /// </summary>
        /// <param name="recalcIndicators">true - to recalculate all the indicators.</param>
        void Calculate(bool recalcIndicators)
        {
            bool isUPBVChanged = Data.Strategy.AdjustUsePreviousBarValue();

            // Calculates the indicators by slots if it's necessary
            if (recalcIndicators)
            {
                foreach (IndicatorSlot indSlot in Data.Strategy.Slot)
                {
                    string    indicatorName = indSlot.IndicatorName;
                    SlotTypes slotType      = indSlot.SlotType;
                    Indicator indicator     = Indicator_Store.ConstructIndicator(indicatorName, slotType);

                    indicator.IndParam = indSlot.IndParam;

                    indicator.Calculate(slotType);

                    indSlot.IndicatorName  = indicator.IndicatorName;
                    indSlot.IndParam       = indicator.IndParam;
                    indSlot.Component      = indicator.Component;
                    indSlot.SeparatedChart = indicator.SeparatedChart;
                    indSlot.SpecValue      = indicator.SpecialValues;
                    indSlot.MinValue       = indicator.SeparatedChartMinValue;
                    indSlot.MaxValue       = indicator.SeparatedChartMaxValue;
                    indSlot.IsDefined      = true;
                }
            }

            // Searches the indicators' components to determine the Data.FirstBar
            Data.FirstBar = Data.Strategy.SetFirstBar();

            // Logging
            Data.Log("Calculate the strategy");

            // Calculates the backtest
            Backtester.Calculate();
            Backtester.CalculateAccountStats();

            Data.IsResult = true;
            if (isUPBVChanged)
            {
                RebuildStrategyLayout();
            }
            smallIndicatorChart.InitChart();
            smallIndicatorChart.Invalidate();
            smallBalanceChart.SetChartData();
            smallBalanceChart.InitChart();
            smallBalanceChart.Invalidate();
            SetupJournal();
            infpnlAccountStatistics.Update(
                Backtester.AccountStatsParam,
                Backtester.AccountStatsValue,
                Backtester.AccountStatsFlags,
                Language.T("Account Statistics"));

            return;
        }
        /// <summary>
        /// Calculates the result
        /// </summary>
        private void Calculate()
        {
            bool         isLong       = (CbxDirection.SelectedIndex == 0);
            PosDirection posDir       = isLong ? PosDirection.Long : PosDirection.Short;
            int          lotSize      = Data.InstrProperties.LotSize;
            var          lots         = (double)NUDLots.Value;
            var          entryPrice   = (double)NUDEntryPrice.Value;
            var          exitPrice    = (double)NUDExitPrice.Value;
            var          daysRollover = (int)NUDDays.Value;
            double       point        = Data.InstrProperties.Point;
            string       unit         = " " + Configs.AccountCurrency;
            double       entryValue   = lots * lotSize * entryPrice;
            double       exitValue    = lots * lotSize * exitPrice;

            // Required margin
            double requiredMargin = (lots * lotSize / Configs.Leverage) *
                                    (entryPrice / Backtester.AccountExchangeRate(entryPrice));

            AlblOutputValues[0].Text = requiredMargin.ToString("F2") + unit;

            // Gross Profit
            double grossProfit = (isLong ? exitValue - entryValue : entryValue - exitValue) /
                                 Backtester.AccountExchangeRate(exitPrice);

            AlblOutputValues[1].Text = grossProfit.ToString("F2") + unit;

            // Spread
            double spread = Data.InstrProperties.Spread * point * lots * lotSize / Backtester.AccountExchangeRate(exitPrice);

            AlblOutputValues[2].Text = spread.ToString("F2") + unit;

            // Entry Commission
            double entryCommission = Backtester.CommissionInMoney(lots, entryPrice, false);

            AlblOutputValues[3].Text = entryCommission.ToString("F2") + unit;

            // Exit Commission
            double exitCommission = Backtester.CommissionInMoney(lots, exitPrice, true);

            AlblOutputValues[4].Text = exitCommission.ToString("F2") + unit;

            // Rollover
            double rollover = Backtester.RolloverInMoney(posDir, lots, daysRollover, exitPrice);

            AlblOutputValues[5].Text = rollover.ToString("F2") + unit;

            // Slippage
            double slippage = Data.InstrProperties.Slippage * point * lots * lotSize / Backtester.AccountExchangeRate(exitPrice);

            AlblOutputValues[6].Text = slippage.ToString("F2") + unit;

            // Net Profit
            double netProfit = grossProfit - entryCommission - exitCommission - rollover - slippage;

            AlblOutputValues[7].Text = netProfit.ToString("F2") + unit;
        }
        /// <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;
        }
示例#9
0
        /// <summary>
        /// Sets the journal's current data
        /// </summary>
        public void SetUpJournal()
        {
            if (Data.IsResult)
            {
                orders = Backtester.Orders(selectedBar);
            }

            SetSizes();
            SetJournalColors();
            UpdateJournalData();

            return;
        }
        /// <summary>
        /// Sets the navigation buttons
        /// </summary>
        void SetBtnNavigate()
        {
            if (Backtester.AmbiguousBars > 0)
            {
                bool isButtonAmbiguous = false;
                for (int i = Data.FirstBar; i < bar; i++)
                {
                    if (Backtester.BackTestEval(i) == "Ambiguous")
                    {
                        isButtonAmbiguous = true;
                        break;
                    }
                }
                btnNavigate[0].Enabled = isButtonAmbiguous;

                isButtonAmbiguous = false;
                for (int i = bar + 1; i < Data.Bars; i++)
                {
                    if (Backtester.BackTestEval(i) == "Ambiguous")
                    {
                        isButtonAmbiguous = true;
                        break;
                    }
                }
                btnNavigate[3].Enabled = isButtonAmbiguous;
            }

            btnNavigate[1].Enabled = bar > Data.FirstBar;
            btnNavigate[2].Enabled = bar < Data.Bars - 1;

            if (btnNavigate[0].Enabled)
            {
                btnNavigate[0].ForeColor = Color.Red;
            }
            else
            {
                btnNavigate[0].ForeColor = btnNavigate[2].ForeColor;
            }

            if (btnNavigate[3].Enabled)
            {
                btnNavigate[3].ForeColor = Color.Red;
            }
            else
            {
                btnNavigate[3].ForeColor = btnNavigate[2].ForeColor;
            }


            return;
        }
示例#11
0
        /// <summary>
        /// Resizes the form.
        /// </summary>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            SetBtnNavigate();
            for (int bar = Data.FirstBar; bar < Data.Bars; bar++)
            {
                if (Backtester.WayPoints(bar) > _maxWayPoints)
                {
                    _maxWayPoints = Backtester.WayPoints(bar);
                }
            }

            var btnHrzSpace     = (int)(Data.HorizontalDLU * 3);
            int clientSizeWidth = (Math.Max(_aiColumnX[_columns] + 2 * btnHrzSpace, 550));

            ClientSize = new Size(clientSizeWidth, 310 + _infoRowHeight * (_maxWayPoints + 2));
        }
示例#12
0
        /// <summary>
        /// Perform intrabar scanning
        /// </summary>
        void Scan()
        {
            if (!Data.IsIntrabarData)
            {
                ShowScanner();
            }
            else
            {
                Backtester.Scan();
            }

            infpnlAccountStatistics.Update(Backtester.AccountStatsParam, Backtester.AccountStatsValue,
                                           Backtester.AccountStatsFlags, Language.T("Account Statistics"));
            smallBalanceChart.SetChartData();
            smallBalanceChart.InitChart();
            smallBalanceChart.Invalidate();
            SetupJournal();
        }
        /// <summary>
        /// Show position
        /// </summary>
        private void ShowOrder(string input)
        {
            const string pattern    = @"^ord (?<numb>\d+)$";
            var          expression = new Regex(pattern, RegexOptions.Compiled);
            Match        match      = expression.Match(input);

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

                Order order = Backtester.OrdFromNumb(ord - 1);
                TbxOutput.Text += "Order" + Environment.NewLine + "-----------------" +
                                  Environment.NewLine + order + Environment.NewLine;
            }
        }
        /// <summary>
        /// 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>
        /// Resizes the form.
        /// </summary>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            SetBtnNavigate();
            for (int iBar = Data.FirstBar; iBar < Data.Bars; iBar++)
            {
                if (Backtester.WayPoints(iBar) > maxWayPoints)
                {
                    maxWayPoints = Backtester.WayPoints(iBar);
                }
            }

            int btnHrzSpace      = (int)(Data.HorizontalDLU * 3);
            int iClientSizeWidth = (int)(Math.Max(aiColumnX[columns] + 2 * btnHrzSpace, 500));

            ClientSize = new Size(iClientSizeWidth, 310 + infoRowHeight * (maxWayPoints + 2));

            return;
        }
示例#16
0
        /// <summary>
        /// Loads data and recalculates.
        /// </summary>
        protected override void OnShown(EventArgs e)
        {
            base.OnShown(e);

            if (CompactMode)
            {
                return;
            }

            if (!Data.IsIntrabarData)
            {
                StartLoading();
            }
            else
            {
                Backtester.Scan();
                ShowScanningResult();
                ProgressBar.Value = 100;
                BtnClose.Focus();
            }
        }
        /// <summary>
        /// Sets the journal's current data
        /// </summary>
        public void SetUpJournal()
        {
            if (showTransfers)
            {
                positions = Backtester.PositionsTotal;
            }
            else
            {
                if (Backtester.PositionsTotal > 0)
                {
                    aiPosNumber = new int[Backtester.PositionsTotal];
                }
                else
                {
                    aiPosNumber = new int[1];
                }

                positions = 0;
                for (int bar = 0; bar < Data.Bars; bar++)
                {
                    for (int pos = 0; pos < Backtester.Positions(bar); pos++)
                    {
                        Transaction transaction = Backtester.PosTransaction(bar, pos);
                        if (transaction != Transaction.None && transaction != Transaction.Transfer)
                        {
                            aiPosNumber[positions] = Backtester.PosNumb(bar, pos);
                            positions++;
                        }
                    }
                }
            }

            if (positions == 0)
            {
                firstPos    = 0;
                lastPos     = 0;
                shownPos    = 0;
                selectedRow = 0;

                vScrollBar.Enabled = false;
            }
            else if (positions < rows)
            {
                firstPos    = 0;
                lastPos     = rows;
                shownPos    = positions;
                selectedRow = 0;

                vScrollBar.Enabled = false;
            }
            else
            {
                vScrollBar.Enabled = true;
                vScrollBar.Maximum = positions - 1;

                firstPos = vScrollBar.Value;
                if (firstPos + rows > positions)
                {
                    lastPos  = positions - 1;
                    shownPos = lastPos - firstPos + 1;
                }
                else
                {
                    shownPos = rows;
                    lastPos  = firstPos + shownPos - 1;
                }
            }

            selectedRow = Math.Min(selectedRow, shownPos - 1);
            selectedRow = Math.Max(selectedRow, 0);

            UpdateJournalData();
            SetJournalColors();

            return;
        }
        /// <summary>
        /// Sets the chart params
        /// </summary>
        void InitChart(int width, int height)
        {
            chart = new Bitmap(width, height);

            if (!Data.IsData || !Data.IsResult || Data.Bars <= Data.FirstBar)
            {
                return;
            }

            int border = 1;
            int space  = 2;

            int   XLeft, XRight, YTop, YBottom;
            float XScale, YScale;

            int bars;
            int chartBars;
            int maximum;
            int minimum;
            int firstBar;
            Pen penBorder;

            PointF[] apntBalance;
            PointF[] apntEquity;
            PointF[] apntLongBalance;
            PointF[] apntShortBalance;

            firstBar  = Data.FirstBar;
            bars      = Data.Bars;
            chartBars = Data.Bars - firstBar;
            int iMaxBalance = Configs.AccountInMoney ? (int)Backtester.MaxMoneyBalance : Backtester.MaxBalance;
            int iMinBalance = Configs.AccountInMoney ? (int)Backtester.MinMoneyBalance : Backtester.MinBalance;
            int iMaxEquity  = Configs.AccountInMoney ? (int)Backtester.MaxMoneyEquity : Backtester.MaxEquity;
            int iMinEquity  = Configs.AccountInMoney ? (int)Backtester.MinMoneyEquity : Backtester.MinEquity;

            if (Configs.AdditionalStatistics)
            {
                int iMaxLongBalance  = Configs.AccountInMoney ? (int)Backtester.MaxLongMoneyBalance : Backtester.MaxLongBalance;
                int iMinLongBalance  = Configs.AccountInMoney ? (int)Backtester.MinLongMoneyBalance : Backtester.MinLongBalance;
                int iMaxShortBalance = Configs.AccountInMoney ? (int)Backtester.MaxShortMoneyBalance : Backtester.MaxShortBalance;
                int iMinShortBalance = Configs.AccountInMoney ? (int)Backtester.MinShortMoneyBalance : Backtester.MinShortBalance;
                int iMaxLSBalance    = Math.Max(iMaxLongBalance, iMaxShortBalance);
                int iMinLSBalance    = Math.Min(iMinLongBalance, iMinShortBalance);

                maximum = Math.Max(Math.Max(iMaxBalance, iMaxEquity), iMaxLSBalance) + 1;
                minimum = Math.Min(Math.Min(iMinBalance, iMinEquity), iMinLSBalance) - 1;
            }
            else
            {
                maximum = Math.Max(iMaxBalance, iMaxEquity) + 1;
                minimum = Math.Min(iMinBalance, iMinEquity) - 1;
            }

            YTop    = border + space;
            YBottom = height - border - space;
            XLeft   = border;
            XRight  = width - border - space;
            XScale  = (XRight - XLeft) / (float)chartBars;
            YScale  = (YBottom - YTop) / (float)(maximum - minimum);

            penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border);

            apntBalance      = new PointF[chartBars];
            apntEquity       = new PointF[chartBars];
            apntLongBalance  = new PointF[chartBars];
            apntShortBalance = new PointF[chartBars];

            int index = 0;

            for (int iBar = firstBar; iBar < bars; iBar++)
            {
                apntBalance[index].X = XLeft + index * XScale;
                apntEquity[index].X  = XLeft + index * XScale;
                if (Configs.AccountInMoney)
                {
                    apntBalance[index].Y = (float)(YBottom - (Backtester.MoneyBalance(iBar) - minimum) * YScale);
                    apntEquity[index].Y  = (float)(YBottom - (Backtester.MoneyEquity(iBar) - minimum) * YScale);
                }
                else
                {
                    apntBalance[index].Y = YBottom - (Backtester.Balance(iBar) - minimum) * YScale;
                    apntEquity[index].Y  = YBottom - (Backtester.Equity(iBar) - minimum) * YScale;
                }

                if (Configs.AdditionalStatistics)
                {
                    apntLongBalance[index].X  = XLeft + index * XScale;
                    apntShortBalance[index].X = XLeft + index * XScale;
                    if (Configs.AccountInMoney)
                    {
                        apntLongBalance[index].Y  = (float)(YBottom - (Backtester.LongMoneyBalance(iBar) - minimum) * YScale);
                        apntShortBalance[index].Y = (float)(YBottom - (Backtester.ShortMoneyBalance(iBar) - minimum) * YScale);
                    }
                    else
                    {
                        apntLongBalance[index].Y  = YBottom - (Backtester.LongBalance(iBar) - minimum) * YScale;
                        apntShortBalance[index].Y = YBottom - (Backtester.ShortBalance(iBar) - minimum) * YScale;
                    }
                }

                index++;
            }

            Graphics g = Graphics.FromImage(chart);

            // Paints the background by gradient
            RectangleF rectField = new RectangleF(1, 1, width - 2, height - 2);

            g.FillRectangle(new SolidBrush(LayoutColors.ColorChartBack), rectField);

            // Border
            g.DrawRectangle(penBorder, 0, 0, width - 1, height - 1);

            // Equity line
            g.DrawLines(new Pen(LayoutColors.ColorChartEquityLine), apntEquity);

            // Draw Long and Short balance
            if (Configs.AdditionalStatistics)
            {
                g.DrawLines(new Pen(Color.Red), apntShortBalance);
                g.DrawLines(new Pen(Color.Green), apntLongBalance);
            }

            // Draw the balance line
            g.DrawLines(new Pen(LayoutColors.ColorChartBalanceLine), apntBalance);
        }
 private void CalculateStrategy()
 {
     Backtester.Calculate();
     Backtester.CalculateAccountStats();
 }
        /// <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);
        }
示例#21
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);
        }
示例#22
0
        /// <summary>
        /// Updates the journal data from the backtester
        /// </summary>
        void UpdateJournalData()
        {
            if (!Data.IsResult)
            {
                return;
            }

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

            int ordIndex = 0;

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

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

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

            asJournalData = new string[orders, columns];

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

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

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

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

            return;
        }
        /// <summary>
        /// Calculates the balance lines
        /// </summary>
        private int Calculate(BackgroundWorker worker)
        {
            // Determine the number of lines
            // For each method per line
            // The random line shows the averaged values
            // Also we have two border lines for the random method
            // Plus the average balance line

            _isRandom      = false;
            _minimum       = float.MaxValue;
            _maximum       = float.MinValue;
            _minimumRandom = float.MaxValue;
            _maximumRandom = float.MinValue;
            var randomLines = (int)NumRandom.Value;

            _checkedMethods = 0;
            _lines          = 1;
            for (int m = 0; m < _countMethods; m++)
            {
                if (AchboxMethods[m].Checked)
                {
                    _checkedMethods++;
                    _lines++;
                    if ((InterpolationMethod)AchboxMethods[m].Tag == InterpolationMethod.Random)
                    {
                        _isRandom = true;
                    }
                }
            }

            if (_checkedMethods == 0 && Configs.PlaySounds)
            {
                SystemSounds.Hand.Play();
                return(-1);
            }

            _afBalance = new float[Data.Bars - Data.FirstBar];
            _afMethods = new float[_countMethods, Data.Bars - Data.FirstBar];
            if (_isRandom)
            {
                _afRandoms   = new float[randomLines, Data.Bars - Data.FirstBar];
                _afMinRandom = new float[Data.Bars - Data.FirstBar];
                _afMaxRandom = new float[Data.Bars - Data.FirstBar];
            }

            // Progress parameters
            int computedCycles           = 0;
            int cycles                   = _lines + (_isRandom ? randomLines : 0);
            int highestPercentageReached = 0;
            int percentComplete;

            // Calculates the lines
            for (int m = 0; m < _countMethods; m++)
            {
                if (worker.CancellationPending)
                {
                    return(-1);
                }
                if (!AchboxMethods[m].Checked)
                {
                    continue;
                }

                var method = (InterpolationMethod)AchboxMethods[m].Tag;

                if (method == InterpolationMethod.Random)
                {
                    for (int r = 0; r < randomLines; r++)
                    {
                        if (worker.CancellationPending)
                        {
                            return(-1);
                        }

                        Backtester.InterpolationMethod = method;
                        Backtester.Calculate();

                        if (Configs.AccountInMoney)
                        {
                            for (int iBar = 0; iBar < Data.Bars - Data.FirstBar; iBar++)
                            {
                                _afRandoms[r, iBar] = (float)Backtester.MoneyBalance(iBar + Data.FirstBar);
                            }
                        }
                        else
                        {
                            for (int iBar = 0; iBar < Data.Bars - Data.FirstBar; iBar++)
                            {
                                _afRandoms[r, iBar] = Backtester.Balance(iBar + Data.FirstBar);
                            }
                        }


                        // Report progress as a percentage of the total task.
                        computedCycles++;
                        percentComplete = 100 * computedCycles / cycles;
                        percentComplete = percentComplete > 100 ? 100 : percentComplete;
                        if (percentComplete > highestPercentageReached)
                        {
                            highestPercentageReached = percentComplete;
                            worker.ReportProgress(percentComplete);
                        }
                    }

                    for (int iBar = 0; iBar < Data.Bars - Data.FirstBar; iBar++)
                    {
                        float randomSum = 0;
                        float minRandom = float.MaxValue;
                        float maxRandom = float.MinValue;
                        for (int r = 0; r < randomLines; r++)
                        {
                            float value = _afRandoms[r, iBar];
                            randomSum += value;
                            minRandom  = value < minRandom ? value : minRandom;
                            maxRandom  = value > maxRandom ? value : maxRandom;
                        }
                        _afMethods[m, iBar] = randomSum / randomLines;
                        _afMinRandom[iBar]  = minRandom;
                        _afMaxRandom[iBar]  = maxRandom;
                        _minimumRandom      = minRandom < _minimumRandom ? minRandom : _minimumRandom;
                        _maximumRandom      = maxRandom > _maximumRandom ? maxRandom : _maximumRandom;
                    }

                    // Report progress as a percentage of the total task.
                    computedCycles++;
                    percentComplete = 100 * computedCycles / cycles;
                    percentComplete = percentComplete > 100 ? 100 : percentComplete;
                    if (percentComplete > highestPercentageReached)
                    {
                        highestPercentageReached = percentComplete;
                        worker.ReportProgress(percentComplete);
                    }
                }
                else
                {
                    Backtester.InterpolationMethod = method;
                    Backtester.Calculate();

                    if (Configs.AccountInMoney)
                    {
                        for (int iBar = 0; iBar < Data.Bars - Data.FirstBar; iBar++)
                        {
                            _afMethods[m, iBar] = (float)Backtester.MoneyBalance(iBar + Data.FirstBar);
                        }
                    }
                    else
                    {
                        for (int iBar = 0; iBar < Data.Bars - Data.FirstBar; iBar++)
                        {
                            _afMethods[m, iBar] = Backtester.Balance(iBar + Data.FirstBar);
                        }
                    }

                    // Report progress as a percentage of the total task.
                    computedCycles++;
                    percentComplete = 100 * computedCycles / cycles;
                    percentComplete = percentComplete > 100 ? 100 : percentComplete;
                    if (percentComplete > highestPercentageReached)
                    {
                        highestPercentageReached = percentComplete;
                        worker.ReportProgress(percentComplete);
                    }
                }
            }

            // Calculates the average balance, Min and Max
            for (int bar = 0; bar < Data.Bars - Data.FirstBar; bar++)
            {
                float sum = 0;
                for (int m = 0; m < _countMethods; m++)
                {
                    if (!AchboxMethods[m].Checked)
                    {
                        continue;
                    }

                    float value = _afMethods[m, bar];
                    sum += value;
                    if (value < _minimum)
                    {
                        _minimum = value;
                    }
                    if (value > _maximum)
                    {
                        _maximum = value;
                    }
                }
                _afBalance[bar] = sum / _checkedMethods;
            }

            // Report progress as a percentage of the total task.
            computedCycles++;
            percentComplete = 100 * computedCycles / cycles;
            percentComplete = percentComplete > 100 ? 100 : percentComplete;
            if (percentComplete > highestPercentageReached)
            {
                worker.ReportProgress(percentComplete);
            }

            return(0);
        }
        /// <summary>
        /// Paints panel pnlInfo
        /// </summary>
        void PnlInfo_Paint(object sender, PaintEventArgs e)
        {
            // ---------------------------------------------------------------------+
            // |                          Way points description                    |
            // |--------------------------------------------------------------------+
            // | Number | Description | Price | Direction | Lots | Position | Order |
            // |--------------------------------------------------------------------+
            //xp0      xp1           xp2     xp3         xp4    xp5        xp6     xp7

            Graphics g = e.Graphics;

            g.Clear(LayoutColors.ColorControlBack);

            if (!Data.IsData || !Data.IsResult)
            {
                return;
            }

            Panel  pnl   = (Panel)sender;
            Brush  brush = Brushes.White;
            string FF    = Data.FF;   // Format modifier to print the floats

            Size size = new Size(aiX[columns] - aiX[0], infoRowHeight);

            StringFormat sf = new StringFormat();

            sf.Alignment     = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Near;

            // Caption background
            PointF     pntStart     = new PointF(0, 0);
            SizeF      szfCaption   = new Size(pnl.ClientSize.Width, 2 * infoRowHeight);
            RectangleF rectfCaption = new RectangleF(pntStart, szfCaption);

            Data.GradientPaint(g, rectfCaption, LayoutColors.ColorCaptionBack, LayoutColors.DepthCaption);

            // Caption Text
            StringFormat stringFormatCaption = new StringFormat();

            stringFormatCaption.LineAlignment = StringAlignment.Center;
            stringFormatCaption.Trimming      = StringTrimming.EllipsisCharacter;
            stringFormatCaption.FormatFlags   = StringFormatFlags.NoWrap;
            stringFormatCaption.Alignment     = StringAlignment.Near;
            string stringCaptionText = Language.T("Way Points Description");
            float  fCaptionWidth     = (float)Math.Min(pnlInfo.ClientSize.Width, aiX[columns] - aiX[0]);
            float  fCaptionTextWidth = g.MeasureString(stringCaptionText, fontInfo).Width;
            float  fCaptionTextX     = (float)Math.Max((fCaptionWidth - fCaptionTextWidth) / 2f, 0);
            PointF pfCaptionText     = new PointF(fCaptionTextX, 0);
            SizeF  sfCaptionText     = new SizeF(fCaptionWidth - fCaptionTextX, infoRowHeight);

            rectfCaption = new RectangleF(pfCaptionText, sfCaptionText);

            // First caption raw
            g.DrawString(stringCaptionText, fontInfo, brushCaptionText, rectfCaption, stringFormatCaption);

            // Second caption raw
            for (int i = 0; i < columns; i++)
            {
                g.DrawString(asTitles[i], fontInfo, brushCaptionText, (aiX[i] + aiX[i + 1]) / 2, infoRowHeight, sf);
            }

            brush = new SolidBrush(LayoutColors.ColorControlText);

            for (int pnt = 0; pnt < Backtester.WayPoints(bar); pnt++)
            {
                int   y     = (pnt + 2) * infoRowHeight;
                Point point = new Point(aiX[0], y);

                // Even row
                if (pnt % 2f != 0)
                {
                    g.FillRectangle(brushEvenRow, new Rectangle(point, size));
                }

                int          positionNumber = Backtester.WayPoint(bar, pnt).PosNumb;
                WayPointType wpType         = Backtester.WayPoint(bar, pnt).WPType;
                PosDirection posDirection   = Backtester.PosFromNumb(positionNumber).PosDir;
                double       posLots        = Backtester.PosFromNumb(positionNumber).PosLots;
                int          ordNumber      = Backtester.WayPoint(bar, pnt).OrdNumb;

                g.DrawString((pnt + 1).ToString(), fontInfo, brush, (aiX[0] + aiX[1]) / 2, y, sf);
                g.DrawString(Language.T(Way_Point.WPTypeToString(wpType)), fontInfo, brush, aiX[1] + 2, y);
                g.DrawString(Backtester.WayPoint(bar, pnt).Price.ToString(FF), fontInfo, brush, (aiX[3] + aiX[2]) / 2, y, sf);

                if (positionNumber > -1)
                {
                    g.DrawString(Language.T(posDirection.ToString()), fontInfo, brush, (aiX[4] + aiX[3]) / 2, y, sf);
                    g.DrawString(posLots.ToString(), fontInfo, brush, (aiX[5] + aiX[4]) / 2, y, sf);
                    g.DrawString((positionNumber + 1).ToString(), fontInfo, brush, (aiX[6] + aiX[5]) / 2, y, sf);
                }

                if (ordNumber > -1)
                {
                    g.DrawString((ordNumber + 1).ToString(), fontInfo, brush, (aiX[7] + aiX[6]) / 2, y, sf);
                }
            }

            // Vertical lines
            Pen penLine = new Pen(LayoutColors.ColorJournalLines);

            for (int i = 1; i < columns; i++)
            {
                g.DrawLine(penLine, aiX[i], 2 * infoRowHeight, aiX[i], ClientSize.Height - border);
            }

            // Border
            Pen penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border);

            g.DrawLine(penBorder, 1, 2 * infoRowHeight, 1, pnl.ClientSize.Height);
            g.DrawLine(penBorder, pnl.ClientSize.Width - border + 1, 2 * infoRowHeight, pnl.ClientSize.Width - border + 1, pnl.ClientSize.Height);
            g.DrawLine(penBorder, 0, pnl.ClientSize.Height - border + 1, pnl.ClientSize.Width, pnl.ClientSize.Height - border + 1);

            return;
        }
        /// <summary>
        /// Initialize the form and controls
        /// </summary>
        public Bar_Explorer(int iBarNumber)
        {
            pnlChart = new Panel();
            pnlInfo  = new Panel();
            toolTip  = new ToolTip();

            bar = iBarNumber < Data.FirstBar ? Data.FirstBar : iBarNumber;

            this.Text            = Language.T("Bar Explorer");
            this.BackColor       = LayoutColors.ColorFormBack;
            this.FormBorderStyle = FormBorderStyle.FixedDialog;
            this.Icon            = Data.Icon;
            this.MaximizeBox     = false;
            this.MinimizeBox     = false;
            this.ShowInTaskbar   = false;

            fontInfo      = new Font(Font.FontFamily, 9);
            infoRowHeight = (int)Math.Max(fontInfo.Height, 18);

            barInfo = Language.T("Bar") + ": " + (bar + 1).ToString() + " " +
                      Data.Time[bar].ToString(Data.DF) + " " +
                      Data.Time[bar].ToString("HH:mm") + "; " +
                      Language.T("Interpolation method") + ": " +
                      Backtester.InterpolationMethodToString();

            pnlChart.Parent = this;
            pnlChart.Paint += new PaintEventHandler(PnlChart_Paint);

            pnlInfo.Parent = this;
            pnlInfo.Paint += new PaintEventHandler(PnlInfo_Paint);

            btnNavigate = new Button[4];
            string [] btnNavigateText = new string [4] {
                "< !", "<", ">", "! >"
            };
            string[] btnNavigateTips = new string [4] {
                Language.T("Previous ambiguous bar."),
                Language.T("Previous bar."),
                Language.T("Next bar."),
                Language.T("Next ambiguous bar.")
            };

            for (int i = 0; i < 4; i++)
            {
                btnNavigate[i]             = new Button();
                btnNavigate[i].Parent      = this;
                btnNavigate[i].Text        = btnNavigateText[i];
                btnNavigate[i].Name        = btnNavigateText[i];
                btnNavigate[i].Click      += new EventHandler(BtnNavigate_Click);
                btnNavigate[i].MouseWheel += new MouseEventHandler(Bar_Explorer_MouseWheel);
                btnNavigate[i].UseVisualStyleBackColor = true;
                toolTip.SetToolTip(btnNavigate[i], btnNavigateTips[i]);
            }

            btnNavigate[0].Enabled = Backtester.AmbiguousBars > 0;
            btnNavigate[3].Enabled = Backtester.AmbiguousBars > 0;

            nudGo           = new NumericUpDown();
            nudGo.Parent    = this;
            nudGo.TextAlign = HorizontalAlignment.Center;
            nudGo.BeginInit();
            nudGo.Minimum   = Data.FirstBar + 1;
            nudGo.Maximum   = Data.Bars;
            nudGo.Increment = 1;
            nudGo.Value     = bar + 1;
            nudGo.EndInit();

            btnGo        = new Button();
            btnGo.Parent = this;
            btnGo.Name   = "Go";
            btnGo.Text   = Language.T("Go");
            btnGo.UseVisualStyleBackColor = true;
            btnGo.Click      += new EventHandler(BtnNavigate_Click);
            btnGo.MouseWheel += new MouseEventHandler(Bar_Explorer_MouseWheel);
            toolTip.SetToolTip(btnGo, Language.T("Go to the chosen bar."));

            //Button Close
            btnClose                         = new Button();
            btnClose.Parent                  = this;
            btnClose.Text                    = Language.T("Close");
            btnClose.DialogResult            = DialogResult.Cancel;
            btnClose.UseVisualStyleBackColor = true;

            // Colors
            brushRed = new SolidBrush(LayoutColors.ColorSignalRed);

            brushCaptionBack = new SolidBrush(LayoutColors.ColorCaptionBack);
            brushCaptionText = new SolidBrush(LayoutColors.ColorCaptionText);
            brushEvenRow     = new SolidBrush(LayoutColors.ColorEvenRowBack);
            brushBack        = new SolidBrush(LayoutColors.ColorControlBack);
            brushGridText    = new SolidBrush(LayoutColors.ColorChartFore);
            brushBarWhite    = new SolidBrush(LayoutColors.ColorBarWhite);
            brushBarBlack    = new SolidBrush(LayoutColors.ColorBarBlack);
            brushTradeLong   = new SolidBrush(LayoutColors.ColorTradeLong);
            brushTradeShort  = new SolidBrush(LayoutColors.ColorTradeShort);
            brushTradeClose  = new SolidBrush(LayoutColors.ColorTradeClose);

            penGrid             = new Pen(LayoutColors.ColorChartGrid);
            penGrid.DashStyle   = DashStyle.Dash;
            penGrid.DashPattern = new float[] { 4, 2 };
            penGridSolid        = new Pen(LayoutColors.ColorChartGrid);
            penAxes             = new Pen(LayoutColors.ColorChartFore);
            penCross            = new Pen(LayoutColors.ColorChartCross);
            penBarBorder        = new Pen(LayoutColors.ColorBarBorder);

            colorBarWight1 = Data.GetGradientColor(LayoutColors.ColorBarWhite, 30);
            colorBarWight2 = Data.GetGradientColor(LayoutColors.ColorBarWhite, -30);
            colorBarBlack1 = Data.GetGradientColor(LayoutColors.ColorBarBlack, 30);
            colorBarBlack2 = Data.GetGradientColor(LayoutColors.ColorBarBlack, -30);

            colorLongTrade1   = Data.GetGradientColor(LayoutColors.ColorTradeLong, 30);
            colorLongTrade2   = Data.GetGradientColor(LayoutColors.ColorTradeLong, -30);
            colorShortTrade1  = Data.GetGradientColor(LayoutColors.ColorTradeShort, 30);
            colorShortTrade2  = Data.GetGradientColor(LayoutColors.ColorTradeShort, -30);
            colorClosedTrade1 = Data.GetGradientColor(LayoutColors.ColorTradeClose, 30);
            colorClosedTrade2 = Data.GetGradientColor(LayoutColors.ColorTradeClose, -30);

            SetJournalPoints();

            return;
        }
        /// <summary>
        /// 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;
        }
示例#27
0
        /// <summary>
        /// Prepare the parameters
        /// </summary>
        public void SetUpChart()
        {
            // Panel caption
            stringCaptionText                  = Language.T("Indicator Chart");
            fontCaptionText                    = new Font(Font.FontFamily, 9);
            captionHeight                      = Math.Max(fontCaptionText.Height, 18);
            captionWidth                       = this.ClientSize.Width;
            brushCaptionText                   = new SolidBrush(LayoutColors.ColorCaptionText);
            rectfCaption                       = new RectangleF(0, 0, captionWidth, captionHeight);
            stringFormatCaption                = new StringFormat();
            stringFormatCaption.Alignment     |= StringAlignment.Center;
            stringFormatCaption.LineAlignment |= StringAlignment.Center;
            stringFormatCaption.Trimming      |= StringTrimming.EllipsisCharacter;
            stringFormatCaption.FormatFlags   |= StringFormatFlags.NoWrap;

            if (!Data.IsData || !Data.IsResult || Data.Bars <= Data.FirstBar)
            {
                return;
            }

            clSzWidth  = this.ClientSize.Width;
            clSzHeight = this.ClientSize.Height;
            xLeft      = space;
            xRight     = clSzWidth - space;
            yTop       = (int)captionHeight + space;
            yBottom    = clSzHeight - scrollBar.Height - space;
            yPrcBottom = yBottom; // Price chart y
            inds       = 0;       // Count of separated indicators
            indHeight  = 0;       // Height of Ind charts
            aiIndSlot  = new int[12];

            penFore   = new Pen(LayoutColors.ColorChartFore);
            penVolume = new Pen(LayoutColors.ColorVolume);
            penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border);

            for (int slot = Data.Strategy.Slots - 1; slot >= 0; slot--)
            {
                if (Data.Strategy.Slot[slot].SeparatedChart)
                {
                    aiIndSlot[inds++] = slot;
                }
            }

            if (inds > 0)
            {
                indHeight  = (yBottom - yTop) / (2 + inds);
                yPrcBottom = yBottom - inds * indHeight;
            }

            maxPrice  = double.MinValue;
            minPrice  = double.MaxValue;
            maxVolume = int.MinValue;

            for (int bar = firstBar; bar <= lastBar; bar++)
            {
                if (Data.High[bar] > maxPrice)
                {
                    maxPrice = Data.High[bar];
                }
                if (Data.Low[bar] < minPrice)
                {
                    minPrice = Data.Low[bar];
                }
                if (Data.Volume[bar] > maxVolume)
                {
                    maxVolume = Data.Volume[bar];
                }
            }
            minPrice  = Math.Round(minPrice, Data.InstrProperties.Point < 0.001 ? 3 : 1) - Data.InstrProperties.Point * 10;
            maxPrice  = Math.Round(maxPrice, Data.InstrProperties.Point < 0.001 ? 3 : 1) + Data.InstrProperties.Point * 10;
            scaleY    = (yPrcBottom - yTop) / (maxPrice - minPrice);
            scaleYVol = maxVolume > 0 ? ((yPrcBottom - yTop) / 8d) / maxVolume : 0d;

            // Volume, Lots and Price
            x             = new int[chartBars];
            yOpen         = new int[chartBars];
            yHigh         = new int[chartBars];
            yLow          = new int[chartBars];
            yClose        = new int[chartBars];
            yVolume       = new int[chartBars];
            rectPosition  = new Rectangle[chartBars];
            brushPosition = new Brush[chartBars];

            int index = 0;

            for (int bar = firstBar; bar <= lastBar; bar++)
            {
                x[index]       = (bar - firstBar) * barPixels + xLeft;
                yOpen[index]   = (int)(yPrcBottom - (Data.Open[bar] - minPrice) * scaleY);
                yHigh[index]   = (int)(yPrcBottom - (Data.High[bar] - minPrice) * scaleY);
                yLow[index]    = (int)(yPrcBottom - (Data.Low[bar] - minPrice) * scaleY);
                yClose[index]  = (int)(yPrcBottom - (Data.Close[bar] - minPrice) * scaleY);
                yVolume[index] = (int)(yPrcBottom - Data.Volume[bar] * scaleYVol);

                // Draw position lots
                if (Backtester.IsPos(bar))
                {
                    int iPosHight = (int)(Math.Max(Backtester.SummaryLots(bar) * 2, 2));

                    int iPosY = yPrcBottom - iPosHight;

                    if (Backtester.SummaryDir(bar) == PosDirection.Long)
                    {   // Long
                        rectPosition[index]  = new Rectangle(x[index], iPosY, 1, iPosHight);
                        brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeLong);
                    }
                    else if (Backtester.SummaryDir(bar) == PosDirection.Short)
                    {   // Short
                        rectPosition[index]  = new Rectangle(x[index], iPosY, 1, iPosHight);
                        brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeShort);
                    }
                    else
                    {   // Close position
                        rectPosition[index]  = new Rectangle(x[index], iPosY - 2, 1, 2);
                        brushPosition[index] = new SolidBrush(LayoutColors.ColorTradeClose);
                    }
                }
                else
                {   // There is no position
                    rectPosition[index]  = Rectangle.Empty;
                    brushPosition[index] = new SolidBrush(LayoutColors.ColorChartBack);
                }
                index++;
            }

            // Indicators in the chart
            slots             = Data.Strategy.Slots;
            bIsSeparatedChart = new bool[slots];
            iComponentLenght  = new int[slots];
            chartType         = new IndChartType[slots][];
            chartLine         = new Point[slots][][];
            chartDot          = new Rectangle[slots][][];
            chartLevel        = new Rectangle[slots][][];
            chartValue        = new double[slots][][];
            chartPen          = new Pen[slots][][];
            chartBrush        = new Brush[slots][];
            for (int iSlot = 0; iSlot < slots; iSlot++)
            {
                bIsSeparatedChart[iSlot] = Data.Strategy.Slot[iSlot].SeparatedChart;
                int iLenght = Data.Strategy.Slot[iSlot].Component.Length;
                iComponentLenght[iSlot] = iLenght;
                chartType[iSlot]        = new IndChartType[iLenght];
                chartLine[iSlot]        = new Point[iLenght][];
                chartDot[iSlot]         = new Rectangle[iLenght][];
                chartLevel[iSlot]       = new Rectangle[iLenght][];
                chartValue[iSlot]       = new double[iLenght][];
                chartPen[iSlot]         = new Pen[iLenght][];
                chartBrush[iSlot]       = new Brush[iLenght];
            }

            for (int slot = 0; slot < slots; slot++)
            {
                if (bIsSeparatedChart[slot])
                {
                    continue;
                }

                for (int comp = 0; comp < iComponentLenght[slot]; comp++)
                {
                    chartType[slot][comp] = Data.Strategy.Slot[slot].Component[comp].ChartType;
                    if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.Line ||
                        Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.CloudUp ||
                        Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.CloudDown)
                    {   // Line
                        chartBrush[slot][comp] = new SolidBrush(Data.Strategy.Slot[slot].Component[comp].ChartColor);
                        chartLine[slot][comp]  = new Point[lastBar - firstBar + 1];
                        for (int bar = firstBar; bar <= lastBar; bar++)
                        {
                            double dValue = Data.Strategy.Slot[slot].Component[comp].Value[bar];
                            int    ix     = (bar - firstBar) * barPixels + xLeft;
                            int    iy     = (int)(yPrcBottom - (dValue - minPrice) * scaleY);

                            if (dValue == 0)
                            {
                                chartLine[slot][comp][bar - firstBar] = chartLine[slot][comp][Math.Max(bar - firstBar - 1, 0)];
                            }
                            else
                            {
                                chartLine[slot][comp][bar - firstBar] = new Point(ix, iy);
                            }
                        }
                    }
                    else if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.Dot)
                    {   // Dots
                        chartBrush[slot][comp] = new SolidBrush(Data.Strategy.Slot[slot].Component[comp].ChartColor);
                        chartDot[slot][comp]   = new Rectangle[lastBar - firstBar + 1];
                        for (int bar = firstBar; bar <= lastBar; bar++)
                        {
                            double dValue = Data.Strategy.Slot[slot].Component[comp].Value[bar];
                            int    ix     = (bar - firstBar) * barPixels + xLeft;
                            int    iy     = (int)(yPrcBottom - (dValue - minPrice) * scaleY);
                            chartDot[slot][comp][bar - firstBar] = new Rectangle(ix, iy, 1, 1);
                        }
                    }
                    else if (Data.Strategy.Slot[slot].Component[comp].ChartType == IndChartType.Level)
                    {   // Level
                        chartBrush[slot][comp] = new SolidBrush(Data.Strategy.Slot[slot].Component[comp].ChartColor);
                        chartLevel[slot][comp] = new Rectangle[lastBar - firstBar + 1];
                        for (int bar = firstBar; bar <= lastBar; bar++)
                        {
                            double dValue = Data.Strategy.Slot[slot].Component[comp].Value[bar];
                            int    ix     = (bar - firstBar) * barPixels + xLeft;
                            int    iy     = (int)(yPrcBottom - (dValue - minPrice) * scaleY);
                            chartLevel[slot][comp][bar - firstBar] = new Rectangle(ix, iy, barPixels, 1);
                        }
                    }
                }
            }

            // Separate indicators
            yIndTop    = new int[inds];
            yIndBottom = new int[inds];
            dMaxValue  = new double[inds];
            dMinValue  = new double[inds];
            dScale     = new double[inds];
            for (int ind = 0; ind < inds; ind++)
            {
                yIndTop[ind]    = yBottom - (ind + 1) * indHeight + 1;
                yIndBottom[ind] = yBottom - ind * indHeight - 1;
                dMaxValue[ind]  = double.MinValue;
                dMinValue[ind]  = double.MaxValue;
                int    iSlot = aiIndSlot[ind];
                double dValue;

                for (int iComp = 0; iComp < iComponentLenght[iSlot]; iComp++)
                {
                    if (Data.Strategy.Slot[iSlot].Component[iComp].ChartType != IndChartType.NoChart)
                    {
                        for (bar = Math.Max(firstBar, Data.Strategy.Slot[iSlot].Component[iComp].FirstBar); bar <= lastBar; bar++)
                        {
                            dValue = Data.Strategy.Slot[iSlot].Component[iComp].Value[bar];
                            if (dValue > dMaxValue[ind])
                            {
                                dMaxValue[ind] = dValue;
                            }
                            if (dValue < dMinValue[ind])
                            {
                                dMinValue[ind] = dValue;
                            }
                        }
                    }
                }

                dMaxValue[ind] = Math.Max(dMaxValue[ind], Data.Strategy.Slot[iSlot].MaxValue);
                dMinValue[ind] = Math.Min(dMinValue[ind], Data.Strategy.Slot[iSlot].MinValue);

                foreach (double dSpecVal in Data.Strategy.Slot[iSlot].SpecValue)
                {
                    if (dSpecVal == 0)
                    {
                        dMaxValue[ind] = Math.Max(dMaxValue[ind], 0);
                        dMinValue[ind] = Math.Min(dMinValue[ind], 0);
                    }
                }

                dScale[ind] = (yIndBottom[ind] - yIndTop[ind] - 2) / (Math.Max(dMaxValue[ind] - dMinValue[ind], 0.0001f));

                // Indicator chart
                for (int iComp = 0; iComp < Data.Strategy.Slot[iSlot].Component.Length; iComp++)
                {
                    chartType[iSlot][iComp] = Data.Strategy.Slot[iSlot].Component[iComp].ChartType;
                    if (Data.Strategy.Slot[iSlot].Component[iComp].ChartType == IndChartType.Line)
                    {   // Line
                        chartBrush[iSlot][iComp] = new SolidBrush(Data.Strategy.Slot[iSlot].Component[iComp].ChartColor);
                        chartLine[iSlot][iComp]  = new Point[lastBar - firstBar + 1];
                        for (bar = firstBar; bar <= lastBar; bar++)
                        {
                            dValue = Data.Strategy.Slot[iSlot].Component[iComp].Value[bar];
                            int ix = (bar - firstBar) * barPixels + xLeft;
                            int iy = (int)(yIndBottom[ind] - 1 - (dValue - dMinValue[ind]) * dScale[ind]);
                            chartLine[iSlot][iComp][bar - firstBar] = new Point(ix, iy);
                        }
                    }
                    else if (Data.Strategy.Slot[iSlot].Component[iComp].ChartType == IndChartType.Histogram)
                    {   // Histogram
                        chartValue[iSlot][iComp] = new double[lastBar - firstBar + 1];
                        chartPen[iSlot][iComp]   = new Pen[lastBar - firstBar + 1];
                        for (bar = firstBar; bar <= lastBar; bar++)
                        {
                            dValue = Data.Strategy.Slot[iSlot].Component[iComp].Value[bar];
                            chartValue[iSlot][iComp][bar - firstBar] = dValue;
                            if (dValue > Data.Strategy.Slot[iSlot].Component[iComp].Value[bar - 1])
                            {
                                chartPen[iSlot][iComp][bar - firstBar] = penGreen;
                            }
                            else
                            {
                                chartPen[iSlot][iComp][bar - firstBar] = penRed;
                            }
                        }
                    }
                }
            }
        }
示例#28
0
        /// <summary>
        /// Sets the chart parameters
        /// </summary>
        private void InitChart(int width, int height)
        {
            Chart = new Bitmap(width, height);

            if (!Data.IsData || !Data.IsResult || Data.Bars <= Data.FirstBar)
            {
                return;
            }

            const int border = 1;
            const int space  = 2;

            int maximum;
            int minimum;

            int firstBar   = Data.FirstBar;
            int bars       = Data.Bars;
            int chartBars  = Data.Bars - firstBar;
            int maxBalance = Configs.AccountInMoney ? (int)Backtester.MaxMoneyBalance : Backtester.MaxBalance;
            int minBalance = Configs.AccountInMoney ? (int)Backtester.MinMoneyBalance : Backtester.MinBalance;
            int maxEquity  = Configs.AccountInMoney ? (int)Backtester.MaxMoneyEquity : Backtester.MaxEquity;
            int minEquity  = Configs.AccountInMoney ? (int)Backtester.MinMoneyEquity : Backtester.MinEquity;

            if (Configs.AdditionalStatistics)
            {
                int maxLongBalance  = Configs.AccountInMoney ? (int)Backtester.MaxLongMoneyBalance : Backtester.MaxLongBalance;
                int minLongBalance  = Configs.AccountInMoney ? (int)Backtester.MinLongMoneyBalance : Backtester.MinLongBalance;
                int maxShortBalance = Configs.AccountInMoney ? (int)Backtester.MaxShortMoneyBalance : Backtester.MaxShortBalance;
                int minShortBalance = Configs.AccountInMoney ? (int)Backtester.MinShortMoneyBalance : Backtester.MinShortBalance;
                int maxLSBalance    = Math.Max(maxLongBalance, maxShortBalance);
                int minLSBalance    = Math.Min(minLongBalance, minShortBalance);

                maximum = Math.Max(Math.Max(maxBalance, maxEquity), maxLSBalance) + 1;
                minimum = Math.Min(Math.Min(minBalance, minEquity), minLSBalance) - 1;
            }
            else
            {
                maximum = Math.Max(maxBalance, maxEquity) + 1;
                minimum = Math.Min(minBalance, minEquity) - 1;
            }

            const int yTop    = border + space;
            int       yBottom = height - border - space;
            const int xLeft   = border;
            int       xRight  = width - border - space;
            float     xScale  = (xRight - xLeft) / (float)chartBars;
            float     yScale  = (yBottom - yTop) / (float)(maximum - minimum);

            var penBorder = new Pen(Data.GetGradientColor(LayoutColors.ColorCaptionBack, -LayoutColors.DepthCaption), border);

            var balancePoints      = new PointF[chartBars];
            var equityPoints       = new PointF[chartBars];
            var longBalancePoints  = new PointF[chartBars];
            var shortBalancePoints = new PointF[chartBars];

            int index = 0;

            for (int bar = firstBar; bar < bars; bar++)
            {
                balancePoints[index].X = xLeft + index * xScale;
                equityPoints[index].X  = xLeft + index * xScale;
                if (Configs.AccountInMoney)
                {
                    balancePoints[index].Y = (float)(yBottom - (Backtester.MoneyBalance(bar) - minimum) * yScale);
                    equityPoints[index].Y  = (float)(yBottom - (Backtester.MoneyEquity(bar) - minimum) * yScale);
                }
                else
                {
                    balancePoints[index].Y = yBottom - (Backtester.Balance(bar) - minimum) * yScale;
                    equityPoints[index].Y  = yBottom - (Backtester.Equity(bar) - minimum) * yScale;
                }

                if (Configs.AdditionalStatistics)
                {
                    longBalancePoints[index].X  = xLeft + index * xScale;
                    shortBalancePoints[index].X = xLeft + index * xScale;
                    if (Configs.AccountInMoney)
                    {
                        longBalancePoints[index].Y  = (float)(yBottom - (Backtester.LongMoneyBalance(bar) - minimum) * yScale);
                        shortBalancePoints[index].Y = (float)(yBottom - (Backtester.ShortMoneyBalance(bar) - minimum) * yScale);
                    }
                    else
                    {
                        longBalancePoints[index].Y  = yBottom - (Backtester.LongBalance(bar) - minimum) * yScale;
                        shortBalancePoints[index].Y = yBottom - (Backtester.ShortBalance(bar) - minimum) * yScale;
                    }
                }

                index++;
            }

            Graphics g = Graphics.FromImage(Chart);

            // Paints the background by gradient
            var rectField = new RectangleF(1, 1, width - 2, height - 2);

            g.FillRectangle(new SolidBrush(LayoutColors.ColorChartBack), rectField);

            // Border
            g.DrawRectangle(penBorder, 0, 0, width - 1, height - 1);

            // Equity line
            g.DrawLines(new Pen(LayoutColors.ColorChartEquityLine), equityPoints);

            // Draw Long and Short balance
            if (Configs.AdditionalStatistics)
            {
                g.DrawLines(new Pen(Color.Red), shortBalancePoints);
                g.DrawLines(new Pen(Color.Green), longBalancePoints);
            }

            // Draw the balance line
            g.DrawLines(new Pen(LayoutColors.ColorChartBalanceLine), balancePoints);
        }
示例#29
0
        /// <summary>
        /// Exports the bar summary
        /// </summary>
        public void ExportBarSummary()
        {
            string stage = String.Empty;

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

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

            sb.Append("Bar Numb\t");
            sb.Append("Date\t");
            sb.Append("Hour\t");
            sb.Append("Open\t");
            sb.Append("High\t");
            sb.Append("Low\t");
            sb.Append("Close\t");
            sb.Append("Volume\t");
            sb.Append("Direction\t");
            sb.Append("Lots\t");
            sb.Append("Transaction\t");
            sb.Append("Price\t");
            sb.Append("Profit Loss\t");
            sb.Append("Floating P/L\t");
            sb.Append("Spread\t");
            sb.Append("Rollover\t");
            sb.Append("Balance\t");
            sb.Append("Equity\t");
            sb.Append("Interpolation" + Environment.NewLine);

            for (int bar = 0; bar < Data.Bars; bar++)
            {
                sb.Append((bar + 1).ToString() + "\t");
                sb.Append(Data.Time[bar].ToString(sDF) + "\t");
                sb.Append(Data.Time[bar].ToString("HH:mm") + "\t");
                sb.Append(Data.Open[bar].ToString(FF) + "\t");
                sb.Append(Data.High[bar].ToString(FF) + "\t");
                sb.Append(Data.Low[bar].ToString(FF) + "\t");
                sb.Append(Data.Close[bar].ToString(FF) + "\t");
                sb.Append(Data.Volume[bar].ToString() + "\t");
                if (Backtester.IsPos(bar))
                {
                    sb.Append(Backtester.SummaryDir(bar).ToString() + "\t");
                    sb.Append(Backtester.SummaryLots(bar).ToString() + "\t");
                    sb.Append(Backtester.SummaryTrans(bar).ToString() + "\t");
                    sb.Append(Backtester.SummaryPrice(bar).ToString(FF) + "\t");
                    sb.Append(Backtester.ProfitLoss(bar).ToString() + "\t");
                    sb.Append(Backtester.FloatingPL(bar).ToString() + "\t");
                }
                else
                {
                    sb.Append("\t\t\t\t\t\t");
                }
                sb.Append(Backtester.ChargedSpread(bar).ToString() + "\t");
                sb.Append(Backtester.ChargedRollOver(bar).ToString() + "\t");
                sb.Append(Backtester.Balance(bar).ToString() + "\t");
                sb.Append(Backtester.Equity(bar).ToString() + "\t");
                sb.Append(Backtester.BackTestEval(bar) + "\t");
                sb.Append(Environment.NewLine);
            }

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

            SaveData(fileName);
            return;
        }
        /// <summary>
        /// Navigates to a bar.
        /// </summary>
        void Navigate(string sDir)
        {
            switch (sDir)
            {
            case "< !":
                for (int i = bar - 1; i >= Data.FirstBar; i--)
                {
                    if (Backtester.BackTestEval(i) == "Ambiguous")
                    {
                        bar = i;
                        break;
                    }
                }
                break;

            case "<":
                if (bar > Data.FirstBar)
                {
                    bar--;
                }
                break;

            case "! >":
                for (int i = bar + 1; i < Data.Bars; i++)
                {
                    if (Backtester.BackTestEval(i) == "Ambiguous")
                    {
                        bar = i;
                        break;
                    }
                }
                break;

            case ">":
                if (bar < Data.Bars - 1)
                {
                    bar++;
                }
                break;

            case "Go":
                bar = (int)nudGo.Value - 1;
                break;

            default:
                break;
            }

            SetBtnNavigate();

            barInfo = Language.T("Bar") + ": " + (bar + 1).ToString() +
                      " " + Data.Time[bar].ToString(Data.DF) +
                      " " + Data.Time[bar].ToString("HH:mm") + "; " +
                      Language.T("Interpolation method") + ": " +
                      Backtester.InterpolationMethodToString();

            Rectangle rectPnlChart = new Rectangle(border, infoRowHeight, pnlChart.ClientSize.Width - 2 * border, pnlChart.ClientSize.Height - infoRowHeight - border);

            pnlChart.Invalidate(rectPnlChart);

            Rectangle rectPnlInfo = new Rectangle(border, 2 * infoRowHeight, pnlInfo.ClientSize.Width - 2 * border, pnlInfo.ClientSize.Height - 2 * infoRowHeight - border);

            pnlInfo.Invalidate(rectPnlInfo);

            nudGo.Value = bar + 1;

            return;
        }