Lean  $LEAN_TAG$
Beta.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;
18 using MathNet.Numerics.Statistics;
19 
21 {
22  /// <summary>
23  /// In technical analysis Beta indicator is used to measure volatility or risk of a target (ETF) relative to the overall
24  /// risk (volatility) of the reference (market indexes). The Beta indicators compares target's price movement to the
25  /// movements of the indexes over the same period of time.
26  ///
27  /// It is common practice to use the SPX index as a benchmark of the overall reference market when it comes to Beta
28  /// calculations.
29  ///
30  /// The indicator only updates when both assets have a price for a time step. When a bar is missing for one of the assets,
31  /// the indicator value fills forward to improve the accuracy of the indicator.
32  /// </summary>
33  public class Beta : DualSymbolIndicator<IBaseDataBar>
34  {
35  /// <summary>
36  /// RollingWindow of returns of the target symbol in the given period
37  /// </summary>
38  private readonly RollingWindow<double> _targetReturns;
39 
40  /// <summary>
41  /// RollingWindow of returns of the reference symbol in the given period
42  /// </summary>
43  private readonly RollingWindow<double> _referenceReturns;
44 
45  /// <summary>
46  /// Gets a flag indicating when the indicator is ready and fully initialized
47  /// </summary>
48  public override bool IsReady => _targetReturns.IsReady && _referenceReturns.IsReady;
49 
50  /// <summary>
51  /// Creates a new Beta indicator with the specified name, target, reference,
52  /// and period values
53  /// </summary>
54  /// <param name="name">The name of this indicator</param>
55  /// <param name="targetSymbol">The target symbol of this indicator</param>
56  /// <param name="period">The period of this indicator</param>
57  /// <param name="referenceSymbol">The reference symbol of this indicator</param>
58  public Beta(string name, Symbol targetSymbol, Symbol referenceSymbol, int period)
59  : base(name, targetSymbol, referenceSymbol, 2)
60  {
61  // Assert the period is greater than two, otherwise the beta can not be computed
62  if (period < 2)
63  {
64  throw new ArgumentException($"Period parameter for Beta indicator must be greater than 2 but was {period}.");
65  }
66 
67  _targetReturns = new RollingWindow<double>(period);
68  _referenceReturns = new RollingWindow<double>(period);
69  WarmUpPeriod += (period - 2) + 1;
70  }
71 
72  /// <summary>
73  /// Creates a new Beta indicator with the specified target, reference,
74  /// and period values
75  /// </summary>
76  /// <param name="targetSymbol">The target symbol of this indicator</param>
77  /// <param name="period">The period of this indicator</param>
78  /// <param name="referenceSymbol">The reference symbol of this indicator</param>
79  public Beta(Symbol targetSymbol, Symbol referenceSymbol, int period)
80  : this($"B({period})", targetSymbol, referenceSymbol, period)
81  {
82  }
83 
84  /// <summary>
85  /// Creates a new Beta indicator with the specified name, period, target and
86  /// reference values
87  /// </summary>
88  /// <param name="name">The name of this indicator</param>
89  /// <param name="period">The period of this indicator</param>
90  /// <param name="targetSymbol">The target symbol of this indicator</param>
91  /// <param name="referenceSymbol">The reference symbol of this indicator</param>
92  /// <remarks>Constructor overload for backward compatibility.</remarks>
93  public Beta(string name, int period, Symbol targetSymbol, Symbol referenceSymbol)
94  : this(name, targetSymbol, referenceSymbol, period)
95  {
96  }
97 
98  /// <summary>
99  /// Computes the returns with the new given data point and the last given data point
100  /// </summary>
101  /// <param name="rollingWindow">The collection of data points from which we want
102  /// to compute the return</param>
103  /// <returns>The returns with the new given data point</returns>
104  private static double GetNewReturn(IReadOnlyWindow<IBaseDataBar> rollingWindow)
105  {
106  return (double)(rollingWindow[0].Close.SafeDivision(rollingWindow[1].Close) - 1);
107  }
108 
109  /// <summary>
110  /// Computes the beta value of the target in relation with the reference
111  /// using the target and reference returns
112  /// </summary>
113  protected override decimal ComputeIndicator()
114  {
115  if (TargetDataPoints.IsReady)
116  {
117  _targetReturns.Add(GetNewReturn(TargetDataPoints));
118  }
119 
120  if (ReferenceDataPoints.IsReady)
121  {
122  _referenceReturns.Add(GetNewReturn(ReferenceDataPoints));
123  }
124 
125  var varianceComputed = _referenceReturns.Variance();
126  var covarianceComputed = _targetReturns.Covariance(_referenceReturns);
127 
128  // Avoid division with NaN or by zero
129  var variance = !varianceComputed.IsNaNOrZero() ? varianceComputed : 1;
130  var covariance = !covarianceComputed.IsNaNOrZero() ? covarianceComputed : 0;
131  return (decimal)(covariance / variance);
132  }
133 
134  /// <summary>
135  /// Resets this indicator to its initial state
136  /// </summary>
137  public override void Reset()
138  {
139  _targetReturns.Reset();
140  _referenceReturns.Reset();
141  base.Reset();
142  }
143  }
144 }