Lean  $LEAN_TAG$
GapSideBySideWhite.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  /// Up/Down-gap side-by-side white lines candlestick pattern
23  /// </summary>
24  /// <remarks>
25  /// Must have:
26  /// - upside or downside gap (between the bodies)
27  /// - first candle after the window: white candlestick
28  /// - second candle after the window: white candlestick with similar size(near the same) and about the same
29  /// open(equal) of the previous candle
30  /// - the second candle does not close the window
31  /// The meaning of "near" and "equal" is specified with SetCandleSettings
32  /// The returned value is positive(+1) or negative(-1): the user should consider that upside
33  /// or downside gap side-by-side white lines is significant when it appears in a trend, while this function
34  /// does not consider the trend
35  /// </remarks>
37  {
38  private readonly int _nearAveragePeriod;
39  private readonly int _equalAveragePeriod;
40 
41  private decimal _nearPeriodTotal;
42  private decimal _equalPeriodTotal;
43 
44  /// <summary>
45  /// Initializes a new instance of the <see cref="GapSideBySideWhite"/> class using the specified name.
46  /// </summary>
47  /// <param name="name">The name of this indicator</param>
48  public GapSideBySideWhite(string name)
49  : base(name, Math.Max(CandleSettings.Get(CandleSettingType.Near).AveragePeriod, CandleSettings.Get(CandleSettingType.Equal).AveragePeriod) + 2 + 1)
50  {
51  _nearAveragePeriod = CandleSettings.Get(CandleSettingType.Near).AveragePeriod;
52  _equalAveragePeriod = CandleSettings.Get(CandleSettingType.Equal).AveragePeriod;
53  }
54 
55  /// <summary>
56  /// Initializes a new instance of the <see cref="GapSideBySideWhite"/> class.
57  /// </summary>
59  : this("GAPSIDEBYSIDEWHITE")
60  {
61  }
62 
63  /// <summary>
64  /// Gets a flag indicating when this indicator is ready and fully initialized
65  /// </summary>
66  public override bool IsReady
67  {
68  get { return Samples >= Period; }
69  }
70 
71  /// <summary>
72  /// Computes the next value of this indicator from the given state
73  /// </summary>
74  /// <param name="window">The window of data held in this indicator</param>
75  /// <param name="input">The input given to the indicator</param>
76  /// <returns>A new value for this indicator</returns>
77  protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
78  {
79  if (!IsReady)
80  {
81  if (Samples >= Period - _nearAveragePeriod)
82  {
83  _nearPeriodTotal += GetCandleRange(CandleSettingType.Near, window[1]);
84  }
85 
86  if (Samples >= Period - _equalAveragePeriod)
87  {
88  _equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]);
89  }
90 
91  return 0m;
92  }
93 
94  decimal value;
95  if (
96  ( // upside or downside gap between the 1st candle and both the next 2 candles
97  (GetRealBodyGapUp(window[1], window[2]) && GetRealBodyGapUp(input, window[2]))
98  ||
99  (GetRealBodyGapDown(window[1], window[2]) && GetRealBodyGapDown(input, window[2]))
100  ) &&
101  // 2nd: white
102  GetCandleColor(window[1]) == CandleColor.White &&
103  // 3rd: white
104  GetCandleColor(input) == CandleColor.White &&
105  // same size 2 and 3
106  GetRealBody(input) >= GetRealBody(window[1]) - GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, window[1]) &&
107  GetRealBody(input) <= GetRealBody(window[1]) + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, window[1]) &&
108  // same open 2 and 3
109  input.Open >= window[1].Open - GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1]) &&
110  input.Open <= window[1].Open + GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1])
111  )
112  value = GetRealBodyGapUp(window[1], window[2]) ? 1m : -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  _nearPeriodTotal += GetCandleRange(CandleSettingType.Near, window[1]) -
120  GetCandleRange(CandleSettingType.Near, window[1 + _nearAveragePeriod]);
121 
122  _equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]) -
123  GetCandleRange(CandleSettingType.Equal, window[1 + _equalAveragePeriod]);
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  _nearPeriodTotal = 0;
134  _equalPeriodTotal = 0;
135  base.Reset();
136  }
137  }
138 }