Lean  $LEAN_TAG$
ConcealedBabySwallow.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  /// Concealed Baby Swallow candlestick pattern
23  /// </summary>
24  /// <remarks>
25  /// Must have:
26  /// - first candle: black marubozu (very short shadows)
27  /// - second candle: black marubozu(very short shadows)
28  /// - third candle: black candle that opens gapping down but has an upper shadow that extends into the prior body
29  /// - fourth candle: black candle that completely engulfs the third candle, including the shadows
30  /// The meanings of "very short shadow" are specified with SetCandleSettings;
31  /// The returned value is positive(+1): concealing baby swallow is always bullish;
32  /// The user should consider that concealing baby swallow is significant when it appears in downtrend, while
33  /// this function does not consider it
34  /// </remarks>
36  {
37  private readonly int _shadowVeryShortAveragePeriod;
38 
39  private decimal[] _shadowVeryShortPeriodTotal = new decimal[4];
40 
41  /// <summary>
42  /// Initializes a new instance of the <see cref="ConcealedBabySwallow"/> class using the specified name.
43  /// </summary>
44  /// <param name="name">The name of this indicator</param>
45  public ConcealedBabySwallow(string name)
46  : base(name, CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod + 3 + 1)
47  {
48  _shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
49  }
50 
51  /// <summary>
52  /// Initializes a new instance of the <see cref="ConcealedBabySwallow"/> class.
53  /// </summary>
55  : this("CONCEALEDBABYSWALLOW")
56  {
57  }
58 
59  /// <summary>
60  /// Gets a flag indicating when this indicator is ready and fully initialized
61  /// </summary>
62  public override bool IsReady
63  {
64  get { return Samples >= Period; }
65  }
66 
67  /// <summary>
68  /// Computes the next value of this indicator from the given state
69  /// </summary>
70  /// <param name="window">The window of data held in this indicator</param>
71  /// <param name="input">The input given to the indicator</param>
72  /// <returns>A new value for this indicator</returns>
73  protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
74  {
75  if (!IsReady)
76  {
77  if (Samples >= Period - _shadowVeryShortAveragePeriod)
78  {
79  _shadowVeryShortPeriodTotal[3] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[3]);
80  _shadowVeryShortPeriodTotal[2] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[2]);
81  _shadowVeryShortPeriodTotal[1] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[1]);
82  }
83 
84  return 0m;
85  }
86 
87  decimal value;
88  if (
89  // 1st black
90  GetCandleColor(window[3]) == CandleColor.Black &&
91  // 2nd black
92  GetCandleColor(window[2]) == CandleColor.Black &&
93  // 3rd black
94  GetCandleColor(window[1]) == CandleColor.Black &&
95  // 4th black
96  GetCandleColor(input) == CandleColor.Black &&
97  // 1st: marubozu
98  GetLowerShadow(window[3]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[3], window[3]) &&
99  GetUpperShadow(window[3]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[3], window[3]) &&
100  // 2nd: marubozu
101  GetLowerShadow(window[2]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[2], window[2]) &&
102  GetUpperShadow(window[2]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[2], window[2]) &&
103  // 3rd: opens gapping down
104  GetRealBodyGapDown(window[1], window[2]) &&
105  // and has an upper shadow
106  GetUpperShadow(window[1]) > GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[1], window[1]) &&
107  // that extends into the prior body
108  window[1].High > window[2].Close &&
109  // 4th: engulfs the 3rd including the shadows
110  input.High > window[1].High && input.Low < window[1].Low
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  for (var i = 3; i >= 1; i--)
120  {
121  _shadowVeryShortPeriodTotal[i] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[i]) -
122  GetCandleRange(CandleSettingType.ShadowVeryShort, window[i + _shadowVeryShortAveragePeriod]);
123  }
124 
125  return value;
126  }
127 
128  /// <summary>
129  /// Resets this indicator to its initial state
130  /// </summary>
131  public override void Reset()
132  {
133  _shadowVeryShortPeriodTotal = new decimal[4];
134  base.Reset();
135  }
136  }
137 }