/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using QuantConnect.Data.Market; using System; namespace QuantConnect.Indicators { /// /// The Aroon Oscillator is the difference between AroonUp and AroonDown. The value of this /// indicator fluctuates between -100 and +100. An upward trend bias is present when the oscillator /// is positive, and a negative trend bias is present when the oscillator is negative. AroonUp/Down /// values over 75 identify strong trends in their respective direction. /// public class AroonOscillator : BarIndicator, IIndicatorWarmUpPeriodProvider { /// /// Gets the AroonUp indicator /// public IndicatorBase AroonUp { get; } /// /// Gets the AroonDown indicator /// public IndicatorBase AroonDown { get; } /// /// Gets a flag indicating when this indicator is ready and fully initialized /// public override bool IsReady => AroonUp.IsReady && AroonDown.IsReady; /// /// Required period, in data points, for the indicator to be ready and fully initialized. /// public int WarmUpPeriod { get; } /// /// Creates a new AroonOscillator from the specified up/down periods. /// /// The lookback period to determine the highest high for the AroonDown /// The lookback period to determine the lowest low for the AroonUp public AroonOscillator(int upPeriod, int downPeriod) : this($"AROON({upPeriod},{downPeriod})", upPeriod, downPeriod) { } /// /// Creates a new AroonOscillator from the specified up/down periods. /// /// The name of this indicator /// The lookback period to determine the highest high for the AroonDown /// The lookback period to determine the lowest low for the AroonUp public AroonOscillator(string name, int upPeriod, int downPeriod) : base(name) { var max = new Maximum(name + "_Max", upPeriod + 1); AroonUp = new FunctionalIndicator(name + "_AroonUp", input => ComputeAroonUp(upPeriod, max, input), aroonUp => max.IsReady, () => max.Reset() ); var min = new Minimum(name + "_Min", downPeriod + 1); AroonDown = new FunctionalIndicator(name + "_AroonDown", input => ComputeAroonDown(downPeriod, min, input), aroonDown => min.IsReady, () => min.Reset() ); WarmUpPeriod = 1 + Math.Max(upPeriod, downPeriod); } /// /// Computes the next value of this indicator from the given state /// /// The input given to the indicator /// A new value for this indicator protected override decimal ComputeNextValue(IBaseDataBar input) { AroonUp.Update(input.EndTime, input.High); AroonDown.Update(input.EndTime, input.Low); return AroonUp.Current.Value - AroonDown.Current.Value; } /// /// AroonUp = 100 * (period - {periods since max})/period /// /// The AroonUp period /// A Maximum indicator used to compute periods since max /// The next input data /// The AroonUp value private static decimal ComputeAroonUp(int upPeriod, Maximum max, IndicatorDataPoint input) { max.Update(input); return 100m * (upPeriod - max.PeriodsSinceMaximum) / upPeriod; } /// /// AroonDown = 100 * (period - {periods since min})/period /// /// The AroonDown period /// A Minimum indicator used to compute periods since min /// The next input data /// The AroonDown value private static decimal ComputeAroonDown(int downPeriod, Minimum min, IndicatorDataPoint input) { min.Update(input); return 100m * (downPeriod - min.PeriodsSinceMinimum) / downPeriod; } /// /// Resets this indicator and both sub-indicators (AroonUp and AroonDown) /// public override void Reset() { AroonUp.Reset(); AroonDown.Reset(); base.Reset(); } } }