Lean  $LEAN_TAG$
Breakaway.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 
17 
19 {
20  /// <summary>
21  /// Breakaway candlestick pattern indicator
22  /// </summary>
23  /// <remarks>
24  /// Must have:
25  /// - first candle: long black(white)
26  /// - second candle: black(white) day whose body gaps down(up)
27  /// - third candle: black or white day with lower(higher) high and lower(higher) low than prior candle's
28  /// - fourth candle: black(white) day with lower(higher) high and lower(higher) low than prior candle's
29  /// - fifth candle: white(black) day that closes inside the gap, erasing the prior 3 days
30  /// The meaning of "long" is specified with SetCandleSettings
31  /// The returned value is positive(+1) when bullish or negative(-1) when bearish;
32  /// The user should consider that breakaway is significant in a trend opposite to the last candle, while this
33  /// function does not consider it
34  /// </remarks>
36  {
37  private readonly int _bodyLongAveragePeriod;
38 
39  private decimal _bodyLongPeriodTotal;
40 
41  /// <summary>
42  /// Initializes a new instance of the <see cref="Breakaway"/> class using the specified name.
43  /// </summary>
44  /// <param name="name">The name of this indicator</param>
45  public Breakaway(string name)
46  : base(name, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod + 4 + 1)
47  {
48  _bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
49  }
50 
51  /// <summary>
52  /// Initializes a new instance of the <see cref="Breakaway"/> class.
53  /// </summary>
54  public Breakaway()
55  : this("BREAKAWAY")
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 - _bodyLongAveragePeriod)
78  {
79  _bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[4]);
80  }
81 
82  return 0m;
83  }
84 
85  decimal value;
86  if (
87  // 1st long
88  GetRealBody(window[4]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[4]) &&
89  // 1st, 2nd, 4th same color, 5th opposite
90  GetCandleColor(window[4]) == GetCandleColor(window[3]) &&
91  GetCandleColor(window[3]) == GetCandleColor(window[1]) &&
92  (int)GetCandleColor(window[1]) == -(int)GetCandleColor(input) &&
93  (
94  (
95  // when 1st is black:
96  GetCandleColor(window[4]) == CandleColor.Black &&
97  // 2nd gaps down
98  GetRealBodyGapDown(window[3], window[4]) &&
99  // 3rd has lower high and low than 2nd
100  window[2].High < window[3].High && window[2].Low < window[3].Low &&
101  // 4th has lower high and low than 3rd
102  window[1].High < window[2].High && window[1].Low < window[2].Low &&
103  // 5th closes inside the gap
104  input.Close > window[3].Open && input.Close < window[4].Close
105  )
106  ||
107  (
108  // when 1st is white:
109  GetCandleColor(window[4]) == CandleColor.White &&
110  // 2nd gaps up
111  GetRealBodyGapUp(window[3], window[4]) &&
112  // 3rd has higher high and low than 2nd
113  window[2].High > window[3].High && window[2].Low > window[3].Low &&
114  // 4th has higher high and low than 3rd
115  window[1].High > window[2].High && window[1].Low > window[2].Low &&
116  // 5th closes inside the gap
117  input.Close < window[3].Open && input.Close > window[4].Close
118  )
119  )
120  )
121  value = (int)GetCandleColor(input);
122  else
123  value = 0m;
124 
125  // add the current range and subtract the first range: this is done after the pattern recognition
126  // when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
127 
128  _bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[4]) -
129  GetCandleRange(CandleSettingType.BodyLong, window[4 + _bodyLongAveragePeriod]);
130 
131  return value;
132  }
133 
134  /// <summary>
135  /// Resets this indicator to its initial state
136  /// </summary>
137  public override void Reset()
138  {
139  _bodyLongPeriodTotal = 0m;
140  base.Reset();
141  }
142  }
143 }