Lean  $LEAN_TAG$
InvertedHammer.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 
20 {
21  /// <summary>
22  /// Inverted Hammer candlestick pattern indicator
23  /// </summary>
24  /// <remarks>
25  /// Must have:
26  /// - small real body
27  /// - long upper shadow
28  /// - no, or very short, lower shadow
29  /// - gap down
30  /// The meaning of "short", "very short" and "long" is specified with SetCandleSettings;
31  /// The returned value is positive(+1): inverted hammer is always bullish;
32  /// The user should consider that an inverted hammer must appear in a downtrend, while this function does not consider it
33  /// </remarks>
35  {
36  private readonly int _bodyShortAveragePeriod;
37  private readonly int _shadowLongAveragePeriod;
38  private readonly int _shadowVeryShortAveragePeriod;
39 
40  private decimal _bodyShortPeriodTotal;
41  private decimal _shadowLongPeriodTotal;
42  private decimal _shadowVeryShortPeriodTotal;
43 
44  /// <summary>
45  /// Initializes a new instance of the <see cref="InvertedHammer"/> class using the specified name.
46  /// </summary>
47  /// <param name="name">The name of this indicator</param>
48  public InvertedHammer(string name)
49  : base(name, Math.Max(Math.Max(CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod),
50  CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod) + 1 + 1)
51  {
52  _bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
53  _shadowLongAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod;
54  _shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
55  }
56 
57  /// <summary>
58  /// Initializes a new instance of the <see cref="InvertedHammer"/> class.
59  /// </summary>
60  public InvertedHammer()
61  : this("INVERTEDHAMMER")
62  {
63  }
64 
65  /// <summary>
66  /// Gets a flag indicating when this indicator is ready and fully initialized
67  /// </summary>
68  public override bool IsReady
69  {
70  get { return Samples >= Period; }
71  }
72 
73  /// <summary>
74  /// Computes the next value of this indicator from the given state
75  /// </summary>
76  /// <param name="window">The window of data held in this indicator</param>
77  /// <param name="input">The input given to the indicator</param>
78  /// <returns>A new value for this indicator</returns>
79  protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
80  {
81  if (!IsReady)
82  {
83  if (Samples >= Period - _bodyShortAveragePeriod)
84  {
85  _bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
86  }
87 
88  if (Samples >= Period - _shadowLongAveragePeriod)
89  {
90  _shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, input);
91  }
92 
93  if (Samples >= Period - _shadowVeryShortAveragePeriod)
94  {
95  _shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
96  }
97 
98  return 0m;
99  }
100 
101  decimal value;
102  if (
103  // small rb
104  GetRealBody(input) < GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
105  // long upper shadow
106  GetUpperShadow(input) > GetCandleAverage(CandleSettingType.ShadowLong, _shadowLongPeriodTotal, input) &&
107  // very short lower shadow
108  GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input) &&
109  // gap down
110  GetRealBodyGapDown(input, window[1])
111  )
112  value = 1m;
113  else
114  value = 0m;
115 
116  // add the current range and subtract the first range: this is done after the pattern recognition
117  // when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
118 
119  _bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
120  GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
121 
122  _shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, input) -
123  GetCandleRange(CandleSettingType.ShadowLong, window[_shadowLongAveragePeriod]);
124 
125  _shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input) -
126  GetCandleRange(CandleSettingType.ShadowVeryShort, window[_shadowVeryShortAveragePeriod]);
127 
128  return value;
129  }
130 
131  /// <summary>
132  /// Resets this indicator to its initial state
133  /// </summary>
134  public override void Reset()
135  {
136  _bodyShortPeriodTotal = 0m;
137  _shadowLongPeriodTotal = 0m;
138  _shadowVeryShortPeriodTotal = 0m;
139  base.Reset();
140  }
141  }
142 }