Lean  $LEAN_TAG$
Alpha.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 Python.Runtime;
17 using QuantConnect.Data;
19 using QuantConnect.Python;
20 using System;
21 
23 {
24  /// <summary>
25  /// In financial analysis, the Alpha indicator is used to measure the performance of an investment (such as a stock or ETF)
26  /// relative to a benchmark index, often representing the broader market. Alpha indicates the excess return of the investment
27  /// compared to the return of the benchmark index.
28  ///
29  /// The S P 500 index is frequently used as a benchmark in Alpha calculations to represent the overall market performance.
30  /// Alpha is an essential tool for investors to understand the idiosyncratic returns of their investment that aren't caused
31  /// by movement in the underlying benchmark.
32  /// </summary>
33 
35  {
36  /// <summary>
37  /// Symbol of the reference used
38  /// </summary>
39  private readonly Symbol _referenceSymbol;
40 
41  /// <summary>
42  /// Symbol of the target used
43  /// </summary>
44  private readonly Symbol _targetSymbol;
45 
46  /// <summary>
47  /// Period of the indicator - alpha
48  /// </summary>
49  private readonly decimal _alphaPeriod;
50 
51  /// <summary>
52  /// Rate of change of the target symbol
53  /// </summary>
54  private readonly RateOfChange _targetROC;
55 
56  /// <summary>
57  /// Rate of change of the reference symbol
58  /// </summary>
59  private readonly RateOfChange _referenceROC;
60 
61  /// <summary>
62  /// Alpha of the target used in relation with the reference
63  /// </summary>
64  private decimal _alpha;
65 
66  /// <summary>
67  /// Beta of the target used in relation with the reference
68  /// </summary>
69  private readonly Beta _beta;
70 
71  /// <summary>
72  /// Interest rate model used to compute the risk free rate
73  /// </summary>
74  private readonly IRiskFreeInterestRateModel _riskFreeInterestRateModel;
75 
76  /// <summary>
77  /// Required period, in data points, for the indicator to be ready and fully initialized.
78  /// </summary>
79  public int WarmUpPeriod { get; private set; }
80 
81  /// <summary>
82  /// Gets a flag indicating when the indicator is ready and fully initialized
83  /// </summary>
84  public override bool IsReady => _targetROC.IsReady && _beta.IsReady && _referenceROC.IsReady;
85 
86  /// <summary>
87  /// Creates a new Alpha indicator with the specified name, target, reference, and period values
88  /// </summary>
89  /// <param name="name">The name 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  /// <param name="alphaPeriod">Period of the indicator - alpha</param>
93  /// <param name="betaPeriod">Period of the indicator - beta</param>
94  /// <param name="riskFreeRateModel">The risk free rate model of this indicator</param>
95  public Alpha(string name, Symbol targetSymbol, Symbol referenceSymbol, int alphaPeriod, int betaPeriod, IRiskFreeInterestRateModel riskFreeRateModel)
96  : base(name)
97  {
98  // Assert that the target and reference symbols are not the same
99  if (targetSymbol == referenceSymbol)
100  {
101  throw new ArgumentException("The target and reference symbols cannot be the same.");
102  }
103 
104  // Assert that the period is greater than 2, otherwise the alpha can not be computed
105  if (alphaPeriod < 1)
106  {
107  throw new ArgumentException("The period must be equal or greater than 1.");
108  }
109 
110  // Assert that the beta period is greater than 2, otherwise the beta can not be computed
111  if (betaPeriod < 2)
112  {
113  throw new ArgumentException("The beta period must be equal or greater than 2.");
114  }
115 
116  _targetSymbol = targetSymbol;
117  _referenceSymbol = referenceSymbol;
118  _alphaPeriod = alphaPeriod;
119  _riskFreeInterestRateModel = riskFreeRateModel;
120 
121  _targetROC = new RateOfChange($"{name}_TargetROC", alphaPeriod);
122  _referenceROC = new RateOfChange($"{name}_ReferenceROC", alphaPeriod);
123 
124  _beta = new Beta($"{name}_Beta", _targetSymbol, _referenceSymbol, betaPeriod);
125 
126  WarmUpPeriod = alphaPeriod >= betaPeriod ? alphaPeriod + 1 : betaPeriod + 1;
127 
128  _alpha = 0m;
129  }
130 
131  /// <summary>
132  /// Creates a new Alpha indicator with the specified name, target, reference, and period values
133  /// </summary>
134  /// <param name="name">The name of this indicator</param>
135  /// <param name="targetSymbol">The target symbol of this indicator</param>
136  /// <param name="referenceSymbol">The reference symbol of this indicator</param>
137  /// <param name="alphaPeriod">Period of the indicator - alpha</param>
138  /// <param name="betaPeriod">Period of the indicator - beta</param>
139  /// <param name="riskFreeRate">The risk free rate of this indicator for given period</param>
140  public Alpha(string name, Symbol targetSymbol, Symbol referenceSymbol, int alphaPeriod, int betaPeriod, decimal? riskFreeRate = null)
141  : this(name, targetSymbol, referenceSymbol, alphaPeriod, betaPeriod, new ConstantRiskFreeRateInterestRateModel(riskFreeRate ?? 0m))
142  {
143  }
144 
145  /// <summary>
146  /// Creates a new Alpha indicator with the specified target, reference, and period values
147  /// </summary>
148  /// <param name="targetSymbol"></param>
149  /// <param name="referenceSymbol"></param>
150  /// <param name="alphaPeriod">Period of the indicator - alpha</param>
151  /// <param name="betaPeriod">Period of the indicator - beta</param>
152  /// <param name="riskFreeRate">The risk free rate of this indicator for given period</param>
153  public Alpha(Symbol targetSymbol, Symbol referenceSymbol, int alphaPeriod, int betaPeriod, decimal? riskFreeRate = null)
154  : this($"ALPHA({targetSymbol},{referenceSymbol},{alphaPeriod},{betaPeriod},{riskFreeRate})", targetSymbol, referenceSymbol, alphaPeriod, betaPeriod, new ConstantRiskFreeRateInterestRateModel(riskFreeRate ?? 0m))
155  {
156  }
157 
158  /// <summary>
159  /// Creates a new Alpha indicator with the specified target, reference, and period value
160  /// </summary>
161  /// <param name="targetSymbol">The target symbol of this indicator</param>
162  /// <param name="referenceSymbol">The reference symbol of this indicator</param>
163  /// <param name="period">Period of the indicator - alpha and beta</param>
164  /// <param name="riskFreeRate">The risk free rate of this indicator for given period</param>
165  public Alpha(Symbol targetSymbol, Symbol referenceSymbol, int period, decimal? riskFreeRate = null)
166  : this($"ALPHA({targetSymbol},{referenceSymbol},{period},{riskFreeRate})", targetSymbol, referenceSymbol, period, period, new ConstantRiskFreeRateInterestRateModel(riskFreeRate ?? 0m))
167  {
168  }
169 
170  /// <summary>
171  /// Creates a new Alpha indicator with the specified name, target, reference, and period value
172  /// </summary>
173  /// <param name="name"></param>
174  /// <param name="targetSymbol"></param>
175  /// <param name="referenceSymbol"></param>
176  /// <param name="period">Period of the indicator - alpha and beta</param>
177  /// <param name="riskFreeRate">The risk free rate of this indicator for given period</param>
178  public Alpha(string name, Symbol targetSymbol, Symbol referenceSymbol, int period, decimal? riskFreeRate = null)
179  : this(name, targetSymbol, referenceSymbol, period, period, new ConstantRiskFreeRateInterestRateModel(riskFreeRate ?? 0m))
180  {
181  }
182 
183  /// <summary>
184  /// Creates a new Alpha indicator with the specified target, reference, and period values
185  /// </summary>
186  /// <param name="targetSymbol"></param>
187  /// <param name="referenceSymbol"></param>
188  /// <param name="alphaPeriod">Period of the indicator - alpha</param>
189  /// <param name="betaPeriod">Period of the indicator - beta</param>
190  /// <param name="riskFreeRateModel">The risk free rate model of this indicator</param>
191  public Alpha(Symbol targetSymbol, Symbol referenceSymbol, int alphaPeriod, int betaPeriod, IRiskFreeInterestRateModel riskFreeRateModel)
192  : this($"ALPHA({targetSymbol},{referenceSymbol},{alphaPeriod},{betaPeriod})", targetSymbol, referenceSymbol, alphaPeriod, betaPeriod, riskFreeRateModel)
193  {
194  }
195 
196  /// <summary>
197  /// Creates a new Alpha indicator with the specified target, reference, and period value
198  /// </summary>
199  /// <param name="targetSymbol">The target symbol of this indicator</param>
200  /// <param name="referenceSymbol">The reference symbol of this indicator</param>
201  /// <param name="period">Period of the indicator - alpha and beta</param>
202  /// <param name="riskFreeRateModel">The risk free rate model of this indicator</param>
203  public Alpha(Symbol targetSymbol, Symbol referenceSymbol, int period, IRiskFreeInterestRateModel riskFreeRateModel)
204  : this($"ALPHA({targetSymbol},{referenceSymbol},{period})", targetSymbol, referenceSymbol, period, period, riskFreeRateModel)
205  {
206  }
207 
208  /// <summary>
209  /// Creates a new Alpha indicator with the specified name, target, reference, and period value
210  /// </summary>
211  /// <param name="name"></param>
212  /// <param name="targetSymbol"></param>
213  /// <param name="referenceSymbol"></param>
214  /// <param name="period">Period of the indicator - alpha and beta</param>
215  /// <param name="riskFreeRateModel">The risk free rate model of this indicator</param>
216  public Alpha(string name, Symbol targetSymbol, Symbol referenceSymbol, int period, IRiskFreeInterestRateModel riskFreeRateModel)
217  : this(name, targetSymbol, referenceSymbol, period, period, riskFreeRateModel)
218  {
219  }
220 
221  /// <summary>
222  /// Creates a new Alpha indicator with the specified name, target, reference, and period values
223  /// </summary>
224  /// <param name="name">The name of this indicator</param>
225  /// <param name="targetSymbol">The target symbol of this indicator</param>
226  /// <param name="referenceSymbol">The reference symbol of this indicator</param>
227  /// <param name="alphaPeriod">Period of the indicator - alpha</param>
228  /// <param name="betaPeriod">Period of the indicator - beta</param>
229  /// <param name="riskFreeRateModel">The risk free rate model of this indicator</param>
230  public Alpha(string name, Symbol targetSymbol, Symbol referenceSymbol, int alphaPeriod, int betaPeriod, PyObject riskFreeRateModel)
231  : this(name, targetSymbol, referenceSymbol, alphaPeriod, betaPeriod, RiskFreeInterestRateModelPythonWrapper.FromPyObject(riskFreeRateModel))
232  {
233  }
234 
235  /// <summary>
236  /// Creates a new Alpha indicator with the specified target, reference, and period values
237  /// </summary>
238  /// <param name="targetSymbol"></param>
239  /// <param name="referenceSymbol"></param>
240  /// <param name="alphaPeriod">Period of the indicator - alpha</param>
241  /// <param name="betaPeriod">Period of the indicator - beta</param>
242  /// <param name="riskFreeRateModel">The risk free rate model of this indicator</param>
243  public Alpha(Symbol targetSymbol, Symbol referenceSymbol, int alphaPeriod, int betaPeriod, PyObject riskFreeRateModel)
244  : this($"ALPHA({targetSymbol},{referenceSymbol},{alphaPeriod},{betaPeriod})", targetSymbol, referenceSymbol, alphaPeriod, betaPeriod, RiskFreeInterestRateModelPythonWrapper.FromPyObject(riskFreeRateModel))
245  {
246  }
247 
248  /// <summary>
249  /// Creates a new Alpha indicator with the specified target, reference, and period value
250  /// </summary>
251  /// <param name="targetSymbol">The target symbol of this indicator</param>
252  /// <param name="referenceSymbol">The reference symbol of this indicator</param>
253  /// <param name="period">Period of the indicator - alpha and beta</param>
254  /// <param name="riskFreeRateModel">The risk free rate model of this indicator</param>
255  public Alpha(Symbol targetSymbol, Symbol referenceSymbol, int period, PyObject riskFreeRateModel)
256  : this($"ALPHA({targetSymbol},{referenceSymbol},{period})", targetSymbol, referenceSymbol, period, period, RiskFreeInterestRateModelPythonWrapper.FromPyObject(riskFreeRateModel))
257  {
258  }
259 
260  /// <summary>
261  /// Creates a new Alpha indicator with the specified name, target, reference, and period value
262  /// </summary>
263  /// <param name="name"></param>
264  /// <param name="targetSymbol"></param>
265  /// <param name="referenceSymbol"></param>
266  /// <param name="period">Period of the indicator - alpha and beta</param>
267  /// <param name="riskFreeRateModel">The risk free rate model of this indicator</param>
268  public Alpha(string name, Symbol targetSymbol, Symbol referenceSymbol, int period, PyObject riskFreeRateModel)
269  : this(name, targetSymbol, referenceSymbol, period, period, RiskFreeInterestRateModelPythonWrapper.FromPyObject(riskFreeRateModel))
270  {
271  }
272 
273  /// <summary>
274  /// Computes the next value for this indicator from the given state.
275  /// </summary>
276  /// <param name="input"></param>
277  /// <returns></returns>
278  /// <exception cref="ArgumentException"></exception>
279  protected override decimal ComputeNextValue(IBaseDataBar input)
280  {
281  if (input is null)
282  {
283  throw new ArgumentNullException(nameof(input));
284  }
285  var inputSymbol = input.Symbol;
286 
287  if (inputSymbol == _targetSymbol)
288  {
289  _targetROC.Update(input.EndTime, input.Close);
290  }
291  else if (inputSymbol == _referenceSymbol)
292  {
293  _referenceROC.Update(input.EndTime, input.Close);
294  }
295  else
296  {
297  throw new ArgumentException($"The input symbol {inputSymbol} is not the target or reference symbol.");
298  }
299 
300  _beta.Update(input);
301 
302  if (_targetROC.Samples == _referenceROC.Samples && _referenceROC.Samples > 0)
303  {
304  ComputeAlpha();
305  }
306 
307  return _alpha;
308  }
309 
310  /// <summary>
311  /// Computes the alpha of the target used in relation with the reference and stores it in the _alpha field
312  /// </summary>
313  private void ComputeAlpha()
314  {
315  if (!_beta.IsReady || !_targetROC.IsReady || !_referenceROC.IsReady)
316  {
317  _alpha = 0m;
318  return;
319  }
320 
321  var targetMean = _targetROC.Current.Value / _alphaPeriod;
322  var referenceMean = _referenceROC.Current.Value / _alphaPeriod;
323 
324  var riskFreeRate = _riskFreeInterestRateModel.GetInterestRate(_targetROC.Current.Time);
325 
326  _alpha = targetMean - (riskFreeRate + _beta.Current.Value * (referenceMean - riskFreeRate));
327  }
328 
329  /// <summary>
330  /// Resets this indicator to its initial state
331  /// </summary>
332  public override void Reset()
333  {
334  _targetROC.Reset();
335  _referenceROC.Reset();
336  _beta.Reset();
337  _alpha = 0m;
338  base.Reset();
339  }
340  }
341 }