/* * 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; namespace QuantConnect.Indicators { /// /// Super trend indicator. /// Formula can be found here via the excel file: /// https://tradingtuitions.com/supertrend-indicator-excel-sheet-with-realtime-buy-sell-signals/ /// public class SuperTrend : BarIndicator, IIndicatorWarmUpPeriodProvider { private readonly decimal _multiplier; private decimal _superTrend; private decimal _currentClose; private decimal _previousTrailingUpperBand; private decimal _previousTrailingLowerBand; private decimal _previousClose; private decimal _prevSuper; private readonly int _period; /// /// Average true range indicator used to calculate super trend's basic upper and lower bands /// private readonly AverageTrueRange _averageTrueRange; /// /// Basic Upper Band /// public decimal BasicUpperBand { get; private set; } /// /// Basic Lower band /// public decimal BasicLowerBand { get; private set; } /// /// Current Trailing Upper Band /// public decimal CurrentTrailingUpperBand { get; private set; } /// /// Current Trailing Lower Band /// public decimal CurrentTrailingLowerBand { get; private set; } /// /// Gets a flag indicating when this indicator is ready and fully initialized /// public override bool IsReady => _averageTrueRange.IsReady; /// /// Required period, in data points, for the indicator to be ready and fully initialized. /// public int WarmUpPeriod => _period; /// /// Creates a new SuperTrend indicator using the specified name, period, multiplier and moving average type /// /// The name of this indicator /// The smoothing period used by average true range /// The coefficient used in calculations of basic upper and lower bands /// The type of smoothing used to smooth the true range values public SuperTrend(string name, int period, decimal multiplier, MovingAverageType movingAverageType = MovingAverageType.Wilders) : base(name) { _averageTrueRange = new AverageTrueRange(period, movingAverageType); _multiplier = multiplier; _period = period; _prevSuper = -1; } /// /// Creates a new SuperTrend indicator using the specified period, multiplier and moving average type /// /// The smoothing period used in average true range /// The coefficient used in calculations of basic upper and lower bands /// The type of smoothing used to smooth the true range values public SuperTrend(int period, decimal multiplier, MovingAverageType movingAverageType = MovingAverageType.Wilders) : this($"SuperTrend({period},{multiplier})", period, multiplier, movingAverageType) { } /// /// 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) { if (!_averageTrueRange.Update(input)) { _previousClose = input.Close; return 0m; } _currentClose = input.Close; BasicLowerBand = ((input.High + input.Low) / 2) - (_multiplier * _averageTrueRange.Current.Value); BasicUpperBand = ((input.High + input.Low) / 2) + (_multiplier * _averageTrueRange.Current.Value); CurrentTrailingLowerBand = ((BasicLowerBand > _previousTrailingLowerBand) || (_previousClose < _previousTrailingLowerBand)) ? BasicLowerBand : _previousTrailingLowerBand; CurrentTrailingUpperBand = ((BasicUpperBand < _previousTrailingUpperBand) || (_previousClose > _previousTrailingUpperBand)) ? BasicUpperBand : _previousTrailingUpperBand; if ((_prevSuper == -1) || (_prevSuper == _previousTrailingUpperBand)) { _superTrend = (_currentClose <= CurrentTrailingUpperBand) ? CurrentTrailingUpperBand : CurrentTrailingLowerBand; } else if (_prevSuper == _previousTrailingLowerBand) { _superTrend = (_currentClose >= CurrentTrailingLowerBand) ? CurrentTrailingLowerBand : CurrentTrailingUpperBand; } // Save the values to be used in next iteration. _previousClose = _currentClose; _prevSuper = _superTrend; _previousTrailingLowerBand = CurrentTrailingLowerBand; _previousTrailingUpperBand = CurrentTrailingUpperBand; return _superTrend; } /// /// Resets this indicator to its initial state /// public override void Reset() { _averageTrueRange.Reset(); _previousTrailingLowerBand = 0; _previousTrailingUpperBand = 0; _prevSuper = -1; base.Reset(); } } }