/// <summary>
        ///     Tests general parameters of a custom indicator.
        /// </summary>
        /// <param name="indicator">The indicator.</param>
        /// <param name="errorsList">List of the errors</param>
        /// <returns>True, if the test succeed.</returns>
        public static bool CustomIndicatorFastTest(Indicator indicator, out string errorsList)
        {
            bool isOk = true;

            var sb = new StringBuilder();

            sb.AppendLine("ERROR: Indicator test failed for '" + indicator.IndicatorName + "' indicator.");

            // Tests the IndicatorName property.
            if (string.IsNullOrEmpty(indicator.IndicatorName))
            {
                sb.AppendLine("\tThe property 'IndicatorName' is not set.");
                isOk = false;
            }

            // Tests the PossibleSlots property.
            if (!indicator.TestPossibleSlot(SlotTypes.Open) &&
                !indicator.TestPossibleSlot(SlotTypes.OpenFilter) &&
                !indicator.TestPossibleSlot(SlotTypes.Close) &&
                !indicator.TestPossibleSlot(SlotTypes.CloseFilter))
            {
                sb.AppendLine("\tThe property 'PossibleSlots' is not set.");
                isOk = false;
            }

            // Tests the CustomIndicator property.
            if (!indicator.CustomIndicator)
            {
                sb.AppendLine("\tThe indicator '" + indicator.IndicatorName +
                              "' is not marked as custom. Set CustomIndicator = true;");
                isOk = false;
            }

            // Tests the SeparatedChartMaxValue properties.
            if (!indicator.SeparatedChart && Math.Abs(indicator.SeparatedChartMaxValue - double.MinValue) > 0.000001)
            {
                sb.AppendLine("\tSet SeparatedChart = true; or remove the property: SeparatedChartMaxValue = " +
                              indicator.SeparatedChartMaxValue);
                isOk = false;
            }

            // Tests the SeparatedChartMinValue properties.
            if (!indicator.SeparatedChart && Math.Abs(indicator.SeparatedChartMinValue - double.MaxValue) > 0.000001)
            {
                sb.AppendLine("\tSet SeparatedChart = true; or remove the property: SeparatedChartMinValue = " +
                              indicator.SeparatedChartMinValue);
                isOk = false;
            }

            // Tests the SpecialValues properties.
            if (!indicator.SeparatedChart && indicator.SpecialValues.Length > 0)
            {
                sb.AppendLine("\tSet SeparatedChart = true; or remove the property SpecialValues");
                isOk = false;
            }

            // Tests the IndParam properties.
            if (indicator.IndParam == null)
            {
                sb.AppendLine("\tThe property IndParam is not set. Set IndParam = new IndicatorParam();");
                isOk = false;
            }

            // Tests the IndParam.IndicatorName properties.
            if (indicator.IndParam != null && indicator.IndParam.IndicatorName != indicator.IndicatorName)
            {
                sb.AppendLine(
                    "\tThe property IndParam.IndicatorName is not set. Set IndParam.IndicatorName = IndicatorName;");
                isOk = false;
            }

            // Tests the IndParam.SlotType properties.
            if (indicator.IndParam != null && indicator.IndParam.SlotType != SlotTypes.NotDefined)
            {
                sb.AppendLine("\tThe property IndParam.SlotType is not set. Set IndParam.SlotType = slotType;");
                isOk = false;
            }

            // Tests the IndParam.ListParam properties.
            for (int param = 0; param < indicator.IndParam.ListParam.Length; param++)
            {
                ListParam listParam = indicator.IndParam.ListParam[param];
                if (!listParam.Enabled)
                    continue;

                if (string.IsNullOrEmpty(listParam.Caption))
                {
                    sb.AppendLine("\tThe property IndParam.ListParam[" + param + "].Caption is not set.");
                    isOk = false;
                }

                if (listParam.ItemList.Length == 0)
                {
                    sb.AppendLine("\tThe property IndParam.ListParam[" + param + "].ItemList is not set.");
                    isOk = false;
                }

                if (listParam.ItemList[listParam.Index] != listParam.Text)
                {
                    sb.AppendLine("\tThe property IndParam.ListParam[" + param + "].Text is wrong." +
                                  " Set " + "IndParam.ListParam[" + param + "].Text = IndParam.ListParam[" + param +
                                  "].ItemList[IndParam.ListParam[" + param + "].Index];");
                    isOk = false;
                }

                if (string.IsNullOrEmpty(listParam.ToolTip))
                {
                    sb.AppendLine("\tThe property IndParam.ListParam[" + param + "].ToolTip is not set.");
                    isOk = false;
                }
            }

            // Tests the IndParam.NumParam properties.
            for (int param = 0; param < indicator.IndParam.NumParam.Length; param++)
            {
                NumericParam numParam = indicator.IndParam.NumParam[param];
                if (!numParam.Enabled)
                    continue;

                if (string.IsNullOrEmpty(numParam.Caption))
                {
                    sb.AppendLine("\tThe property IndParam.NumParam[" + param + "].Caption is not set.");
                    isOk = false;
                }

                double value = numParam.Value;
                double min = numParam.Min;
                double max = numParam.Max;
                double point = numParam.Point;

                if (min > max)
                {
                    sb.AppendLine("\tIndParam.NumParam[" + param + "].Min > IndParam.NumParam[" + param + "].Max.");
                    isOk = false;
                }

                if (value > max)
                {
                    sb.AppendLine("\tIndParam.NumParam[" + param + "].Value > IndParam.NumParam[" + param + "].Max.");
                    isOk = false;
                }

                if (value < min)
                {
                    sb.AppendLine("\tIndParam.NumParam[" + param + "].Value < IndParam.NumParam[" + param + "].Min.");
                    isOk = false;
                }

                if (point < 0)
                {
                    sb.AppendLine("\tIndParam.NumParam[" + param + "].Point cannot be < 0");
                    isOk = false;
                }

                if (point > 6)
                {
                    sb.AppendLine("\tIndParam.NumParam[" + param + "].Point cannot be > 6");
                    isOk = false;
                }

                if (string.IsNullOrEmpty(numParam.ToolTip))
                {
                    sb.AppendLine("\tThe property IndParam.NumParam[" + param + "].ToolTip is not set.");
                    isOk = false;
                }
            }

            // Tests the IndParam.CheckParam properties.
            for (int param = 0; param < indicator.IndParam.CheckParam.Length; param++)
            {
                CheckParam checkParam = indicator.IndParam.CheckParam[param];
                if (!checkParam.Enabled)
                    continue;

                if (string.IsNullOrEmpty(checkParam.Caption))
                {
                    sb.AppendLine("\tThe property IndParam.CheckParam[" + param + "].Caption is not set.");
                    isOk = false;
                }

                if (string.IsNullOrEmpty(checkParam.ToolTip))
                {
                    sb.AppendLine("\tThe property IndParam.CheckParam[" + param + "].ToolTip is not set.");
                    isOk = false;
                }
            }

            try
            {
                indicator.Calculate(Data.DataSet);
            }
            catch (Exception exc)
            {
                sb.AppendLine("\tError when executing Calculate(). " + exc.Message);
                isOk = false;
            }

            try
            {
                indicator.SetDescription();
            }
            catch (Exception exc)
            {
                sb.AppendLine("\tError when executing SetDescription(SlotTypes.NotDefined). " + exc.Message);
                isOk = false;
            }

            try
            {
                string description = indicator.ToString();
                Console.WriteLine(description);
            }
            catch (Exception exc)
            {
                sb.AppendLine("\tError when executing ToString(). " + exc.Message);
                isOk = false;
            }

            errorsList = isOk ? string.Empty : sb.ToString();

            return isOk;
        }
        /// <summary>
        ///     Sets the indicator overview and warning message.
        /// </summary>
        private void SetIndicatorNotification(Indicator indicator)
        {
            // Warning message.
            warningMessage = indicator.WarningMessage;
            LblIndicatorWarning.Visible = !string.IsNullOrEmpty(warningMessage);

            // Set description.
            indicator.SetDescription();
            description = "Long position:" + Environment.NewLine;
            if (SlotType == SlotTypes.Open)
            {
                description += "   Open a long position " + indicator.EntryPointLongDescription + "." +
                               Environment.NewLine + Environment.NewLine;
                description += "Short position:" + Environment.NewLine;
                description += "   Open a short position " + indicator.EntryPointShortDescription + ".";
            }
            else if (SlotType == SlotTypes.OpenFilter)
            {
                description += "   Open a long position when " + indicator.EntryFilterLongDescription + "." +
                               Environment.NewLine + Environment.NewLine;
                description += "Short position:" + Environment.NewLine;
                description += "   Open a short position when " + indicator.EntryFilterShortDescription + ".";
            }
            else if (SlotType == SlotTypes.Close)
            {
                description += "   Close a long position " + indicator.ExitPointLongDescription + "." +
                               Environment.NewLine + Environment.NewLine;
                description += "Short position:" + Environment.NewLine;
                description += "   Close a short position " + indicator.ExitPointShortDescription + ".";
            }
            else
            {
                description += "   Close a long position when " + indicator.ExitFilterLongDescription + "." +
                               Environment.NewLine + Environment.NewLine;
                description += "Short position:" + Environment.NewLine;
                description += "   Close a short position when " + indicator.ExitFilterShortDescription + ".";
            }

            for (int i = 0; i < 2; i++)
                if (indicator.IndParam.CheckParam[i].Caption == "Use previous bar value")
                    description += Environment.NewLine + "-------------" + Environment.NewLine + "* Use the value of " +
                                   indicator.IndicatorName + " from the previous bar.";

            toolTip.SetToolTip(LblIndicatorInfo, description);
        }
        /// <summary>
        ///     Calculates an indicator and returns OK status.
        /// </summary>
        private bool CalculateIndicator(SlotTypes type, Indicator indicator)
        {
            bool okStatus;

            try
            {
                indicator.Calculate(Data.DataSet);

                okStatus = true;
            }
            catch (Exception exception)
            {
                string request = "Please report this error in the support forum!";
                if (indicator.CustomIndicator)
                    request = "Please report this error to the author of the indicator!<br />" +
                              "You may remove this indicator from the Custom Indicators folder.";

                string text =
                    "<h1>Error: " + exception.Message + "</h1>" +
                    "<p>Slot type: <strong>" + type + "</strong><br />" +
                    "Indicator: <strong>" + indicator + "</strong></p>" +
                    "<p>" + request + "</p>";

                const string caption = "Indicator Calculation Error";
                var msgBox = new FancyMessageBox(text, caption) {BoxWidth = 450, BoxHeight = 250};
                msgBox.Show();

                okStatus = false;
            }

            return okStatus;
        }
        /// <summary>
        ///     Checks and stores the indicator.
        /// </summary>
        private bool IntegrateIndicator(string filePath, out string errorMessages, Indicator newIndicator)
        {
            errorMessages = string.Empty;

            // Check for a repeated indicator name among the custom indicators
            foreach (Indicator indicator in CustomIndicatorsList)
                if (indicator.IndicatorName == newIndicator.IndicatorName)
                {
                    errorMessages = string.Format("Indicator '{0}' found in [{1}] is already loaded.",
                                                  newIndicator.IndicatorName,
                                                  Path.GetFileName(filePath));
                    return false;
                }

            // Check for a repeated indicator name among the original indicators
            foreach (string indicatorName in IndicatorManager.OriginalIndicatorNames)
                if (indicatorName == newIndicator.IndicatorName)
                    newIndicator.OverrideMainIndicator = true;

            // Test the new custom indicator
            string errorTestIndicator;
            if (!IndicatorTester.CustomIndicatorFastTest(newIndicator, out errorTestIndicator))
            {
                errorMessages = errorTestIndicator;
                return false;
            }

            // Adds the custom indicator to the list
            CustomIndicatorsList.Add(newIndicator);

            return true;
        }
        /// <summary>
        ///     Calculates an indicator and returns OK status.
        /// </summary>
        private bool CalculateIndicator(SlotTypes slotType, Indicator indicator)
        {
#if !DEBUG
            try
            {
#endif
                indicator.Calculate(Data.DataSet);
                totalCalculations++;
                return true;
#if !DEBUG
            }
            catch (Exception exception)
            {
                string message = "Please report this error in the support forum!";
                if (indicator.CustomIndicator)
                    message = "Please report this error to the author of the indicator!<br />" +
                              "You may remove this indicator from the Custom Indicators folder.";

                string text =
                    "<h1>Error: " + exception.Message + "</h1>" +
                    "<p>" +
                    "Slot type: <strong>" + slotType + "</strong><br />" +
                    "Indicator: <strong>" + indicator + "</strong>" +
                    "</p>" +
                    "<p>" +
                    message +
                    "</p>";

                const string caption = "Indicator Calculation Error";
                ReportIndicatorError(text, caption);
                indicatorBlackList.Add(indicator.IndicatorName);
                return false;
            }
#endif
        }