Lean  $LEAN_TAG$
ArnaudLegouxMovingAverage.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 
16 using System;
17 using System.Linq;
18 
20 {
21  /// <summary>
22  /// Smooth and high sensitive moving Average. This moving average reduce lag of the information
23  /// but still being smooth to reduce noises.
24  /// Is a weighted moving average, which weights have a Normal shape;
25  /// the parameters Sigma and Offset affect the kurtosis and skewness of the weights respectively.
26  /// Source: https://www.cjournal.cz/files/308.pdf
27  /// </summary>
28  /// <seealso cref="IndicatorDataPoint" />
30  {
31  private readonly decimal[] _weightVector;
32 
33  /// <summary>
34  /// Required period, in data points, for the indicator to be ready and fully initialized.
35  /// </summary>
36  public int WarmUpPeriod => _weightVector.Length;
37 
38  /// <summary>
39  /// Initializes a new instance of the <see cref="ArnaudLegouxMovingAverage" /> class.
40  /// </summary>
41  /// <param name="name">string - a name for the indicator</param>
42  /// <param name="period">int - the number of periods to calculate the ALMA</param>
43  /// <param name="sigma">
44  /// int - this parameter is responsible for the shape of the curve coefficients. It affects the weight vector kurtosis.
45  /// </param>
46  /// <param name="offset">
47  /// decimal - This parameter allows regulating the smoothness and high sensitivity of the
48  /// Moving Average. The range for this parameter is [0, 1]. It affects the weight vector skewness.
49  /// </param>
50  public ArnaudLegouxMovingAverage(string name, int period, int sigma = 6, decimal offset = 0.85m)
51  : base(name, period)
52  {
53  if (offset < 0 || offset > 1) throw new ArgumentException($"Offset parameter range is [0,1]. Value: {offset}", nameof(offset));
54 
55  var m = Math.Floor(offset * (period - 1));
56  var s = period * 1m / sigma;
57 
58  var tmpVector = Enumerable.Range(0, period)
59  .Select(i => Math.Exp((double) (-(i - m) * (i - m) / (2 * s * s))))
60  .ToArray();
61 
62  _weightVector = tmpVector
63  .Select(i => (decimal) (i / tmpVector.Sum())).Reverse()
64  .ToArray();
65  }
66 
67  /// <summary>
68  /// Initializes a new instance of the <see cref="ArnaudLegouxMovingAverage" /> class.
69  /// </summary>
70  /// <param name="name">string - a name for the indicator</param>
71  /// <param name="period">int - the number of periods to calculate the ALMA.</param>
72  public ArnaudLegouxMovingAverage(string name, int period)
73  : this(name, period, 6)
74  {
75  }
76 
77  /// <summary>
78  /// Initializes a new instance of the <see cref="ArnaudLegouxMovingAverage" /> class.
79  /// </summary>
80  /// <param name="period">int - the number of periods to calculate the ALMA</param>
81  /// <param name="sigma">
82  /// int - this parameter is responsible for the shape of the curve coefficients. It affects the weight
83  /// vector kurtosis.
84  /// </param>
85  /// <param name="offset">
86  /// decimal - This parameter allows regulating the smoothness and high sensitivity of the Moving
87  /// Average. The range for this parameter is [0, 1]. It affects the weight vector skewness.
88  /// </param>
89  public ArnaudLegouxMovingAverage(int period, int sigma, decimal offset = 0.85m)
90  : this($"ALMA({period},{sigma},{offset})", period, sigma, offset)
91  {
92  }
93 
94  /// <summary>
95  /// Initializes a new instance of the <see cref="ArnaudLegouxMovingAverage" /> class.
96  /// </summary>
97  /// <param name="period">int - the number of periods to calculate the ALMA.</param>
98  public ArnaudLegouxMovingAverage(int period)
99  : this(period, 6)
100  {
101  }
102 
103  /// <summary>
104  /// Computes the next value for this indicator from the given state.
105  /// </summary>
106  /// <param name="window">The window of data held in this indicator</param>
107  /// <param name="input">The input value to this indicator on this time step</param>
108  /// <returns>
109  /// A new value for this indicator
110  /// </returns>
111  /// <exception cref="System.NotImplementedException"></exception>
112  protected override decimal ComputeNextValue(IReadOnlyWindow<IndicatorDataPoint> window,
113  IndicatorDataPoint input)
114  {
115  return IsReady
116  ? window.Select((t, i) => t.Price * _weightVector[i]).Sum()
117  : input.Value;
118  }
119  }
120 }