Lean
$LEAN_TAG$
WilderSwingIndex.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
using
System.Linq;
18
using
QuantConnect
.
Data
.
Market
;
19
20
namespace
QuantConnect.Indicators
21
{
22
/// <summary>
23
/// This indicator calculates the Swing Index (SI) as defined by Welles Wilder
24
/// in his book 'New Concepts in Technical Trading Systems'.
25
/// <para>
26
/// SIₜ = 50 * ( N / R ) * ( K / T )
27
/// </para>
28
/// <para>
29
/// Where:
30
/// <list type="bullet">
31
/// <item>
32
/// <term>N</term>
33
/// <description>
34
/// Equals: Cₜ - Cₜ₋₁ + 0.5 * (Cₜ - Oₜ) + 0.25 * (Cₜ₋₁ - Oₜ₋₁)
35
/// <para>
36
/// <i>See <see cref="GetNValue"/></i>
37
/// </para>
38
/// </description>
39
/// </item>
40
/// <item>
41
/// <term>R</term>
42
/// <description>
43
/// Found by selecting the expression with the largest value and
44
/// then using the corresponding formula.
45
/// <para>
46
/// Expression => Formula
47
/// <list type="number">
48
/// <item>
49
/// <description>
50
/// |Hₜ - Cₜ₋₁| => |Hₜ - Cₜ| - 0.5 * |Lₜ - Cₜ₋₁| + 0.25 * |Cₜ₋₁ - Oₜ₋₁|
51
/// </description>
52
/// </item>
53
/// <item>
54
/// <description>
55
/// |Lₜ - Cₜ₋₁| => |Lₜ - Cₜ| - 0.5 * |Hₜ - Cₜ₋₁| + 0.25 * |Cₜ₋₁ - Oₜ₋₁|
56
/// </description>
57
/// </item>
58
/// <item>
59
/// <description>
60
/// |Hₜ - Lₜ| => |Hₜ - Lₜ₋₁| + 0.25 * |Cₜ₋₁ - Oₜ₋₁|
61
/// </description>
62
/// </item>
63
/// </list>
64
/// </para>
65
/// <para>
66
/// <i>See <see cref="GetRValue"/></i>
67
/// </para>
68
/// </description>
69
/// </item>
70
/// <item>
71
/// <term>K</term>
72
/// <description>
73
/// Found by selecting the larger of the two expressions:
74
/// |Hₜ - Cₜ₋₁|, |Lₜ - Cₜ₋₁|
75
/// <para>
76
/// <i>See <see cref="GetKValue"/></i>
77
/// </para>
78
/// </description>
79
/// </item>
80
/// <item>
81
/// <term>T</term>
82
/// <description>
83
/// The limit move, or the maximum change in price during the time
84
/// period for the bar. Passed as limitMove via the constructor.
85
/// <para>
86
/// <i>See <see cref="T"/></i>
87
/// </para>
88
/// </description>
89
/// </item>
90
/// </list>
91
/// </para>
92
/// </summary>
93
/// <seealso cref="WilderAccumulativeSwingIndex"/>
94
public
class
WilderSwingIndex
:
TradeBarIndicator
,
IIndicatorWarmUpPeriodProvider
95
{
96
/// <summary>
97
/// Holds the bar for the current period.
98
/// </summary>
99
protected
IBaseDataBar
_currentInput
{
get
;
private
set
; }
100
101
/// <summary>
102
/// Holds the bar for the previous period.
103
/// </summary>
104
protected
IBaseDataBar
_previousInput
{
get
;
private
set
; }
105
106
/// <summary>
107
/// Gets the value for T (the limit move value) set in the constructor.
108
/// </summary>
109
private
readonly decimal T;
110
111
/// <summary>
112
/// Initializes a new instance of the <see cref="WilderSwingIndex"/> class using the specified name.
113
/// </summary>
114
/// <param name="name">A string for the name of this indicator.</param>
115
/// <param name="limitMove">A decimal representing the limit move value for the period.</param>
116
public
WilderSwingIndex
(
string
name, decimal limitMove)
117
: base(name)
118
{
119
T = Math.Abs(limitMove);
120
}
121
122
/// <summary>
123
/// Initializes a new instance of the <see cref="WilderSwingIndex"/> class using the default name.
124
/// </summary>
125
/// <param name="limitMove">A decimal representing the limit move value for the period.</param>
126
public
WilderSwingIndex
(decimal limitMove)
127
: this(
"SI"
, limitMove)
128
{
129
}
130
131
/// <summary>
132
/// Gets a flag indicating when this indicator is ready and fully initialized.
133
/// </summary>
134
public
override
bool
IsReady
=> Samples > 1;
135
136
/// <summary>
137
/// Required period, in data points, for the indicator to be ready and fully initialized.
138
/// </summary>
139
public
int
WarmUpPeriod
=> 2;
140
141
/// <summary>
142
/// Computes the next value of this indicator from the given state.
143
/// </summary>
144
/// <param name="input">The input given to the indicator.</param>
145
/// <returns>A new value for this indicator.</returns>
146
protected
override
decimal
ComputeNextValue
(
TradeBar
input)
147
{
148
if
(!
IsReady
)
149
{
150
_currentInput
= input;
151
return
0m;
152
}
153
154
_previousInput
=
_currentInput
;
155
_currentInput
= input;
156
157
var N = GetNValue();
158
var R = GetRValue();
159
var K = GetKValue();
160
161
if
(R == decimal.Zero || T == decimal.Zero)
162
{
163
return
0m;
164
}
165
return
50m * (N / R) * (K / T);
166
}
167
168
/// <summary>
169
/// Gets the value for N.
170
/// <para>
171
/// N = Cₜ - Cₜ₋₁ + 0.5 * (Cₜ - Oₜ) + 0.25 * (Cₜ₋₁ - Oₜ₋₁)
172
/// </para>
173
/// </summary>
174
private
decimal GetNValue()
175
{
176
return
(
_currentInput
.
Close
-
_previousInput
.
Close
)
177
+ (0.5m * (
_currentInput
.
Close
-
_currentInput
.
Open
))
178
+ (0.25m * (
_previousInput
.
Close
-
_previousInput
.
Open
));
179
}
180
181
/// <summary>
182
/// Gets the value for R, determined by using the formula corresponding
183
/// to the expression with the largest value.
184
/// <para>
185
/// <i>Expressions:</i>
186
/// <list type="number">
187
/// <item>
188
/// <description>|Hₜ - Cₜ₋₁|</description>
189
/// </item>
190
/// <item>
191
/// <description>|Lₜ - Cₜ₋₁|</description>
192
/// </item>
193
/// <item>
194
/// <description>|Hₜ - Lₜ|</description>
195
/// </item>
196
/// </list>
197
/// </para>
198
/// <para>
199
/// <i>Formulas:</i>
200
/// <list type="number">
201
/// <item>
202
/// <description>|Hₜ - Cₜ₋₁| - 0.5 * |Lₜ - Cₜ₋₁| + 0.25 * |Cₜ₋₁ - Oₜ₋₁|</description>
203
/// </item>
204
/// <item>
205
/// <description>|Lₜ - Cₜ₋₁| - 0.5 * |Hₜ - Cₜ₋₁| + 0.25 * |Cₜ₋₁ - Oₜ₋₁|</description>
206
/// </item>
207
/// <item>
208
/// <description>|Hₜ - Lₜ| + 0.25 * |Cₜ₋₁ - Oₜ₋₁|</description>
209
/// </item>
210
/// </list>
211
/// </para>
212
/// </summary>
213
private
decimal GetRValue()
214
{
215
var expressions =
new
decimal[]
216
{
217
Math.Abs(
_currentInput
.
High
-
_previousInput
.
Close
),
218
Math.Abs(
_currentInput
.
Low
-
_previousInput
.
Close
),
219
Math.Abs(
_currentInput
.
High
-
_currentInput
.
Low
)
220
};
221
222
int
expressionIndex = Array.IndexOf(expressions, expressions.Max());
223
224
decimal result;
225
switch
(expressionIndex)
226
{
227
case
0:
228
result = Math.Abs(
_currentInput
.
High
-
_previousInput
.
Close
)
229
- Math.Abs(0.5m * (
_currentInput
.
Low
-
_previousInput
.
Close
))
230
+ Math.Abs(0.25m * (
_previousInput
.
Close
-
_previousInput
.
Open
));
231
break
;
232
233
case
1:
234
result = Math.Abs(
_currentInput
.
Low
-
_previousInput
.
Close
)
235
- Math.Abs(0.5m * (
_currentInput
.
High
-
_previousInput
.
Close
))
236
+ Math.Abs(0.25m * (
_previousInput
.
Close
-
_previousInput
.
Open
));
237
break
;
238
239
case
2:
240
result = Math.Abs(
_currentInput
.
High
-
_currentInput
.
Low
)
241
+ Math.Abs(0.25m * (
_previousInput
.
Close
-
_previousInput
.
Open
));
242
break
;
243
244
default
:
245
result = 0m;
246
break
;
247
}
248
249
return
result;
250
}
251
252
/// <summary>
253
/// Gets the value for K, which is equal to the larger of the two following expressions.
254
/// <para>
255
/// <i>Expressions:</i>
256
/// <list type="number">
257
/// <item>
258
/// <description>|Hₜ - Cₜ₋₁|</description>
259
/// </item>
260
/// <item>
261
/// <description>|Lₜ - Cₜ₋₁|</description>
262
/// </item>
263
/// </list>
264
/// </para>
265
/// </summary>
266
private
decimal GetKValue()
267
{
268
var values =
new
decimal[]
269
{
270
_currentInput
.
High
-
_previousInput
.
Close
,
271
_currentInput
.
Low
-
_previousInput
.
Close
272
};
273
274
return
values.Max(x => Math.Abs(x));
275
}
276
}
277
}
Indicators
WilderSwingIndex.cs
Generated by
1.8.17