Lean
$LEAN_TAG$
RelativeStrengthIndex.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
18
namespace
QuantConnect.Indicators
19
{
20
/// <summary>
21
/// Represents the Relative Strength Index (RSI) developed by K. Welles Wilder.
22
/// You can optionally specified a different moving average type to be used in the computation
23
/// </summary>
24
public
class
RelativeStrengthIndex
:
Indicator
,
IIndicatorWarmUpPeriodProvider
25
{
26
private
IndicatorDataPoint
_previousInput;
27
28
/// <summary>
29
/// Gets the type of indicator used to compute AverageGain and AverageLoss
30
/// </summary>
31
public
MovingAverageType
MovingAverageType
{
get
; }
32
33
/// <summary>
34
/// Gets the EMA for the down days
35
/// </summary>
36
public
IndicatorBase<IndicatorDataPoint>
AverageLoss
{
get
; }
37
38
/// <summary>
39
/// Gets the indicator for average gain
40
/// </summary>
41
public
IndicatorBase<IndicatorDataPoint>
AverageGain
{
get
; }
42
43
/// <summary>
44
/// Initializes a new instance of the RelativeStrengthIndex class with the specified name and period
45
/// </summary>
46
/// <param name="period">The period used for up and down days</param>
47
/// <param name="movingAverageType">The type of moving average to be used for computing the average gain/loss values</param>
48
public
RelativeStrengthIndex
(
int
period,
MovingAverageType
movingAverageType =
MovingAverageType
.Wilders)
49
: this($
"RSI({period})"
, period, movingAverageType)
50
{
51
}
52
53
/// <summary>
54
/// Initializes a new instance of the RelativeStrengthIndex class with the specified name and period
55
/// </summary>
56
/// <param name="name">The name of this indicator</param>
57
/// <param name="period">The period used for up and down days</param>
58
/// <param name="movingAverageType">The type of moving average to be used for computing the average gain/loss values</param>
59
public
RelativeStrengthIndex
(
string
name,
int
period,
MovingAverageType
movingAverageType =
MovingAverageType
.Wilders)
60
: base(name)
61
{
62
MovingAverageType
= movingAverageType;
63
AverageGain
= movingAverageType.AsIndicator(name +
"Up"
, period);
64
AverageLoss
= movingAverageType.AsIndicator(name +
"Down"
, period);
65
WarmUpPeriod
= period + 1;
66
}
67
68
/// <summary>
69
/// Gets a flag indicating when this indicator is ready and fully initialized
70
/// </summary>
71
public
override
bool
IsReady
=>
AverageGain
.IsReady &&
AverageLoss
.IsReady;
72
73
/// <summary>
74
/// Required period, in data points, for the indicator to be ready and fully initialized.
75
/// </summary>
76
public
int
WarmUpPeriod
{
get
; }
77
78
/// <summary>
79
/// Computes the next value of this indicator from the given state
80
/// </summary>
81
/// <param name="input">The input given to the indicator</param>
82
/// <returns>A new value for this indicator</returns>
83
protected
override
decimal
ComputeNextValue
(
IndicatorDataPoint
input)
84
{
85
if
(_previousInput !=
null
&& input.
Value
>= _previousInput.
Value
)
86
{
87
AverageGain
.Update(input.
Time
, input.
Value
- _previousInput.
Value
);
88
AverageLoss
.Update(input.
Time
, 0m);
89
}
90
else
if
(_previousInput !=
null
&& input.
Value
< _previousInput.
Value
)
91
{
92
AverageGain
.Update(input.
Time
, 0m);
93
AverageLoss
.Update(input.
Time
, _previousInput.
Value
- input.
Value
);
94
}
95
96
_previousInput = input;
97
98
// make sure the difference averages are not negative
99
// (can happen with some types of moving averages -- e.g. DEMA)
100
var averageLoss =
AverageLoss
< 0 ? 0 :
AverageLoss
.Current.Value;
101
var averageGain =
AverageGain
< 0 ? 0 :
AverageGain
.Current.Value;
102
103
// Round AverageLoss to avoid computing RSI with very small numbers that lead to overflow exception on the division operation below
104
if
(Math.Round(averageLoss, 10) == 0m)
105
{
106
// all up days is 100
107
return
100m;
108
}
109
110
var rs = averageGain / averageLoss;
111
112
return
100m - 100m / (1 + rs);
113
}
114
115
/// <summary>
116
/// Resets this indicator to its initial state
117
/// </summary>
118
public
override
void
Reset
()
119
{
120
_previousInput =
null
;
121
AverageGain
.Reset();
122
AverageLoss
.Reset();
123
base.Reset();
124
}
125
}
126
}
Indicators
RelativeStrengthIndex.cs
Generated by
1.8.17