/// <summary>
        /// Recalculate all the indicator slots
        /// </summary>
        private void RecalculateSlots()
        {
            foreach (IndicatorSlot indSlot in Data.Strategy.Slot)
            {
                string    indicatorName = indSlot.IndicatorName;
                SlotTypes slotType      = indSlot.SlotType;
                Indicator indicator     = IndicatorStore.ConstructIndicator(indicatorName, slotType);

                indicator.IndParam = indSlot.IndParam;
                indicator.Calculate(slotType);

                indSlot.Component = indicator.Component;
                indSlot.IsDefined = true;
            }

            // Searches the indicators' components to determine the Data.FirstBar
            Data.FirstBar = Data.Strategy.SetFirstBar();
        }
        /// <summary>
        /// Calculates the indicator in the designated slot.
        /// </summary>
        private void CalculateIndicator(int slot)
        {
            IndicatorParam ip = Data.Strategy.Slot[slot].IndParam;

            Indicator indicator = IndicatorStore.ConstructIndicator(ip.IndicatorName, ip.SlotType);

            // List parameters
            for (int i = 0; i < 5; i++)
            {
                indicator.IndParam.ListParam[i].Index   = ip.ListParam[i].Index;
                indicator.IndParam.ListParam[i].Text    = ip.ListParam[i].Text;
                indicator.IndParam.ListParam[i].Enabled = ip.ListParam[i].Enabled;
            }

            // Numeric parameters
            for (int i = 0; i < 6; i++)
            {
                indicator.IndParam.NumParam[i].Value   = ip.NumParam[i].Value;
                indicator.IndParam.NumParam[i].Enabled = ip.NumParam[i].Enabled;
            }

            // Check parameters
            for (int i = 0; i < 2; i++)
            {
                indicator.IndParam.CheckParam[i].Checked = ip.CheckParam[i].Checked;
                indicator.IndParam.CheckParam[i].Enabled = ip.CheckParam[i].Enabled;
            }

            indicator.Calculate(ip.SlotType);

            // Sets Data.Strategy
            Data.Strategy.Slot[slot].IndicatorName  = indicator.IndicatorName;
            Data.Strategy.Slot[slot].IndParam       = indicator.IndParam;
            Data.Strategy.Slot[slot].Component      = indicator.Component;
            Data.Strategy.Slot[slot].SeparatedChart = indicator.SeparatedChart;
            Data.Strategy.Slot[slot].SpecValue      = indicator.SpecialValues;
            Data.Strategy.Slot[slot].MinValue       = indicator.SeparatedChartMinValue;
            Data.Strategy.Slot[slot].MaxValue       = indicator.SeparatedChartMaxValue;
            Data.Strategy.Slot[slot].IsDefined      = true;

            // Searches the indicators' components to determine the Data.FirstBar
            Data.FirstBar = Data.Strategy.SetFirstBar();
        }
        /// <summary>
        /// Calculate the indicator in the designated slot
        /// </summary>
        private void GenerateIndicatorParameters(int slot)
        {
            string    indicatorName = Data.Strategy.Slot[slot].IndicatorName;
            SlotTypes slotType      = Data.Strategy.GetSlotType(slot);
            Indicator indicator     = IndicatorStore.ConstructIndicator(indicatorName, slotType);

            // List parameters
            foreach (ListParam list in indicator.IndParam.ListParam)
            {
                if (list.Enabled)
                {
                    do
                    {
                        list.Index = _random.Next(list.ItemList.Length);
                        list.Text  = list.ItemList[list.Index];
                    } while (list.Caption == "Base price" && (list.Text == "High" || list.Text == "Low"));
                }
            }

            int firstBar;

            do
            {
                // Numeric parameters
                foreach (NumericParam num in indicator.IndParam.NumParam)
                {
                    if (num.Enabled)
                    {
                        if (num.Caption == "Level" && !indicator.IndParam.ListParam[0].Text.Contains("Level"))
                        {
                            continue;
                        }
                        if (!ChbUseDefaultIndicatorValues.Checked)
                        {
                            double step    = Math.Pow(10, -num.Point);
                            double minimum = num.Min;
                            double maximum = num.Max;

                            if (maximum > Data.Bars / 3.0 && ((num.Caption.ToLower()).Contains("period") ||
                                                              (num.Caption.ToLower()).Contains("shift") ||
                                                              (num.ToolTip.ToLower()).Contains("period")))
                            {
                                maximum = Math.Max(minimum + step, Data.Bars / 3.0);
                            }

                            double value = minimum + step * _random.Next((int)((maximum - minimum) / step));
                            num.Value = Math.Round(value, num.Point);
                        }
                    }
                }

                if (!CalculateIndicator(slotType, indicator))
                {
                    return;
                }

                firstBar = 0;
                foreach (IndicatorComp comp in indicator.Component)
                {
                    if (comp.FirstBar > firstBar)
                    {
                        firstBar = comp.FirstBar;
                    }
                }
            } while (firstBar > Data.Bars - 10);

            //Set the Data.Strategy
            IndicatorSlot indSlot = Data.Strategy.Slot[slot];

            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;
        }
        /// <summary>
        /// Normalizes the numeric parameters.
        /// </summary>
        void ReduceTheValuesOfNumericParams(BackgroundWorker worker)
        {
            for (int slot = 0; slot < Data.Strategy.Slots; slot++)
            {
                if (_bestBalance < 500)
                {
                    break;
                }
                if (Data.Strategy.Slot[slot].SlotStatus == StrategySlotStatus.Locked)
                {
                    continue;
                }

                // Numeric parameters
                for (int param = 0; param < 6; param++)
                {
                    if (!Data.Strategy.Slot[slot].IndParam.NumParam[param].Enabled)
                    {
                        continue;
                    }

                    bool isDoAgain;
                    do
                    {
                        if (worker.CancellationPending)
                        {
                            break;
                        }

                        IndicatorSlot indSlot = Data.Strategy.Slot[slot];
                        NumericParam  num     = Data.Strategy.Slot[slot].IndParam.NumParam[param];
                        if (num.Caption == "Level" && !indSlot.IndParam.ListParam[0].Text.Contains("Level"))
                        {
                            break;
                        }

                        Indicator indicator    = IndicatorStore.ConstructIndicator(indSlot.IndicatorName, indSlot.SlotType);
                        double    defaultValue = indicator.IndParam.NumParam[param].Value;

                        double numOldValue = num.Value;
                        if (Math.Abs(num.Value - defaultValue) < 0.00001)
                        {
                            break;
                        }

                        double value = num.Value;
                        double delta = (defaultValue - value) * 3 / 4;
                        value += delta;
                        value  = Math.Round(value, num.Point);

                        if (Math.Abs(value - numOldValue) < value)
                        {
                            break;
                        }

                        num.Value = value;

                        RecalculateSlots();
                        isDoAgain = CalculateTheResult(true);
                        if (!isDoAgain)
                        {
                            RestoreFromBest();
                        }
                    } while (isDoAgain);
                }
            }
        }