Skip to content

Commit 3fa700e

Browse files
authored
New Feature: Implement Covariance Indicator #6982 (#9144)
* Implements Covariance as Lean Indicator * Add COV helper method and fix AcceptsVolumeRenkoBarsAsInput test * Fix AcceptsRenkoBarsAsInput test to use smaller period for faster execution * Fix slow Renko tests by limiting data processed to 50 rows
1 parent 7735917 commit 3fa700e

File tree

5 files changed

+7873
-0
lines changed

5 files changed

+7873
-0
lines changed

Algorithm/QCAlgorithm.Indicators.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,26 @@ public Correlation C(Symbol target, Symbol reference, int period, CorrelationTyp
490490
return correlation;
491491
}
492492

493+
/// <summary>
494+
/// Creates a Covariance indicator for the given target symbol in relation with the reference used.
495+
/// The indicator will be automatically updated on the given resolution.
496+
/// </summary>
497+
/// <param name="target">The target symbol whose Covariance value we want</param>
498+
/// <param name="reference">The reference symbol to compare with the target symbol</param>
499+
/// <param name="period">The period of the Covariance indicator</param>
500+
/// <param name="resolution">The resolution</param>
501+
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
502+
/// <returns>The Covariance indicator for the given parameters</returns>
503+
[DocumentationAttribute(Indicators)]
504+
public Covariance COV(Symbol target, Symbol reference, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
505+
{
506+
var name = CreateIndicatorName(QuantConnect.Symbol.None, $"COV({period})", resolution);
507+
var covariance = new Covariance(name, target, reference, period);
508+
InitializeIndicator(covariance, resolution, selector, target, reference);
509+
510+
return covariance;
511+
}
512+
493513
/// <summary>
494514
/// Creates a new CommodityChannelIndex indicator. The indicator will be automatically
495515
/// updated on the given resolution.

Indicators/Covariance.cs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
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 QuantConnect.Data.Market;
18+
using MathNet.Numerics.Statistics;
19+
20+
namespace QuantConnect.Indicators
21+
{
22+
/// <summary>
23+
/// This indicator computes the Covariance of two assets using the given Look-Back period.
24+
/// The Covariance of two assets is a measure of their co-movement.
25+
/// </summary>
26+
public class Covariance : DualSymbolIndicator<IBaseDataBar>
27+
{
28+
/// <summary>
29+
/// RollingWindow of returns of the target symbol in the given period
30+
/// </summary>
31+
private readonly RollingWindow<double> _targetReturns;
32+
33+
/// <summary>
34+
/// RollingWindow of returns of the reference symbol in the given period
35+
/// </summary>
36+
private readonly RollingWindow<double> _referenceReturns;
37+
38+
/// <summary>
39+
/// Gets a flag indicating when the indicator is ready and fully initialized
40+
/// </summary>
41+
public override bool IsReady => _targetReturns.IsReady && _referenceReturns.IsReady;
42+
43+
/// <summary>
44+
/// Creates a new Covariance indicator with the specified name, target, reference,
45+
/// and period values
46+
/// </summary>
47+
/// <param name="name">The name of this indicator</param>
48+
/// <param name="targetSymbol">The target symbol of this indicator</param>
49+
/// <param name="period">The period of this indicator</param>
50+
/// <param name="referenceSymbol">The reference symbol of this indicator</param>
51+
public Covariance(string name, Symbol targetSymbol, Symbol referenceSymbol, int period)
52+
: base(name, targetSymbol, referenceSymbol, 2)
53+
{
54+
// Assert the period is greater than two, otherwise the covariance can not be computed
55+
if (period < 2)
56+
{
57+
throw new ArgumentException($"Period parameter for Covariance indicator must be greater than 2 but was {period}.");
58+
}
59+
60+
_targetReturns = new RollingWindow<double>(period);
61+
_referenceReturns = new RollingWindow<double>(period);
62+
WarmUpPeriod += (period - 2) + 1;
63+
}
64+
65+
/// <summary>
66+
/// Creates a new Covariance indicator with the specified target, reference,
67+
/// and period values
68+
/// </summary>
69+
/// <param name="targetSymbol">The target symbol of this indicator</param>
70+
/// <param name="period">The period of this indicator</param>
71+
/// <param name="referenceSymbol">The reference symbol of this indicator</param>
72+
public Covariance(Symbol targetSymbol, Symbol referenceSymbol, int period)
73+
: this($"COV({period})", targetSymbol, referenceSymbol, period)
74+
{
75+
}
76+
77+
/// <summary>
78+
/// Creates a new Covariance indicator with the specified name, period, target and
79+
/// reference values
80+
/// </summary>
81+
/// <param name="name">The name of this indicator</param>
82+
/// <param name="period">The period of this indicator</param>
83+
/// <param name="targetSymbol">The target symbol of this indicator</param>
84+
/// <param name="referenceSymbol">The reference symbol of this indicator</param>
85+
/// <remarks>Constructor overload for backward compatibility.</remarks>
86+
public Covariance(string name, int period, Symbol targetSymbol, Symbol referenceSymbol)
87+
: this(name, targetSymbol, referenceSymbol, period)
88+
{
89+
}
90+
91+
/// <summary>
92+
/// Computes the returns with the new given data point and the last given data point
93+
/// </summary>
94+
/// <param name="rollingWindow">The collection of data points from which we want
95+
/// to compute the return</param>
96+
/// <returns>The returns with the new given data point</returns>
97+
private static double GetNewReturn(IReadOnlyWindow<IBaseDataBar> rollingWindow)
98+
{
99+
return (double)(rollingWindow[0].Close.SafeDivision(rollingWindow[1].Close) - 1);
100+
}
101+
102+
/// <summary>
103+
/// Computes the covariance value of the target in relation with the reference
104+
/// using the target and reference returns
105+
/// </summary>
106+
protected override decimal ComputeIndicator()
107+
{
108+
if (TargetDataPoints.IsReady)
109+
{
110+
_targetReturns.Add(GetNewReturn(TargetDataPoints));
111+
}
112+
113+
if (ReferenceDataPoints.IsReady)
114+
{
115+
_referenceReturns.Add(GetNewReturn(ReferenceDataPoints));
116+
}
117+
118+
var covarianceComputed = _targetReturns.Covariance(_referenceReturns);
119+
120+
// Avoid division with NaN or by zero
121+
return (decimal)(!covarianceComputed.IsNaNOrZero() ? covarianceComputed : 0);
122+
}
123+
124+
/// <summary>
125+
/// Resets this indicator to its initial state
126+
/// </summary>
127+
public override void Reset()
128+
{
129+
_targetReturns.Reset();
130+
_referenceReturns.Reset();
131+
base.Reset();
132+
}
133+
}
134+
}

0 commit comments

Comments
 (0)