/// <summary>
        /// The Ultimate Oscillator is the weighted sum of three oscillators of different time periods. The typical time periods are 7, 14 and 28. The values of the Ultimate Oscillator range from zero to 100. Values over 70 indicate overbought conditions, and values under 30 indicate oversold conditions. Also look for agreement/divergence with the price to confirm a trend or signal the end of a trend.
        /// </summary>
        /// <returns></returns>
        public UltimateOscillator UltimateOscillator(Data.IDataSeries input, int fast, int intermediate, int slow)
        {
            if (cacheUltimateOscillator != null)
            {
                for (int idx = 0; idx < cacheUltimateOscillator.Length; idx++)
                {
                    if (cacheUltimateOscillator[idx].Fast == fast && cacheUltimateOscillator[idx].Intermediate == intermediate && cacheUltimateOscillator[idx].Slow == slow && cacheUltimateOscillator[idx].EqualsInput(input))
                    {
                        return(cacheUltimateOscillator[idx]);
                    }
                }
            }

            lock (checkUltimateOscillator)
            {
                checkUltimateOscillator.Fast = fast;
                fast = checkUltimateOscillator.Fast;
                checkUltimateOscillator.Intermediate = intermediate;
                intermediate = checkUltimateOscillator.Intermediate;
                checkUltimateOscillator.Slow = slow;
                slow = checkUltimateOscillator.Slow;

                if (cacheUltimateOscillator != null)
                {
                    for (int idx = 0; idx < cacheUltimateOscillator.Length; idx++)
                    {
                        if (cacheUltimateOscillator[idx].Fast == fast && cacheUltimateOscillator[idx].Intermediate == intermediate && cacheUltimateOscillator[idx].Slow == slow && cacheUltimateOscillator[idx].EqualsInput(input))
                        {
                            return(cacheUltimateOscillator[idx]);
                        }
                    }
                }

                UltimateOscillator indicator = new UltimateOscillator();
                indicator.BarsRequired        = BarsRequired;
                indicator.CalculateOnBarClose = CalculateOnBarClose;
#if NT7
                indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256;
                indicator.MaximumBarsLookBack         = MaximumBarsLookBack;
#endif
                indicator.Input        = input;
                indicator.Fast         = fast;
                indicator.Intermediate = intermediate;
                indicator.Slow         = slow;
                Indicators.Add(indicator);
                indicator.SetUp();

                UltimateOscillator[] tmp = new UltimateOscillator[cacheUltimateOscillator == null ? 1 : cacheUltimateOscillator.Length + 1];
                if (cacheUltimateOscillator != null)
                {
                    cacheUltimateOscillator.CopyTo(tmp, 0);
                }
                tmp[tmp.Length - 1]     = indicator;
                cacheUltimateOscillator = tmp;
                return(indicator);
            }
        }
        /// <summary>
        /// The Ultimate Oscillator is the weighted sum of three oscillators of different time periods. The typical time periods are 7, 14 and 28. The values of the Ultimate Oscillator range from zero to 100. Values over 70 indicate overbought conditions, and values under 30 indicate oversold conditions. Also look for agreement/divergence with the price to confirm a trend or signal the end of a trend.
        /// </summary>
        /// <returns></returns>
        public UltimateOscillator UltimateOscillator(Data.IDataSeries input, int fast, int intermediate, int slow)
        {
            if (cacheUltimateOscillator != null)
                for (int idx = 0; idx < cacheUltimateOscillator.Length; idx++)
                    if (cacheUltimateOscillator[idx].Fast == fast && cacheUltimateOscillator[idx].Intermediate == intermediate && cacheUltimateOscillator[idx].Slow == slow && cacheUltimateOscillator[idx].EqualsInput(input))
                        return cacheUltimateOscillator[idx];

            lock (checkUltimateOscillator)
            {
                checkUltimateOscillator.Fast = fast;
                fast = checkUltimateOscillator.Fast;
                checkUltimateOscillator.Intermediate = intermediate;
                intermediate = checkUltimateOscillator.Intermediate;
                checkUltimateOscillator.Slow = slow;
                slow = checkUltimateOscillator.Slow;

                if (cacheUltimateOscillator != null)
                    for (int idx = 0; idx < cacheUltimateOscillator.Length; idx++)
                        if (cacheUltimateOscillator[idx].Fast == fast && cacheUltimateOscillator[idx].Intermediate == intermediate && cacheUltimateOscillator[idx].Slow == slow && cacheUltimateOscillator[idx].EqualsInput(input))
                            return cacheUltimateOscillator[idx];

                UltimateOscillator indicator = new UltimateOscillator();
                indicator.BarsRequired = BarsRequired;
                indicator.CalculateOnBarClose = CalculateOnBarClose;
#if NT7
                indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256;
                indicator.MaximumBarsLookBack = MaximumBarsLookBack;
#endif
                indicator.Input = input;
                indicator.Fast = fast;
                indicator.Intermediate = intermediate;
                indicator.Slow = slow;
                Indicators.Add(indicator);
                indicator.SetUp();

                UltimateOscillator[] tmp = new UltimateOscillator[cacheUltimateOscillator == null ? 1 : cacheUltimateOscillator.Length + 1];
                if (cacheUltimateOscillator != null)
                    cacheUltimateOscillator.CopyTo(tmp, 0);
                tmp[tmp.Length - 1] = indicator;
                cacheUltimateOscillator = tmp;
                return indicator;
            }
        }