//**************************************************************************************

    /// <summary>
    /// Starts simulation starting from the end of historical candlesticksm and up to prediction duration.
    /// </summary>
    private static void Start(CandlestickCollection iHistoricalCandlesticks, CandlestickCollection iCandlesticks, List <WekaClassifier> iClassifiers, int iPredictionDuration)
    {
        var index        = new CandlestickIndexCollection();
        var candlesticks = iCandlesticks;

        var classfiers      = WekaClassifier.SplitByProfitTime(iClassifiers);
        var initialCount    = candlesticks[WekaClassifier.kTrainingPeriod].Count;
        var startIndex      = Math.Max(initialCount - classfiers.Keys.Max() - 1, 1);
        var endIndex        = initialCount + iPredictionDuration - 1;
        var priceDiffStdDev = Statistics.StandardDeviation(Statistics.CalculateDifferences(iHistoricalCandlesticks[WekaClassifier.kTrainingPeriod].Select(x => x.MedianPrice).ToArray()));

        var wfp    = new SortedDictionary <int, List <float> >();
        var weight = new List <float>(classfiers.Count);

        foreach (KeyValuePair <int, List <WekaClassifier> > pair in classfiers)
        {
            wfp.Add(pair.Key, new List <float>());
            var precision = WekaClassifier.GetAveragePrecision(pair.Value);
            weight.Add((float)(Math.Pow(precision, 6) / Math.Pow(pair.Value[0].GetProfitsStdDev(), 6.0f)));
        }

        weight = Statistics.Normalize(weight.ToArray()).ToList();

        for (int i = startIndex; i <= endIndex; i++)
        {
            // Update indexes
            for (int k = (int)WekaClassifier.kTrainingPeriod; k >= 0; k--)
            {
                index[k] = Math.Max(0, Math.Min(candlesticks[k].Count - 1, Candlestick.FindIndex(candlesticks[k], candlesticks[WekaClassifier.kTrainingPeriod][i].StartTime, index[k]) - 1));
            }

            // Extract current price
            var p = candlesticks[WekaClassifier.kTrainingPeriod][i].MedianPrice;

            // Calculate WFP
            foreach (KeyValuePair <int, List <WekaClassifier> > pair in classfiers)
            {
                if (i >= initialCount - pair.Key - 1)
                {
                    var predictionsNow = WekaClassifier.PredictFP(pair.Value, p, candlesticks, index);
                    var wfpNow         = WekaClassifier.FPToWFP(pair.Value, predictionsNow);
                    wfp[pair.Key].Add(wfpNow);
                }
            }

            // Future
            if (i + 1 >= initialCount)
            {
                var lastCandle = candlesticks[WekaClassifier.kTrainingPeriod][candlesticks[WekaClassifier.kTrainingPeriod].Count - 1];

                var estimatedPrices = new List <float>(classfiers.Count);
                foreach (KeyValuePair <int, List <WekaClassifier> > pair in classfiers)
                {
                    estimatedPrices.Add(EstimatePrice(pair.Key, wfp[pair.Key], candlesticks[WekaClassifier.kTrainingPeriod]));
                }

                var targetPrice = Statistics.WeightedArithmeticMean(estimatedPrices.ToArray(), weight.ToArray());

                targetPrice = Statistics.Clamp(targetPrice, lastCandle.MedianPrice * (1.0f - 3.0f * priceDiffStdDev), lastCandle.MedianPrice * (1.0f + 3.0f * priceDiffStdDev));

                var candle = new Candlestick(lastCandle.EndTime, lastCandle.EndTime + 86400000 / (ulong)Candlestick.PeriodToDaily(Candlestick.Period.H1), lastCandle.ClosePrice, targetPrice, Math.Max(lastCandle.ClosePrice, targetPrice), Math.Min(lastCandle.ClosePrice, targetPrice), targetPrice);

                candlesticks.Add(candle, WekaClassifier.kTrainingPeriod);
            }
        }
    }