Lean  $LEAN_TAG$
SuperTrend.cs
1 /*
2  * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3  * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 */
15 
17 
19 {
20  /// <summary>
21  /// Super trend indicator.
22  /// Formula can be found here via the excel file:
23  /// https://tradingtuitions.com/supertrend-indicator-excel-sheet-with-realtime-buy-sell-signals/
24  /// </summary>
26  {
27  private readonly decimal _multiplier;
28  private decimal _superTrend;
29  private decimal _currentClose;
30  private decimal _previousTrailingUpperBand;
31  private decimal _previousTrailingLowerBand;
32  private decimal _previousClose;
33  private decimal _prevSuper;
34  private readonly int _period;
35 
36  /// <summary>
37  /// Average true range indicator used to calculate super trend's basic upper and lower bands
38  /// </summary>
39  private readonly AverageTrueRange _averageTrueRange;
40 
41  /// <summary>
42  /// Basic Upper Band
43  /// </summary>
44  public decimal BasicUpperBand { get; private set; }
45 
46  /// <summary>
47  /// Basic Lower band
48  /// </summary>
49  public decimal BasicLowerBand { get; private set; }
50 
51  /// <summary>
52  /// Current Trailing Upper Band
53  /// </summary>
54  public decimal CurrentTrailingUpperBand { get; private set; }
55 
56  /// <summary>
57  /// Current Trailing Lower Band
58  /// </summary>
59  public decimal CurrentTrailingLowerBand { get; private set; }
60 
61  /// <summary>
62  /// Gets a flag indicating when this indicator is ready and fully initialized
63  /// </summary>
64  public override bool IsReady => _averageTrueRange.IsReady;
65 
66  /// <summary>
67  /// Required period, in data points, for the indicator to be ready and fully initialized.
68  /// </summary>
69  public int WarmUpPeriod => _period;
70 
71  /// <summary>
72  /// Creates a new SuperTrend indicator using the specified name, period, multiplier and moving average type
73  /// </summary>
74  /// <param name="name">The name of this indicator</param>
75  /// <param name="period">The smoothing period used by average true range</param>
76  /// <param name="multiplier">The coefficient used in calculations of basic upper and lower bands</param>
77  /// <param name="movingAverageType">The type of smoothing used to smooth the true range values</param>
78  public SuperTrend(string name, int period, decimal multiplier, MovingAverageType movingAverageType = MovingAverageType.Wilders)
79  : base(name)
80  {
81  _averageTrueRange = new AverageTrueRange(period, movingAverageType);
82  _multiplier = multiplier;
83  _period = period;
84  _prevSuper = -1;
85  }
86 
87  /// <summary>
88  /// Creates a new SuperTrend indicator using the specified period, multiplier and moving average type
89  /// </summary>
90  /// <param name="period">The smoothing period used in average true range</param>
91  /// <param name="multiplier">The coefficient used in calculations of basic upper and lower bands</param>
92  /// <param name="movingAverageType">The type of smoothing used to smooth the true range values</param>
93  public SuperTrend(int period, decimal multiplier, MovingAverageType movingAverageType = MovingAverageType.Wilders)
94  : this($"SuperTrend({period},{multiplier})", period, multiplier, movingAverageType)
95  {
96  }
97 
98  /// <summary>
99  /// Computes the next value of this indicator from the given state
100  /// </summary>
101  /// <param name="input">The input given to the indicator</param>
102  /// <returns>A new value for this indicator</returns>
103  protected override decimal ComputeNextValue(IBaseDataBar input)
104  {
105  if (!_averageTrueRange.Update(input))
106  {
107  _previousClose = input.Close;
108  return 0m;
109  }
110 
111  _currentClose = input.Close;
112  BasicLowerBand = ((input.High + input.Low) / 2) - (_multiplier * _averageTrueRange.Current.Value);
113  BasicUpperBand = ((input.High + input.Low) / 2) + (_multiplier * _averageTrueRange.Current.Value);
114 
115  CurrentTrailingLowerBand = ((BasicLowerBand > _previousTrailingLowerBand) || (_previousClose < _previousTrailingLowerBand)) ? BasicLowerBand : _previousTrailingLowerBand;
116  CurrentTrailingUpperBand = ((BasicUpperBand < _previousTrailingUpperBand) || (_previousClose > _previousTrailingUpperBand)) ? BasicUpperBand : _previousTrailingUpperBand;
117 
118  if ((_prevSuper == -1) || (_prevSuper == _previousTrailingUpperBand))
119  {
121  }
122  else if (_prevSuper == _previousTrailingLowerBand)
123  {
125  }
126 
127  // Save the values to be used in next iteration.
128  _previousClose = _currentClose;
129  _prevSuper = _superTrend;
130  _previousTrailingLowerBand = CurrentTrailingLowerBand;
131  _previousTrailingUpperBand = CurrentTrailingUpperBand;
132 
133  return _superTrend;
134  }
135 
136  /// <summary>
137  /// Resets this indicator to its initial state
138  /// </summary>
139  public override void Reset()
140  {
141  _averageTrueRange.Reset();
142  _previousTrailingLowerBand = 0;
143  _previousTrailingUpperBand = 0;
144  _prevSuper = -1;
145  base.Reset();
146  }
147  }
148 }