Lean  $LEAN_TAG$
LinearWeightedMovingAverage.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 using System;
16 using System.Linq;
17 
19 {
20  /// <summary>
21  /// Represents the traditional Weighted Moving Average indicator. The weight are linearly
22  /// distributed according to the number of periods in the indicator.
23  ///
24  /// For example, a 4 period indicator will have a numerator of (4 * window[0]) + (3 * window[1]) + (2 * window[2]) + window[3]
25  /// and a denominator of 4 + 3 + 2 + 1 = 10
26  ///
27  /// During the warm up period, IsReady will return false, but the LWMA will still be computed correctly because
28  /// the denominator will be the minimum of Samples factorial or Size factorial and
29  /// the computation iterates over that minimum value.
30  ///
31  /// The RollingWindow of inputs is created when the indicator is created.
32  /// A RollingWindow of LWMAs is not saved. That is up to the caller.
33  /// </summary>
35  {
36  private readonly int _denominator;
37  /// <summary>
38  /// Required period, in data points, for the indicator to be ready and fully initialized.
39  /// </summary>
40  public int WarmUpPeriod => Period;
41 
42  /// <summary>
43  /// Initializes a new instance of the LinearWeightedMovingAverage class with the specified name and period
44  /// </summary>
45  /// <param name="name">The name of this indicator</param>
46  /// <param name="period">The period of the LWMA</param>
47  public LinearWeightedMovingAverage(string name, int period)
48  : base(name, period)
49  {
50  _denominator = (period * (period + 1)) / 2;
51  }
52 
53  /// <summary>
54  /// Initializes a new instance of the LinearWeightedMovingAverage class with the default name and period
55  /// </summary>
56  /// <param name="period">The period of the LWMA</param>
57  public LinearWeightedMovingAverage(int period)
58  : this($"LWMA({period})", period)
59  {
60  }
61 
62  /// <summary>
63  /// Computes the next value for this indicator from the given state.
64  /// </summary>
65  /// <param name="window">The window of data held in this indicator</param>
66  /// <param name="input">The input value to this indicator on this time step</param>
67  /// <returns>A new value for this indicator</returns>
69  {
70  // our first data point just return identity
71  if (!IsReady)
72  {
73  return 0;
74  }
75 
76  var numerator = 0m;
77  var index = window.Size;
78 
79  // If the indicator is not ready, the LWMA will still be correct
80  // because the numerator has the minimum of the Size (number of
81  // entries or the Samples (the allocated space)
82  var minSizeSamples = (int)Math.Min(index, window.Samples);
83  for (var i = 0; i < minSizeSamples; i++)
84  {
85  numerator += (index-- * window[i].Value);
86  }
87  return numerator / _denominator;
88  }
89  }
90 }