chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:02:50 +08:00
commit 0fc60fdcb1
5008 changed files with 910633 additions and 0 deletions
@@ -0,0 +1,184 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Abandoned Baby candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long white (black) real body
/// - second candle: doji
/// - third candle: black(white) real body that moves well within the first candle's real body
/// - upside(downside) gap between the first candle and the doji(the shadows of the two candles don't touch)
/// - downside (upside) gap between the doji and the third candle(the shadows of the two candles don't touch)
/// The meaning of "doji" and "long" is specified with SetCandleSettings
/// The meaning of "moves well within" is specified with penetration and "moves" should mean the real body should
/// not be short ("short" is specified with SetCandleSettings) - Greg Morris wants it to be long, someone else want
/// it to be relatively long
/// The returned value is positive (+1) when it's an abandoned baby bottom or negative (-1) when it's
/// an abandoned baby top; the user should consider that an abandoned baby is significant when it appears in
/// an uptrend or downtrend, while this function does not consider the trend
/// </remarks>
public class AbandonedBaby : CandlestickPattern
{
private readonly decimal _penetration;
private readonly int _bodyDojiAveragePeriod;
private readonly int _bodyLongAveragePeriod;
private readonly int _bodyShortAveragePeriod;
private decimal _bodyDojiPeriodTotal;
private decimal _bodyLongPeriodTotal;
private decimal _bodyShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="AbandonedBaby"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
/// <param name="penetration">Percentage of penetration of a candle within another candle</param>
public AbandonedBaby(string name, decimal penetration = 0.3m)
: base(name, Math.Max(Math.Max(CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod),
CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod) + 2)
{
_penetration = penetration;
_bodyDojiAveragePeriod = CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod;
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="AbandonedBaby"/> class.
/// </summary>
/// <param name="penetration">Percentage of penetration of a candle within another candle</param>
public AbandonedBaby(decimal penetration)
: this("ABANDONEDBABY", penetration)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="AbandonedBaby"/> class.
/// </summary>
public AbandonedBaby()
: this("ABANDONEDBABY")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples > Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples > Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[2]);
}
if (Samples > Period - _bodyDojiAveragePeriod)
{
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, window[1]);
}
if (Samples > Period - _bodyShortAveragePeriod)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
return 0m;
}
decimal value;
if (
// 1st: long
GetRealBody(window[2]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[2]) &&
// 2nd: doji
GetRealBody(window[1]) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, window[1]) &&
// 3rd: longer than short
GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
((
// 1st white
GetCandleColor(window[2]) == CandleColor.White &&
// 3rd black
GetCandleColor(input) == CandleColor.Black &&
// 3rd closes well within 1st rb
input.Close < window[2].Close - GetRealBody(window[2]) * _penetration &&
// upside gap between 1st and 2nd
GetCandleGapUp(window[1], window[2]) &&
// downside gap between 2nd and 3rd
GetCandleGapDown(input, window[1])
)
||
(
// 1st black
GetCandleColor(window[2]) == CandleColor.Black &&
// 3rd white
GetCandleColor(input) == CandleColor.White &&
// 3rd closes well within 1st rb
input.Close > window[2].Close + GetRealBody(window[2]) * _penetration &&
// downside gap between 1st and 2nd
GetCandleGapDown(window[1], window[2]) &&
// upside gap between 2nd and 3rd
GetCandleGapUp(input, window[1])
)
)
)
value = (int)GetCandleColor(input);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[2]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod - 1]);
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, window[1]) -
GetCandleRange(CandleSettingType.BodyDoji, window[_bodyDojiAveragePeriod]);
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod + 1]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0;
_bodyDojiPeriodTotal = 0;
_bodyShortPeriodTotal = 0;
base.Reset();
}
}
}
@@ -0,0 +1,222 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Advance Block candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - three white candlesticks with consecutively higher closes
/// - each candle opens within or near the previous white real body
/// - first candle: long white with no or very short upper shadow(a short shadow is accepted too for more flexibility)
/// - second and third candles, or only third candle, show signs of weakening: progressively smaller white real bodies
/// and/or relatively long upper shadows; see below for specific conditions
/// The meanings of "long body", "short shadow", "far" and "near" are specified with SetCandleSettings;
/// The returned value is negative(-1): advance block is always bearish;
/// The user should consider that advance block is significant when it appears in uptrend, while this function
/// does not consider it
/// </remarks>
public class AdvanceBlock : CandlestickPattern
{
private readonly int _shadowShortAveragePeriod;
private readonly int _shadowLongAveragePeriod;
private readonly int _nearAveragePeriod;
private readonly int _farAveragePeriod;
private readonly int _bodyLongAveragePeriod;
private decimal[] _shadowShortPeriodTotal = new decimal[3];
private decimal[] _shadowLongPeriodTotal = new decimal[2];
private decimal[] _nearPeriodTotal = new decimal[3];
private decimal[] _farPeriodTotal = new decimal[3];
private decimal _bodyLongPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="AdvanceBlock"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public AdvanceBlock(string name)
: base(name, Math.Max(Math.Max(Math.Max(CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowShort).AveragePeriod),
Math.Max(CandleSettings.Get(CandleSettingType.Far).AveragePeriod, CandleSettings.Get(CandleSettingType.Near).AveragePeriod)),
CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod) + 2 + 1)
{
_shadowShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowShort).AveragePeriod;
_shadowLongAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod;
_nearAveragePeriod = CandleSettings.Get(CandleSettingType.Near).AveragePeriod;
_farAveragePeriod = CandleSettings.Get(CandleSettingType.Far).AveragePeriod;
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="AdvanceBlock"/> class.
/// </summary>
public AdvanceBlock()
: this("ADVANCEBLOCK")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _shadowShortAveragePeriod)
{
_shadowShortPeriodTotal[2] += GetCandleRange(CandleSettingType.ShadowShort, window[2]);
_shadowShortPeriodTotal[1] += GetCandleRange(CandleSettingType.ShadowShort, window[1]);
_shadowShortPeriodTotal[0] += GetCandleRange(CandleSettingType.ShadowShort, input);
}
if (Samples >= Period - _shadowLongAveragePeriod)
{
_shadowLongPeriodTotal[1] += GetCandleRange(CandleSettingType.ShadowLong, window[1]);
_shadowLongPeriodTotal[0] += GetCandleRange(CandleSettingType.ShadowLong, input);
}
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[2]);
}
if (Samples >= Period - _nearAveragePeriod)
{
_nearPeriodTotal[2] += GetCandleRange(CandleSettingType.Near, window[2]);
_nearPeriodTotal[1] += GetCandleRange(CandleSettingType.Near, window[1]);
}
if (Samples >= Period - _farAveragePeriod)
{
_farPeriodTotal[2] += GetCandleRange(CandleSettingType.Far, window[2]);
_farPeriodTotal[1] += GetCandleRange(CandleSettingType.Far, window[1]);
}
return 0m;
}
decimal value;
if (
// 1st white
GetCandleColor(window[2]) == CandleColor.White &&
// 2nd white
GetCandleColor(window[1]) == CandleColor.White &&
// 3rd white
GetCandleColor(input) == CandleColor.White &&
// consecutive higher closes
input.Close > window[1].Close && window[1].Close > window[2].Close &&
// 2nd opens within/near 1st real body
window[1].Open > window[2].Open &&
window[1].Open <= window[2].Close + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal[2], window[2]) &&
// 3rd opens within/near 2nd real body
input.Open > window[1].Open &&
input.Open <= window[1].Close + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal[1], window[1]) &&
// 1st: long real body
GetRealBody(window[2]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[2]) &&
// 1st: short upper shadow
GetUpperShadow(window[2]) < GetCandleAverage(CandleSettingType.ShadowShort, _shadowShortPeriodTotal[2], window[2]) &&
(
// ( 2 far smaller than 1 && 3 not longer than 2 )
// advance blocked with the 2nd, 3rd must not carry on the advance
(
GetRealBody(window[1]) < GetRealBody(window[2]) - GetCandleAverage(CandleSettingType.Far, _farPeriodTotal[2], window[2]) &&
GetRealBody(input) < GetRealBody(window[1]) + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal[1], window[1])
) ||
// 3 far smaller than 2
// advance blocked with the 3rd
(
GetRealBody(input) < GetRealBody(window[1]) - GetCandleAverage(CandleSettingType.Far, _farPeriodTotal[1], window[1])
) ||
// ( 3 smaller than 2 && 2 smaller than 1 && (3 or 2 not short upper shadow) )
// advance blocked with progressively smaller real bodies and some upper shadows
(
GetRealBody(input) < GetRealBody(window[1]) &&
GetRealBody(window[1]) < GetRealBody(window[2]) &&
(
GetUpperShadow(input) > GetCandleAverage(CandleSettingType.ShadowShort, _shadowShortPeriodTotal[0], input) ||
GetUpperShadow(window[1]) > GetCandleAverage(CandleSettingType.ShadowShort, _shadowShortPeriodTotal[1], window[1])
)
) ||
// ( 3 smaller than 2 && 3 long upper shadow )
// advance blocked with 3rd candle's long upper shadow and smaller body
(
GetRealBody(input) < GetRealBody(window[1]) &&
GetUpperShadow(input) > GetCandleAverage(CandleSettingType.ShadowLong, _shadowLongPeriodTotal[0], input)
)
)
)
value = -1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
for (var i = 2; i >= 0; i--)
{
_shadowShortPeriodTotal[i] += GetCandleRange(CandleSettingType.ShadowShort, window[i]) -
GetCandleRange(CandleSettingType.ShadowShort, window[i + _shadowShortAveragePeriod]);
}
for (var i = 1; i >= 0; i--)
{
_shadowLongPeriodTotal[i] += GetCandleRange(CandleSettingType.ShadowLong, window[i]) -
GetCandleRange(CandleSettingType.ShadowLong, window[i + _shadowLongAveragePeriod]);
}
for (var i = 2; i >= 1; i--)
{
_farPeriodTotal[i] += GetCandleRange(CandleSettingType.Far, window[i]) -
GetCandleRange(CandleSettingType.Far, window[i + _farAveragePeriod]);
_nearPeriodTotal[i] += GetCandleRange(CandleSettingType.Near, window[i]) -
GetCandleRange(CandleSettingType.Near, window[i + _nearAveragePeriod]);
}
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[2]) -
GetCandleRange(CandleSettingType.BodyLong, window[2 + _bodyLongAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_shadowShortPeriodTotal = new decimal[3];
_shadowLongPeriodTotal = new decimal[2];
_nearPeriodTotal = new decimal[3];
_farPeriodTotal = new decimal[3];
_bodyLongPeriodTotal = 0;
base.Reset();
}
}
}
+131
View File
@@ -0,0 +1,131 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Belt-hold candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - long white(black) real body
/// - no or very short lower(upper) shadow
/// The meaning of "long" and "very short" is specified with SetCandleSettings
/// The returned value is positive(+1) when white(bullish), negative(-1) when black(bearish)
/// </remarks>
public class BeltHold : CandlestickPattern
{
private readonly int _bodyLongAveragePeriod;
private readonly int _shadowVeryShortAveragePeriod;
private decimal _bodyLongPeriodTotal;
private decimal _shadowVeryShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="BeltHold"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public BeltHold(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod) + 1)
{
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="BeltHold"/> class.
/// </summary>
public BeltHold()
: this("BELTHOLD")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
}
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
return 0m;
}
decimal value;
if (
// long body
GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, input) &&
(
(
// white body and very short lower shadow
GetCandleColor(input) == CandleColor.White &&
GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input)
) ||
(
// black body and very short upper shadow
GetCandleColor(input) == CandleColor.Black &&
GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input)
)
))
value = (int)GetCandleColor(input);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod]);
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[_shadowVeryShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0m;
_shadowVeryShortPeriodTotal = 0m;
base.Reset();
}
}
}
+143
View File
@@ -0,0 +1,143 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Breakaway candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long black(white)
/// - second candle: black(white) day whose body gaps down(up)
/// - third candle: black or white day with lower(higher) high and lower(higher) low than prior candle's
/// - fourth candle: black(white) day with lower(higher) high and lower(higher) low than prior candle's
/// - fifth candle: white(black) day that closes inside the gap, erasing the prior 3 days
/// The meaning of "long" is specified with SetCandleSettings
/// The returned value is positive(+1) when bullish or negative(-1) when bearish;
/// The user should consider that breakaway is significant in a trend opposite to the last candle, while this
/// function does not consider it
/// </remarks>
public class Breakaway : CandlestickPattern
{
private readonly int _bodyLongAveragePeriod;
private decimal _bodyLongPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="Breakaway"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public Breakaway(string name)
: base(name, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod + 4 + 1)
{
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="Breakaway"/> class.
/// </summary>
public Breakaway()
: this("BREAKAWAY")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[4]);
}
return 0m;
}
decimal value;
if (
// 1st long
GetRealBody(window[4]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[4]) &&
// 1st, 2nd, 4th same color, 5th opposite
GetCandleColor(window[4]) == GetCandleColor(window[3]) &&
GetCandleColor(window[3]) == GetCandleColor(window[1]) &&
(int)GetCandleColor(window[1]) == -(int)GetCandleColor(input) &&
(
(
// when 1st is black:
GetCandleColor(window[4]) == CandleColor.Black &&
// 2nd gaps down
GetRealBodyGapDown(window[3], window[4]) &&
// 3rd has lower high and low than 2nd
window[2].High < window[3].High && window[2].Low < window[3].Low &&
// 4th has lower high and low than 3rd
window[1].High < window[2].High && window[1].Low < window[2].Low &&
// 5th closes inside the gap
input.Close > window[3].Open && input.Close < window[4].Close
)
||
(
// when 1st is white:
GetCandleColor(window[4]) == CandleColor.White &&
// 2nd gaps up
GetRealBodyGapUp(window[3], window[4]) &&
// 3rd has higher high and low than 2nd
window[2].High > window[3].High && window[2].Low > window[3].Low &&
// 4th has higher high and low than 3rd
window[1].High > window[2].High && window[1].Low > window[2].Low &&
// 5th closes inside the gap
input.Close < window[3].Open && input.Close > window[4].Close
)
)
)
value = (int)GetCandleColor(input);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[4]) -
GetCandleRange(CandleSettingType.BodyLong, window[4 + _bodyLongAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,118 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Types of candlestick settings
/// </summary>
public enum CandleSettingType
{
/// <summary>
/// Real body is long when it's longer than the average of the 10 previous candles' real body (0)
/// </summary>
BodyLong,
/// <summary>
/// Real body is very long when it's longer than 3 times the average of the 10 previous candles' real body (1)
/// </summary>
BodyVeryLong,
/// <summary>
/// Real body is short when it's shorter than the average of the 10 previous candles' real bodies (2)
/// </summary>
BodyShort,
/// <summary>
/// Real body is like doji's body when it's shorter than 10% the average of the 10 previous candles' high-low range (3)
/// </summary>
BodyDoji,
/// <summary>
/// Shadow is long when it's longer than the real body (4)
/// </summary>
ShadowLong,
/// <summary>
/// Shadow is very long when it's longer than 2 times the real body (5)
/// </summary>
ShadowVeryLong,
/// <summary>
/// Shadow is short when it's shorter than half the average of the 10 previous candles' sum of shadows (6)
/// </summary>
ShadowShort,
/// <summary>
/// Shadow is very short when it's shorter than 10% the average of the 10 previous candles' high-low range (7)
/// </summary>
ShadowVeryShort,
/// <summary>
/// When measuring distance between parts of candles or width of gaps
/// "near" means "&lt;= 20% of the average of the 5 previous candles' high-low range" (8)
/// </summary>
Near,
/// <summary>
/// When measuring distance between parts of candles or width of gaps
/// "far" means "&gt;= 60% of the average of the 5 previous candles' high-low range" (9)
/// </summary>
Far,
/// <summary>
/// When measuring distance between parts of candles or width of gaps
/// "equal" means "&lt;= 5% of the average of the 5 previous candles' high-low range" (10)
/// </summary>
Equal
}
/// <summary>
/// Types of candlestick ranges
/// </summary>
public enum CandleRangeType
{
/// <summary>
/// The part of the candle between open and close (0)
/// </summary>
RealBody,
/// <summary>
/// The complete range of the candle (1)
/// </summary>
HighLow,
/// <summary>
/// The shadows (or tails) of the candle (2)
/// </summary>
Shadows
}
/// <summary>
/// Colors of a candle
/// </summary>
public enum CandleColor
{
/// <summary>
/// White is an up candle (close higher or equal than open) (1)
/// </summary>
White = 1,
/// <summary>
/// Black is a down candle (close lower than open) (-1)
/// </summary>
Black = -1
}
}
@@ -0,0 +1,110 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Collections.Generic;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Candle settings for all candlestick patterns
/// </summary>
public static class CandleSettings
{
/// <summary>
/// Default settings for all candle setting types
/// </summary>
private static readonly Dictionary<CandleSettingType, CandleSetting> DefaultSettings = new Dictionary<CandleSettingType, CandleSetting>
{
{ CandleSettingType.BodyLong, new CandleSetting(CandleRangeType.RealBody, 10, 1m) },
{ CandleSettingType.BodyVeryLong, new CandleSetting(CandleRangeType.RealBody, 10, 3m) },
{ CandleSettingType.BodyShort, new CandleSetting(CandleRangeType.RealBody, 10, 1m) },
{ CandleSettingType.BodyDoji, new CandleSetting(CandleRangeType.HighLow, 10, 0.1m) },
{ CandleSettingType.ShadowLong, new CandleSetting(CandleRangeType.RealBody, 0, 1m) },
{ CandleSettingType.ShadowVeryLong, new CandleSetting(CandleRangeType.RealBody, 0, 2m) },
{ CandleSettingType.ShadowShort, new CandleSetting(CandleRangeType.Shadows, 10, 1m) },
{ CandleSettingType.ShadowVeryShort, new CandleSetting(CandleRangeType.HighLow, 10, 0.1m) },
{ CandleSettingType.Near, new CandleSetting(CandleRangeType.HighLow, 5, 0.2m) },
{ CandleSettingType.Far, new CandleSetting(CandleRangeType.HighLow, 5, 0.6m) },
{ CandleSettingType.Equal, new CandleSetting(CandleRangeType.HighLow, 5, 0.05m) }
};
/// <summary>
/// Returns the candle setting for the requested type
/// </summary>
/// <param name="type">The candle setting type</param>
public static CandleSetting Get(CandleSettingType type)
{
CandleSetting setting;
DefaultSettings.TryGetValue(type, out setting);
return setting;
}
/// <summary>
/// Changes the default candle setting for the requested type
/// </summary>
/// <param name="type">The candle setting type</param>
/// <param name="setting">The candle setting</param>
public static void Set(CandleSettingType type, CandleSetting setting)
{
DefaultSettings[type] = setting;
}
}
/// <summary>
/// Represents a candle setting
/// </summary>
public class CandleSetting
{
/// <summary>
/// The candle range type
/// </summary>
public CandleRangeType RangeType
{
get;
private set;
}
/// <summary>
/// The number of previous candles to average
/// </summary>
public int AveragePeriod
{
get;
private set;
}
/// <summary>
/// A multiplier to calculate candle ranges
/// </summary>
public decimal Factor
{
get;
private set;
}
/// <summary>
/// Creates an instance of the <see cref="CandleSetting"/> class
/// </summary>
/// <param name="rangeType">The range type</param>
/// <param name="averagePeriod">The average period</param>
/// <param name="factor">The factor</param>
public CandleSetting(CandleRangeType rangeType, int averagePeriod, decimal factor)
{
RangeType = rangeType;
AveragePeriod = averagePeriod;
Factor = factor;
}
}
}
@@ -0,0 +1,151 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Abstract base class for a candlestick pattern indicator
/// </summary>
public abstract class CandlestickPattern : WindowIndicator<IBaseDataBar>
{
/// <summary>
/// Creates a new <see cref="CandlestickPattern"/> with the specified name
/// </summary>
/// <param name="name">The name of this indicator</param>
/// <param name="period">The number of data points to hold in the window</param>
protected CandlestickPattern(string name, int period)
: base(name, period)
{
}
/// <summary>
/// Returns the candle color of a candle
/// </summary>
/// <param name="tradeBar">The input candle</param>
protected static CandleColor GetCandleColor(IBaseDataBar tradeBar)
{
return tradeBar.Close >= tradeBar.Open ? CandleColor.White : CandleColor.Black;
}
/// <summary>
/// Returns the distance between the close and the open of a candle
/// </summary>
/// <param name="tradeBar">The input candle</param>
protected static decimal GetRealBody(IBaseDataBar tradeBar)
{
return Math.Abs(tradeBar.Close - tradeBar.Open);
}
/// <summary>
/// Returns the full range of the candle
/// </summary>
/// <param name="tradeBar">The input candle</param>
protected static decimal GetHighLowRange(IBaseDataBar tradeBar)
{
return tradeBar.High - tradeBar.Low;
}
/// <summary>
/// Returns the range of a candle
/// </summary>
/// <param name="type">The type of setting to use</param>
/// <param name="tradeBar">The input candle</param>
protected static decimal GetCandleRange(CandleSettingType type, IBaseDataBar tradeBar)
{
switch (CandleSettings.Get(type).RangeType)
{
case CandleRangeType.RealBody:
return GetRealBody(tradeBar);
case CandleRangeType.HighLow:
return GetHighLowRange(tradeBar);
case CandleRangeType.Shadows:
return GetUpperShadow(tradeBar) + GetLowerShadow(tradeBar);
default:
return 0m;
}
}
/// <summary>
/// Returns true if the candle is higher than the previous one
/// </summary>
protected static bool GetCandleGapUp(IBaseDataBar tradeBar, IBaseDataBar previousBar)
{
return tradeBar.Low > previousBar.High;
}
/// <summary>
/// Returns true if the candle is lower than the previous one
/// </summary>
protected static bool GetCandleGapDown(IBaseDataBar tradeBar, IBaseDataBar previousBar)
{
return tradeBar.High < previousBar.Low;
}
/// <summary>
/// Returns true if the candle is higher than the previous one (with no body overlap)
/// </summary>
protected static bool GetRealBodyGapUp(IBaseDataBar tradeBar, IBaseDataBar previousBar)
{
return Math.Min(tradeBar.Open, tradeBar.Close) > Math.Max(previousBar.Open, previousBar.Close);
}
/// <summary>
/// Returns true if the candle is lower than the previous one (with no body overlap)
/// </summary>
protected static bool GetRealBodyGapDown(IBaseDataBar tradeBar, IBaseDataBar previousBar)
{
return Math.Max(tradeBar.Open, tradeBar.Close) < Math.Min(previousBar.Open, previousBar.Close);
}
/// <summary>
/// Returns the range of the candle's lower shadow
/// </summary>
/// <param name="tradeBar">The input candle</param>
protected static decimal GetLowerShadow(IBaseDataBar tradeBar)
{
return (tradeBar.Close >= tradeBar.Open ? tradeBar.Open : tradeBar.Close) - tradeBar.Low;
}
/// <summary>
/// Returns the range of the candle's upper shadow
/// </summary>
/// <param name="tradeBar">The input candle</param>
protected static decimal GetUpperShadow(IBaseDataBar tradeBar)
{
return tradeBar.High - (tradeBar.Close >= tradeBar.Open ? tradeBar.Close : tradeBar.Open);
}
/// <summary>
/// Returns the average range of the previous candles
/// </summary>
/// <param name="type">The type of setting to use</param>
/// <param name="sum">The sum of the previous candles ranges</param>
/// <param name="tradeBar">The input candle</param>
protected static decimal GetCandleAverage(CandleSettingType type, decimal sum, IBaseDataBar tradeBar)
{
var defaultSetting = CandleSettings.Get(type);
return defaultSetting.Factor *
(defaultSetting.AveragePeriod != 0 ? sum / defaultSetting.AveragePeriod : GetCandleRange(type, tradeBar)) /
(defaultSetting.RangeType == CandleRangeType.Shadows ? 2.0m : 1.0m);
}
}
}
@@ -0,0 +1,131 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Closing Marubozu candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - long white(black) real body
/// - no or very short upper(lower) shadow
/// The meaning of "long" and "very short" is specified with SetCandleSettings
/// The returned value is positive(+1) when white(bullish), negative(-1) when black(bearish)
/// </remarks>
public class ClosingMarubozu : CandlestickPattern
{
private readonly int _bodyLongAveragePeriod;
private readonly int _shadowVeryShortAveragePeriod;
private decimal _bodyLongPeriodTotal;
private decimal _shadowVeryShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="ClosingMarubozu"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public ClosingMarubozu(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod) + 1)
{
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="ClosingMarubozu"/> class.
/// </summary>
public ClosingMarubozu()
: this("CLOSINGMARUBOZU")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
}
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
return 0m;
}
decimal value;
if (
// long body
GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, input) &&
(
(
// white body and very short upper shadow
GetCandleColor(input) == CandleColor.White &&
GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input)
) ||
(
// black body and very short lower shadow
GetCandleColor(input) == CandleColor.Black &&
GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input)
)
))
value = (int)GetCandleColor(input);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod]);
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[_shadowVeryShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0m;
_shadowVeryShortPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,137 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Concealed Baby Swallow candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: black marubozu (very short shadows)
/// - second candle: black marubozu(very short shadows)
/// - third candle: black candle that opens gapping down but has an upper shadow that extends into the prior body
/// - fourth candle: black candle that completely engulfs the third candle, including the shadows
/// The meanings of "very short shadow" are specified with SetCandleSettings;
/// The returned value is positive(+1): concealing baby swallow is always bullish;
/// The user should consider that concealing baby swallow is significant when it appears in downtrend, while
/// this function does not consider it
/// </remarks>
public class ConcealedBabySwallow : CandlestickPattern
{
private readonly int _shadowVeryShortAveragePeriod;
private decimal[] _shadowVeryShortPeriodTotal = new decimal[4];
/// <summary>
/// Initializes a new instance of the <see cref="ConcealedBabySwallow"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public ConcealedBabySwallow(string name)
: base(name, CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod + 3 + 1)
{
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="ConcealedBabySwallow"/> class.
/// </summary>
public ConcealedBabySwallow()
: this("CONCEALEDBABYSWALLOW")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal[3] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[3]);
_shadowVeryShortPeriodTotal[2] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[2]);
_shadowVeryShortPeriodTotal[1] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[1]);
}
return 0m;
}
decimal value;
if (
// 1st black
GetCandleColor(window[3]) == CandleColor.Black &&
// 2nd black
GetCandleColor(window[2]) == CandleColor.Black &&
// 3rd black
GetCandleColor(window[1]) == CandleColor.Black &&
// 4th black
GetCandleColor(input) == CandleColor.Black &&
// 1st: marubozu
GetLowerShadow(window[3]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[3], window[3]) &&
GetUpperShadow(window[3]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[3], window[3]) &&
// 2nd: marubozu
GetLowerShadow(window[2]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[2], window[2]) &&
GetUpperShadow(window[2]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[2], window[2]) &&
// 3rd: opens gapping down
GetRealBodyGapDown(window[1], window[2]) &&
// and has an upper shadow
GetUpperShadow(window[1]) > GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[1], window[1]) &&
// that extends into the prior body
window[1].High > window[2].Close &&
// 4th: engulfs the 3rd including the shadows
input.High > window[1].High && input.Low < window[1].Low
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
for (var i = 3; i >= 1; i--)
{
_shadowVeryShortPeriodTotal[i] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[i]) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[i + _shadowVeryShortAveragePeriod]);
}
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_shadowVeryShortPeriodTotal = new decimal[4];
base.Reset();
}
}
}
@@ -0,0 +1,133 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Counterattack candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long black (white)
/// - second candle: long white(black) with close equal to the prior close
/// The meaning of "equal" and "long" is specified with SetCandleSettings
/// The returned value is positive(+1) when bullish or negative(-1) when bearish;
/// The user should consider that counterattack is significant in a trend, while this function does not consider it
/// </remarks>
public class Counterattack : CandlestickPattern
{
private readonly int _equalAveragePeriod;
private readonly int _bodyLongAveragePeriod;
private decimal _equalPeriodTotal;
private decimal[] _bodyLongPeriodTotal = new decimal[2];
/// <summary>
/// Initializes a new instance of the <see cref="Counterattack"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public Counterattack(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.Equal).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod) + 1 + 1)
{
_equalAveragePeriod = CandleSettings.Get(CandleSettingType.Equal).AveragePeriod;
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="Counterattack"/> class.
/// </summary>
public Counterattack()
: this("COUNTERATTACK")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _equalAveragePeriod)
{
_equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]);
}
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal[1] += GetCandleRange(CandleSettingType.BodyLong, window[1]);
_bodyLongPeriodTotal[0] += GetCandleRange(CandleSettingType.BodyLong, input);
}
return 0m;
}
decimal value;
if (
// opposite candles
(int)GetCandleColor(window[1]) == -(int)GetCandleColor(input) &&
// 1st long
GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal[1], window[1]) &&
// 2nd long
GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal[0], input) &&
// equal closes
input.Close <= window[1].Close + GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1]) &&
input.Close >= window[1].Close - GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1])
)
value = (int)GetCandleColor(input);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, input) -
GetCandleRange(CandleSettingType.Equal, window[_equalAveragePeriod + 1]);
for (var i = 1; i >= 0; i--)
{
_bodyLongPeriodTotal[i] += GetCandleRange(CandleSettingType.BodyLong, window[i]) -
GetCandleRange(CandleSettingType.BodyLong, window[i + _bodyLongAveragePeriod]);
}
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_equalPeriodTotal = 0;
_bodyLongPeriodTotal = new decimal[2];
base.Reset();
}
}
}
@@ -0,0 +1,135 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Dark Cloud Cover candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long white candle
/// - second candle: black candle that opens above previous day high and closes within previous day real body;
/// Greg Morris wants the close to be below the midpoint of the previous real body
/// The meaning of "long" is specified with SetCandleSettings, the penetration of the first real body is specified
/// with optInPenetration
/// The returned value is negative(-1): dark cloud cover is always bearish
/// The user should consider that a dark cloud cover is significant when it appears in an uptrend, while
/// this function does not consider it
/// </remarks>
public class DarkCloudCover : CandlestickPattern
{
private readonly decimal _penetration;
private readonly int _bodyLongAveragePeriod;
private decimal _bodyLongPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="DarkCloudCover"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
/// <param name="penetration">Percentage of penetration of a candle within another candle</param>
public DarkCloudCover(string name, decimal penetration = 0.5m)
: base(name, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod + 1 + 1)
{
_penetration = penetration;
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="DarkCloudCover"/> class.
/// </summary>
/// <param name="penetration">Percentage of penetration of a candle within another candle</param>
public DarkCloudCover(decimal penetration)
: this("DARKCLOUDCOVER", penetration)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="DarkCloudCover"/> class.
/// </summary>
public DarkCloudCover()
: this("DARKCLOUDCOVER")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[1]);
}
return 0m;
}
decimal value;
if (
// 1st: white
GetCandleColor(window[1]) == CandleColor.White &&
// long
GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[1]) &&
// 2nd: black
GetCandleColor(input) == CandleColor.Black &&
// open above prior high
input.Open > window[1].High &&
// close within prior body
input.Close > window[1].Open &&
input.Close < window[1].Close - GetRealBody(window[1]) * _penetration
)
value = -1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[1]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 1]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0;
base.Reset();
}
}
}
+100
View File
@@ -0,0 +1,100 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Doji candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - open quite equal to close
/// How much can be the maximum distance between open and close is specified with SetCandleSettings
/// The returned value is always positive(+1) but this does not mean it is bullish: doji shows uncertainty and it is
/// neither bullish nor bearish when considered alone
/// </remarks>
public class Doji : CandlestickPattern
{
private readonly int _bodyDojiAveragePeriod;
private decimal _bodyDojiPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="Doji"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public Doji(string name)
: base(name, CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod + 1)
{
_bodyDojiAveragePeriod = CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="Doji"/> class.
/// </summary>
public Doji()
: this("DOJI")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyDojiAveragePeriod)
{
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input);
}
return 0m;
}
var value = GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, input) ? 1m : 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input) -
GetCandleRange(CandleSettingType.BodyDoji, window[_bodyDojiAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyDojiPeriodTotal = 0m;
base.Reset();
}
}
}
+131
View File
@@ -0,0 +1,131 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Doji Star candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long real body
/// - second candle: star(open gapping up in an uptrend or down in a downtrend) with a doji
/// The meaning of "doji" and "long" is specified with SetCandleSettings
/// The returned value is positive(+1) when bullish or negative(-1) when bearish;
/// it's defined bullish when the long candle is white and the star gaps up, bearish when the long candle
/// is black and the star gaps down; the user should consider that a doji star is bullish when it appears
/// in an uptrend and it's bearish when it appears in a downtrend, so to determine the bullishness or
/// bearishness of the pattern the trend must be analyzed
/// </remarks>
public class DojiStar : CandlestickPattern
{
private readonly int _bodyLongAveragePeriod;
private readonly int _bodyDojiAveragePeriod;
private decimal _bodyLongPeriodTotal;
private decimal _bodyDojiPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="DojiStar"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public DojiStar(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod) + 1 + 1)
{
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_bodyDojiAveragePeriod = CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="DojiStar"/> class.
/// </summary>
public DojiStar()
: this("DOJISTAR")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod - 1 && Samples < Period - 1)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
}
if (Samples >= Period - _bodyDojiAveragePeriod)
{
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input);
}
return 0m;
}
decimal value;
if (
// 1st: long real body
GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[1]) &&
// 2nd: doji
GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, input) &&
// that gaps up if 1st is white
((GetCandleColor(window[1]) == CandleColor.White && GetRealBodyGapUp(input, window[1]))
||
// or down if 1st is black
(GetCandleColor(window[1]) == CandleColor.Black && GetRealBodyGapDown(input, window[1]))
))
value = -(int)GetCandleColor(window[1]);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[1]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 1]);
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input) -
GetCandleRange(CandleSettingType.BodyDoji, window[_bodyDojiAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0m;
_bodyDojiPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,122 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Dragonfly Doji candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - doji body
/// - open and close at the high of the day = no or very short upper shadow
/// - lower shadow(to distinguish from other dojis, here lower shadow should not be very short)
/// The meaning of "doji" and "very short" is specified with SetCandleSettings
/// The returned value is always positive(+1) but this does not mean it is bullish: dragonfly doji must be considered
/// relatively to the trend
/// </remarks>
public class DragonflyDoji : CandlestickPattern
{
private readonly int _bodyDojiAveragePeriod;
private readonly int _shadowVeryShortAveragePeriod;
private decimal _bodyDojiPeriodTotal;
private decimal _shadowVeryShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="DragonflyDoji"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public DragonflyDoji(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod) + 1)
{
_bodyDojiAveragePeriod = CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod;
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="DragonflyDoji"/> class.
/// </summary>
public DragonflyDoji()
: this("DRAGONFLYDOJI")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyDojiAveragePeriod)
{
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input);
}
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
return 0m;
}
decimal value;
if (GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, input) &&
GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input) &&
GetLowerShadow(input) > GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input)
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input) -
GetCandleRange(CandleSettingType.BodyDoji, window[_bodyDojiAveragePeriod]);
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[_shadowVeryShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyDojiPeriodTotal = 0m;
_shadowVeryShortPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,91 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Engulfing candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first: black (white) real body
/// - second: white(black) real body that engulfs the prior real body
/// The returned value is positive(+1) when bullish or negative(-1) when bearish;
/// The user should consider that an engulfing must appear in a downtrend if bullish or in an uptrend if bearish,
/// while this function does not consider it
/// </remarks>
public class Engulfing : CandlestickPattern
{
/// <summary>
/// Initializes a new instance of the <see cref="Engulfing"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public Engulfing(string name)
: base(name, 3)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Engulfing"/> class.
/// </summary>
public Engulfing()
: this("ENGULFING")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
return 0m;
}
decimal value;
if (
// white engulfs black
(GetCandleColor(input) == CandleColor.White && GetCandleColor(window[1]) == CandleColor.Black &&
input.Close > window[1].Open && input.Open < window[1].Close
)
||
// black engulfs white
(GetCandleColor(input) == CandleColor.Black && GetCandleColor(window[1]) == CandleColor.White &&
input.Open > window[1].Close && input.Close < window[1].Open
)
)
value = (int)GetCandleColor(input);
else
value = 0;
return value;
}
}
}
@@ -0,0 +1,166 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Evening Doji Star candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long white real body
/// - second candle: doji gapping up
/// - third candle: black real body that moves well within the first candle's real body
/// The meaning of "doji" and "long" is specified with SetCandleSettings
/// The meaning of "moves well within" is specified with penetration and "moves" should mean the real body should
/// not be short ("short" is specified with SetCandleSettings) - Greg Morris wants it to be long, someone else want
/// it to be relatively long
/// The returned value is negative(-1): evening star is always bearish;
/// The user should consider that an evening star is significant when it appears in an uptrend,
/// while this function does not consider the trend
/// </remarks>
public class EveningDojiStar : CandlestickPattern
{
private readonly decimal _penetration;
private readonly int _bodyDojiAveragePeriod;
private readonly int _bodyLongAveragePeriod;
private readonly int _bodyShortAveragePeriod;
private decimal _bodyDojiPeriodTotal;
private decimal _bodyLongPeriodTotal;
private decimal _bodyShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="EveningDojiStar"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
/// <param name="penetration">Percentage of penetration of a candle within another candle</param>
public EveningDojiStar(string name, decimal penetration = 0.3m)
: base(name, Math.Max(Math.Max(CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod),
CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod) + 2 + 1)
{
_penetration = penetration;
_bodyDojiAveragePeriod = CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod;
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="EveningDojiStar"/> class.
/// </summary>
/// <param name="penetration">Percentage of penetration of a candle within another candle</param>
public EveningDojiStar(decimal penetration)
: this("EVENINGDOJISTAR", penetration)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="EveningDojiStar"/> class.
/// </summary>
public EveningDojiStar()
: this("EVENINGDOJISTAR")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod - 2 && Samples < Period - 2)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
}
if (Samples >= Period - _bodyDojiAveragePeriod - 1 && Samples < Period - 1)
{
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input);
}
if (Samples >= Period - _bodyShortAveragePeriod)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
return 0m;
}
decimal value;
if (
// 1st: long
GetRealBody(window[2]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[2]) &&
// white
GetCandleColor(window[2]) == CandleColor.White &&
// 2nd: doji
GetRealBody(window[1]) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, window[1]) &&
// gapping up
GetRealBodyGapUp(window[1], window[2]) &&
// 3rd: longer than short
GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
// black real body
GetCandleColor(input) == CandleColor.Black &&
// closing well within 1st rb
input.Close < window[2].Close - GetRealBody(window[2]) * _penetration
)
value = -1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[2]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 2]);
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, window[1]) -
GetCandleRange(CandleSettingType.BodyDoji, window[_bodyDojiAveragePeriod + 1]);
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0;
_bodyDojiPeriodTotal = 0;
_bodyShortPeriodTotal = 0;
base.Reset();
}
}
}
@@ -0,0 +1,159 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Evening Star candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long white real body
/// - second candle: star(short real body gapping up)
/// - third candle: black real body that moves well within the first candle's real body
/// The meaning of "short" and "long" is specified with SetCandleSettings
/// The meaning of "moves well within" is specified with penetration and "moves" should mean the real body should
/// not be short ("short" is specified with SetCandleSettings) - Greg Morris wants it to be long, someone else want
/// it to be relatively long
/// The returned value is negative(-1): evening star is always bearish;
/// The user should consider that an evening star is significant when it appears in an uptrend,
/// while this function does not consider the trend
/// </remarks>
public class EveningStar : CandlestickPattern
{
private readonly decimal _penetration;
private readonly int _bodyLongAveragePeriod;
private readonly int _bodyShortAveragePeriod;
private decimal _bodyLongPeriodTotal;
private decimal _bodyShortPeriodTotal;
private decimal _bodyShortPeriodTotal2;
/// <summary>
/// Initializes a new instance of the <see cref="EveningStar"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
/// <param name="penetration">Percentage of penetration of a candle within another candle</param>
public EveningStar(string name, decimal penetration = 0.3m)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod) + 2 + 1)
{
_penetration = penetration;
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="EveningStar"/> class.
/// </summary>
/// <param name="penetration">Percentage of penetration of a candle within another candle</param>
public EveningStar(decimal penetration)
: this("EVENINGSTAR", penetration)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="EveningStar"/> class.
/// </summary>
public EveningStar()
: this("EVENINGSTAR")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod - 2 && Samples < Period - 2)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
}
if (Samples >= Period - _bodyShortAveragePeriod && Samples < Period)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, window[1]);
_bodyShortPeriodTotal2 += GetCandleRange(CandleSettingType.BodyShort, input);
}
return 0m;
}
decimal value;
if (
// 1st: long
GetRealBody(window[2]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[2]) &&
// white
GetCandleColor(window[2]) == CandleColor.White &&
// 2nd: short
GetRealBody(window[1]) <= GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, window[1]) &&
// gapping up
GetRealBodyGapUp(window[1], window[2]) &&
// 3rd: longer than short
GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal2, input) &&
// black real body
GetCandleColor(input) == CandleColor.Black &&
// closing well within 1st rb
input.Close < window[2].Close - GetRealBody(window[2]) * _penetration
)
value = -1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[2]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 2]);
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, window[1]) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod + 1]);
_bodyShortPeriodTotal2 += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0;
_bodyShortPeriodTotal = 0;
_bodyShortPeriodTotal2 = 0;
base.Reset();
}
}
}
@@ -0,0 +1,138 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Up/Down-gap side-by-side white lines candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - upside or downside gap (between the bodies)
/// - first candle after the window: white candlestick
/// - second candle after the window: white candlestick with similar size(near the same) and about the same
/// open(equal) of the previous candle
/// - the second candle does not close the window
/// The meaning of "near" and "equal" is specified with SetCandleSettings
/// The returned value is positive(+1) or negative(-1): the user should consider that upside
/// or downside gap side-by-side white lines is significant when it appears in a trend, while this function
/// does not consider the trend
/// </remarks>
public class GapSideBySideWhite : CandlestickPattern
{
private readonly int _nearAveragePeriod;
private readonly int _equalAveragePeriod;
private decimal _nearPeriodTotal;
private decimal _equalPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="GapSideBySideWhite"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public GapSideBySideWhite(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.Near).AveragePeriod, CandleSettings.Get(CandleSettingType.Equal).AveragePeriod) + 2 + 1)
{
_nearAveragePeriod = CandleSettings.Get(CandleSettingType.Near).AveragePeriod;
_equalAveragePeriod = CandleSettings.Get(CandleSettingType.Equal).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="GapSideBySideWhite"/> class.
/// </summary>
public GapSideBySideWhite()
: this("GAPSIDEBYSIDEWHITE")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _nearAveragePeriod)
{
_nearPeriodTotal += GetCandleRange(CandleSettingType.Near, window[1]);
}
if (Samples >= Period - _equalAveragePeriod)
{
_equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]);
}
return 0m;
}
decimal value;
if (
( // upside or downside gap between the 1st candle and both the next 2 candles
(GetRealBodyGapUp(window[1], window[2]) && GetRealBodyGapUp(input, window[2]))
||
(GetRealBodyGapDown(window[1], window[2]) && GetRealBodyGapDown(input, window[2]))
) &&
// 2nd: white
GetCandleColor(window[1]) == CandleColor.White &&
// 3rd: white
GetCandleColor(input) == CandleColor.White &&
// same size 2 and 3
GetRealBody(input) >= GetRealBody(window[1]) - GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, window[1]) &&
GetRealBody(input) <= GetRealBody(window[1]) + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, window[1]) &&
// same open 2 and 3
input.Open >= window[1].Open - GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1]) &&
input.Open <= window[1].Open + GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1])
)
value = GetRealBodyGapUp(window[1], window[2]) ? 1m : -1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_nearPeriodTotal += GetCandleRange(CandleSettingType.Near, window[1]) -
GetCandleRange(CandleSettingType.Near, window[1 + _nearAveragePeriod]);
_equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]) -
GetCandleRange(CandleSettingType.Equal, window[1 + _equalAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_nearPeriodTotal = 0;
_equalPeriodTotal = 0;
base.Reset();
}
}
}
@@ -0,0 +1,122 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Gravestone Doji candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - doji body
/// - open and close at the low of the day = no or very short lower shadow
/// - upper shadow(to distinguish from other dojis, here upper shadow should not be very short)
/// The meaning of "doji" and "very short" is specified with SetCandleSettings
/// The returned value is always positive(+1) but this does not mean it is bullish: gravestone doji must be considered
/// relatively to the trend
/// </remarks>
public class GravestoneDoji : CandlestickPattern
{
private readonly int _bodyDojiAveragePeriod;
private readonly int _shadowVeryShortAveragePeriod;
private decimal _bodyDojiPeriodTotal;
private decimal _shadowVeryShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="GravestoneDoji"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public GravestoneDoji(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod) + 1)
{
_bodyDojiAveragePeriod = CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod;
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="GravestoneDoji"/> class.
/// </summary>
public GravestoneDoji()
: this("GRAVESTONEDOJI")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyDojiAveragePeriod)
{
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input);
}
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
return 0m;
}
decimal value;
if (GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, input) &&
GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input) &&
GetUpperShadow(input) > GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input)
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input) -
GetCandleRange(CandleSettingType.BodyDoji, window[_bodyDojiAveragePeriod]);
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[_shadowVeryShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyDojiPeriodTotal = 0m;
_shadowVeryShortPeriodTotal = 0m;
base.Reset();
}
}
}
+154
View File
@@ -0,0 +1,154 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Hammer candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - small real body
/// - long lower shadow
/// - no, or very short, upper shadow
/// - body below or near the lows of the previous candle
/// The meaning of "short", "long" and "near the lows" is specified with SetCandleSettings;
/// The returned value is positive(+1): hammer is always bullish;
/// The user should consider that a hammer must appear in a downtrend, while this function does not consider it
/// </remarks>
public class Hammer : CandlestickPattern
{
private readonly int _bodyShortAveragePeriod;
private readonly int _shadowLongAveragePeriod;
private readonly int _shadowVeryShortAveragePeriod;
private readonly int _nearAveragePeriod;
private decimal _bodyShortPeriodTotal;
private decimal _shadowLongPeriodTotal;
private decimal _shadowVeryShortPeriodTotal;
private decimal _nearPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="Hammer"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public Hammer(string name)
: base(name, Math.Max(Math.Max(Math.Max(CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod),
CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod), CandleSettings.Get(CandleSettingType.Near).AveragePeriod) + 1 + 1)
{
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_shadowLongAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod;
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
_nearAveragePeriod = CandleSettings.Get(CandleSettingType.Near).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="Hammer"/> class.
/// </summary>
public Hammer()
: this("HAMMER")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyShortAveragePeriod)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
if (Samples >= Period - _shadowLongAveragePeriod)
{
_shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, input);
}
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
if (Samples >= Period - _nearAveragePeriod - 1 && Samples < Period - 1)
{
_nearPeriodTotal += GetCandleRange(CandleSettingType.Near, input);
}
return 0m;
}
decimal value;
if (
// small rb
GetRealBody(input) < GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
// long lower shadow
GetLowerShadow(input) > GetCandleAverage(CandleSettingType.ShadowLong, _shadowLongPeriodTotal, input) &&
// very short upper shadow
GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input) &&
// rb near the prior candle's lows
Math.Min(input.Close, input.Open) <= window[1].Low + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, window[1])
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
_shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, input) -
GetCandleRange(CandleSettingType.ShadowLong, window[_shadowLongAveragePeriod]);
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[_shadowVeryShortAveragePeriod]);
_nearPeriodTotal += GetCandleRange(CandleSettingType.Near, window[1]) -
GetCandleRange(CandleSettingType.Near, window[_nearAveragePeriod + 1]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyShortPeriodTotal = 0m;
_shadowLongPeriodTotal = 0m;
_shadowVeryShortPeriodTotal = 0m;
_nearPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,154 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Hanging Man candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - small real body
/// - long lower shadow
/// - no, or very short, upper shadow
/// - body above or near the highs of the previous candle
/// The meaning of "short", "long" and "near the highs" is specified with SetCandleSettings;
/// The returned value is negative (-1): hanging man is always bearish;
/// The user should consider that a hanging man must appear in an uptrend, while this function does not consider it
/// </remarks>
public class HangingMan : CandlestickPattern
{
private readonly int _bodyShortAveragePeriod;
private readonly int _shadowLongAveragePeriod;
private readonly int _shadowVeryShortAveragePeriod;
private readonly int _nearAveragePeriod;
private decimal _bodyShortPeriodTotal;
private decimal _shadowLongPeriodTotal;
private decimal _shadowVeryShortPeriodTotal;
private decimal _nearPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="HangingMan"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public HangingMan(string name)
: base(name, Math.Max(Math.Max(Math.Max(CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod),
CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod), CandleSettings.Get(CandleSettingType.Near).AveragePeriod) + 1 + 1)
{
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_shadowLongAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod;
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
_nearAveragePeriod = CandleSettings.Get(CandleSettingType.Near).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="HangingMan"/> class.
/// </summary>
public HangingMan()
: this("HANGINGMAN")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyShortAveragePeriod)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
if (Samples >= Period - _shadowLongAveragePeriod)
{
_shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, input);
}
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
if (Samples >= Period - _nearAveragePeriod - 1 && Samples < Period - 1)
{
_nearPeriodTotal += GetCandleRange(CandleSettingType.Near, input);
}
return 0m;
}
decimal value;
if (
// small rb
GetRealBody(input) < GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
// long lower shadow
GetLowerShadow(input) > GetCandleAverage(CandleSettingType.ShadowLong, _shadowLongPeriodTotal, input) &&
// very short upper shadow
GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input) &&
// rb near the prior candle's highs
Math.Min(input.Close, input.Open) >= window[1].High - GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, window[1])
)
value = -1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
_shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, input) -
GetCandleRange(CandleSettingType.ShadowLong, window[_shadowLongAveragePeriod]);
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[_shadowVeryShortAveragePeriod]);
_nearPeriodTotal += GetCandleRange(CandleSettingType.Near, window[1]) -
GetCandleRange(CandleSettingType.Near, window[_nearAveragePeriod + 1]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyShortPeriodTotal = 0m;
_shadowLongPeriodTotal = 0m;
_shadowVeryShortPeriodTotal = 0m;
_nearPeriodTotal = 0m;
base.Reset();
}
}
}
+127
View File
@@ -0,0 +1,127 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Harami candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long white (black) real body
/// - second candle: short real body totally engulfed by the first
/// The meaning of "short" and "long" is specified with SetCandleSettings
/// The returned value is positive(+1) when bullish or negative(-1) when bearish;
/// The user should consider that a harami is significant when it appears in a downtrend if bullish or
/// in an uptrend when bearish, while this function does not consider the trend
/// </remarks>
public class Harami : CandlestickPattern
{
private readonly int _bodyLongAveragePeriod;
private readonly int _bodyShortAveragePeriod;
private decimal _bodyLongPeriodTotal;
private decimal _bodyShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="Harami"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public Harami(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod) + 1 + 1)
{
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="Harami"/> class.
/// </summary>
public Harami()
: this("HARAMI")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod - 1 && Samples < Period - 1)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
}
if (Samples >= Period - _bodyShortAveragePeriod)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
return 0m;
}
decimal value;
if (
// 1st: long
GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[1]) &&
// 2nd: short
GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
// engulfed by 1st
Math.Max(input.Close, input.Open) < Math.Max(window[1].Close, window[1].Open) &&
Math.Min(input.Close, input.Open) > Math.Min(window[1].Close, window[1].Open)
)
value = -(int)GetCandleColor(window[1]);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[1]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 1]);
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0m;
_bodyShortPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,127 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Harami Cross candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long white (black) real body
/// - second candle: doji totally engulfed by the first
/// The meaning of "doji" and "long" is specified with SetCandleSettings
/// The returned value is positive(+1) when bullish or negative(-1) when bearish;
/// The user should consider that a harami cross is significant when it appears in a downtrend if bullish or
/// in an uptrend when bearish, while this function does not consider the trend
/// </remarks>
public class HaramiCross : CandlestickPattern
{
private readonly int _bodyLongAveragePeriod;
private readonly int _bodyDojiAveragePeriod;
private decimal _bodyLongPeriodTotal;
private decimal _bodyDojiPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="HaramiCross"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public HaramiCross(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod) + 1 + 1)
{
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_bodyDojiAveragePeriod = CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="HaramiCross"/> class.
/// </summary>
public HaramiCross()
: this("HARAMICROSS")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod - 1 && Samples < Period - 1)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
}
if (Samples >= Period - _bodyDojiAveragePeriod)
{
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input);
}
return 0m;
}
decimal value;
if (
// 1st: long
GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[1]) &&
// 2nd: doji
GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, input) &&
// engulfed by 1st
Math.Max(input.Close, input.Open) < Math.Max(window[1].Close, window[1].Open) &&
Math.Min(input.Close, input.Open) > Math.Min(window[1].Close, window[1].Open)
)
value = -(int)GetCandleColor(window[1]);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[1]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 1]);
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input) -
GetCandleRange(CandleSettingType.BodyDoji, window[_bodyDojiAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0m;
_bodyDojiPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,121 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// High-Wave Candle candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - short real body
/// - very long upper and lower shadow
/// The meaning of "short" and "very long" is specified with SetCandleSettings
/// The returned value is positive(+1) when white or negative(-1) when black;
/// it does not mean bullish or bearish
/// </remarks>
public class HighWaveCandle : CandlestickPattern
{
private readonly int _bodyShortAveragePeriod;
private readonly int _shadowVeryLongAveragePeriod;
private decimal _bodyShortPeriodTotal;
private decimal _shadowVeryLongPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="HighWaveCandle"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public HighWaveCandle(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowVeryLong).AveragePeriod) + 1)
{
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
_shadowVeryLongAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryLong).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="HighWaveCandle"/> class.
/// </summary>
public HighWaveCandle()
: this("HIGHWAVECANDLE")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyShortAveragePeriod)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
if (Samples >= Period - _shadowVeryLongAveragePeriod)
{
_shadowVeryLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryLong, input);
}
return 0m;
}
decimal value;
if (GetRealBody(input) < GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
GetUpperShadow(input) > GetCandleAverage(CandleSettingType.ShadowVeryLong, _shadowVeryLongPeriodTotal, input) &&
GetLowerShadow(input) > GetCandleAverage(CandleSettingType.ShadowVeryLong, _shadowVeryLongPeriodTotal, input)
)
value = (int)GetCandleColor(input);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
_shadowVeryLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryLong, input) -
GetCandleRange(CandleSettingType.ShadowVeryLong, window[_shadowVeryLongAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyShortPeriodTotal = 0m;
_shadowVeryLongPeriodTotal = 0m;
base.Reset();
}
}
}
+154
View File
@@ -0,0 +1,154 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Hikkake candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first and second candle: inside bar (2nd has lower high and higher low than 1st)
/// - third candle: lower high and lower low than 2nd(higher high and higher low than 2nd)
/// The returned value for the hikkake bar is positive(+1) or negative(-1) meaning bullish or bearish hikkake
/// Confirmation could come in the next 3 days with:
/// - a day that closes higher than the high(lower than the low) of the 2nd candle
/// The returned value for the confirmation bar is equal to 1 + the bullish hikkake result or -1 - the bearish hikkake result
/// Note: if confirmation and a new hikkake come at the same bar, only the new hikkake is reported(the new hikkake
/// overwrites the confirmation of the old hikkake)
/// </remarks>
public class Hikkake : CandlestickPattern
{
private int _patternIndex;
private int _patternResult;
/// <summary>
/// Initializes a new instance of the <see cref="Hikkake"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public Hikkake(string name)
: base(name, 5 + 1)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Hikkake"/> class.
/// </summary>
public Hikkake()
: this("HIKKAKE")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= 3)
{
// copy here the pattern recognition code below
// 1st + 2nd: lower high and higher low
if (window[1].High < window[2].High && window[1].Low > window[2].Low &&
// (bull) 3rd: lower high and lower low
((input.High < window[1].High && input.Low < window[1].Low)
||
// (bear) 3rd: higher high and higher low
(input.High > window[1].High && input.Low > window[1].Low)
)
)
{
_patternResult = (input.High < window[1].High ? 1 : -1);
_patternIndex = (int)Samples - 1;
}
else
// search for confirmation if hikkake was no more than 3 bars ago
if (Samples <= _patternIndex + 4 &&
// close higher than the high of 2nd
((_patternResult > 0 && input.Close > window[(int)Samples - _patternIndex].High)
||
// close lower than the low of 2nd
(_patternResult < 0 && input.Close < window[(int)Samples - _patternIndex].Low)
)
)
_patternIndex = 0;
}
return 0m;
}
decimal value;
// 1st + 2nd: lower high and higher low
if (window[1].High < window[2].High && window[1].Low > window[2].Low &&
// (bull) 3rd: lower high and lower low
((input.High < window[1].High && input.Low < window[1].Low)
||
// (bear) 3rd: higher high and higher low
(input.High > window[1].High && input.Low > window[1].Low)
)
)
{
_patternResult = (input.High < window[1].High ? 1 : -1);
_patternIndex = (int) Samples - 1;
value = _patternResult;
}
else
{
// search for confirmation if hikkake was no more than 3 bars ago
if (Samples <= _patternIndex + 4 &&
// close higher than the high of 2nd
((_patternResult > 0 && input.Close > window[(int) Samples - _patternIndex].High)
||
// close lower than the low of 2nd
(_patternResult < 0 && input.Close < window[(int) Samples - _patternIndex].Low)
)
)
{
value = _patternResult + (_patternResult > 0 ? 1 : -1);
_patternIndex = 0;
}
else
value = 0;
}
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_patternIndex = 0;
_patternResult = 0;
base.Reset();
}
}
}
@@ -0,0 +1,198 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Hikkake Modified candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle
/// - second candle: candle with range less than first candle and close near the bottom(near the top)
/// - third candle: lower high and higher low than 2nd
/// - fourth candle: lower high and lower low(higher high and higher low) than 3rd
/// The returned value for the hikkake bar is positive(+1) or negative(-1) meaning bullish or bearish hikkake
/// Confirmation could come in the next 3 days with:
/// - a day that closes higher than the high(lower than the low) of the 3rd candle
/// The returned value for the confirmation bar is equal to 1 + the bullish hikkake result or -1 - the bearish hikkake result
/// Note: if confirmation and a new hikkake come at the same bar, only the new hikkake is reported(the new hikkake
/// overwrites the confirmation of the old hikkake);
/// The user should consider that modified hikkake is a reversal pattern, while hikkake could be both a reversal
/// or a continuation pattern, so bullish(bearish) modified hikkake is significant when appearing in a downtrend(uptrend)
/// </remarks>
public class HikkakeModified : CandlestickPattern
{
private readonly int _nearAveragePeriod;
private decimal _nearPeriodTotal;
private int _patternIndex;
private int _patternResult;
/// <summary>
/// Initializes a new instance of the <see cref="HikkakeModified"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public HikkakeModified(string name)
: base(name, Math.Max(1, CandleSettings.Get(CandleSettingType.Near).AveragePeriod) + 5 + 1)
{
_nearAveragePeriod = CandleSettings.Get(CandleSettingType.Near).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="HikkakeModified"/> class.
/// </summary>
public HikkakeModified()
: this("HIKKAKEMODIFIED")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _nearAveragePeriod - 3 && Samples < Period - 3)
{
_nearPeriodTotal += GetCandleRange(CandleSettingType.Near, window[2]);
}
else if (Samples >= Period - 3)
{
// copy here the pattern recognition code below
// 2nd: lower high and higher low than 1st
if (window[2].High < window[3].High && window[2].Low > window[3].Low &&
// 3rd: lower high and higher low than 2nd
window[1].High < window[2].High && window[1].Low > window[2].Low &&
// (bull) 4th: lower high and lower low
((input.High < window[1].High && input.Low < window[1].Low &&
// (bull) 2nd: close near the low
window[2].Close <= window[2].Low + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, window[2])
)
||
// (bear) 4th: higher high and higher low
(input.High > window[1].High && input.Low > window[1].Low &&
// (bull) 2nd: close near the top
window[2].Close >= window[2].High - GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, window[2])
)
)
)
{
_patternResult = (input.High < window[1].High ? 1 : -1);
_patternIndex = (int) Samples - 1;
}
else
{
// search for confirmation if modified hikkake was no more than 3 bars ago
if (Samples <= _patternIndex + 4 &&
// close higher than the high of 3rd
((_patternResult > 0 && input.Close > window[(int) Samples - _patternIndex].High)
||
// close lower than the low of 3rd
(_patternResult < 0 && input.Close < window[(int) Samples - _patternIndex].Low))
)
_patternIndex = 0;
}
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_nearPeriodTotal += GetCandleRange(CandleSettingType.Near, window[2]) -
GetCandleRange(CandleSettingType.Near, window[(int)Samples - 1]);
}
return 0m;
}
decimal value;
// 2nd: lower high and higher low than 1st
if (window[2].High < window[3].High && window[2].Low > window[3].Low &&
// 3rd: lower high and higher low than 2nd
window[1].High < window[2].High && window[1].Low > window[2].Low &&
// (bull) 4th: lower high and lower low
((input.High < window[1].High && input.Low < window[1].Low &&
// (bull) 2nd: close near the low
window[2].Close <= window[2].Low + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, window[2])
)
||
// (bear) 4th: higher high and higher low
(input.High > window[1].High && input.Low > window[1].Low &&
// (bull) 2nd: close near the top
window[2].Close >= window[2].High - GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, window[2])
)
)
)
{
_patternResult = (input.High < window[1].High ? 1 : -1);
_patternIndex = (int) Samples - 1;
value = _patternResult;
}
else
{
// search for confirmation if modified hikkake was no more than 3 bars ago
if (Samples <= _patternIndex + 4 &&
// close higher than the high of 3rd
((_patternResult > 0 && input.Close > window[(int)Samples - _patternIndex].High)
||
// close lower than the low of 3rd
(_patternResult < 0 && input.Close < window[(int)Samples - _patternIndex].Low))
)
{
value = _patternResult + (_patternResult > 0 ? 1 : -1);
_patternIndex = 0;
}
else
value = 0;
}
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_nearPeriodTotal += GetCandleRange(CandleSettingType.Near, window[2]) -
GetCandleRange(CandleSettingType.Near, window[_nearAveragePeriod + 5]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_nearPeriodTotal = 0;
_patternIndex = 0;
_patternResult = 0;
base.Reset();
}
}
}
@@ -0,0 +1,131 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Homing Pigeon candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long black candle
/// - second candle: short black real body completely inside the previous day's body
/// The meaning of "short" and "long" is specified with SetCandleSettings
/// The returned value is positive(+1): homing pigeon is always bullish;
/// The user should consider that homing pigeon is significant when it appears in a downtrend,
/// while this function does not consider the trend
/// </remarks>
public class HomingPigeon : CandlestickPattern
{
private readonly int _bodyLongAveragePeriod;
private readonly int _bodyShortAveragePeriod;
private decimal _bodyLongPeriodTotal;
private decimal _bodyShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="HomingPigeon"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public HomingPigeon(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod) + 1 + 1)
{
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="HomingPigeon"/> class.
/// </summary>
public HomingPigeon()
: this("HOMINGPIGEON")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[1]);
}
if (Samples >= Period - _bodyShortAveragePeriod)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
return 0m;
}
decimal value;
if (
// 1st black
GetCandleColor(window[1]) == CandleColor.Black &&
// 2nd black
GetCandleColor(input) == CandleColor.Black &&
// 1st long
GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[1]) &&
// 2nd short
GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
// 2nd engulfed by 1st
input.Open < window[1].Open &&
input.Close > window[1].Close
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[1]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 1]);
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0m;
_bodyShortPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,153 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Identical Three Crows candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - three consecutive and declining black candlesticks
/// - each candle must have no or very short lower shadow
/// - each candle after the first must open at or very close to the prior candle's close
/// The meaning of "very short" is specified with SetCandleSettings;
/// the meaning of "very close" is specified with SetCandleSettings(Equal);
/// The returned value is negative(-1): identical three crows is always bearish;
/// The user should consider that identical 3 crows is significant when it appears after a mature advance or at high levels,
/// while this function does not consider it
/// </remarks>
public class IdenticalThreeCrows : CandlestickPattern
{
private readonly int _shadowVeryShortAveragePeriod;
private readonly int _equalAveragePeriod;
private decimal[] _shadowVeryShortPeriodTotal = new decimal[3];
private decimal[] _equalPeriodTotal = new decimal[3];
/// <summary>
/// Initializes a new instance of the <see cref="IdenticalThreeCrows"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public IdenticalThreeCrows(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod, CandleSettings.Get(CandleSettingType.Equal).AveragePeriod) + 2 + 1)
{
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
_equalAveragePeriod = CandleSettings.Get(CandleSettingType.Equal).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="IdenticalThreeCrows"/> class.
/// </summary>
public IdenticalThreeCrows()
: this("IDENTICALTHREECROWS")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal[2] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[2]);
_shadowVeryShortPeriodTotal[1] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[1]);
_shadowVeryShortPeriodTotal[0] += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
if (Samples >= Period - _equalAveragePeriod)
{
_equalPeriodTotal[2] += GetCandleRange(CandleSettingType.Near, window[2]);
_equalPeriodTotal[1] += GetCandleRange(CandleSettingType.Near, window[1]);
}
return 0m;
}
decimal value;
if (
// 1st black
GetCandleColor(window[2]) == CandleColor.Black &&
// very short lower shadow
GetLowerShadow(window[2]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[2], window[2]) &&
// 2nd black
GetCandleColor(window[1]) == CandleColor.Black &&
// very short lower shadow
GetLowerShadow(window[1]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[1], window[1]) &&
// 3rd black
GetCandleColor(input) == CandleColor.Black &&
// very short lower shadow
GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[0], input) &&
// three declining
window[2].Close > window[1].Close &&
window[1].Close > input.Close &&
// 2nd black opens very close to 1st close
window[1].Open <= window[2].Close + GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal[2], window[2]) &&
window[1].Open >= window[2].Close - GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal[2], window[2]) &&
// 3rd black opens very close to 2nd close
input.Open <= window[1].Close + GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal[1], window[1]) &&
input.Open >= window[1].Close - GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal[1], window[1])
)
value = -1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
for (var i = 2; i >= 0; i--)
{
_shadowVeryShortPeriodTotal[i] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[i]) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[i + _shadowVeryShortAveragePeriod]);
}
for (var i = 2; i >= 1; i--)
{
_equalPeriodTotal[i] += GetCandleRange(CandleSettingType.Equal, window[i]) -
GetCandleRange(CandleSettingType.Equal, window[i + _equalAveragePeriod]);
}
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_shadowVeryShortPeriodTotal = new decimal[3];
_equalPeriodTotal = new decimal[3];
base.Reset();
}
}
}
+131
View File
@@ -0,0 +1,131 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// In-Neck candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long black candle
/// - second candle: white candle with open below previous day low and close slightly into previous day body
/// The meaning of "equal" is specified with SetCandleSettings
/// The returned value is negative(-1): in-neck is always bearish
/// The user should consider that in-neck is significant when it appears in a downtrend, while this function
/// does not consider it
/// </remarks>
public class InNeck : CandlestickPattern
{
private readonly int _equalAveragePeriod;
private readonly int _bodyLongAveragePeriod;
private decimal _equalPeriodTotal;
private decimal _bodyLongPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="InNeck"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public InNeck(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.Equal).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod) + 1 + 1)
{
_equalAveragePeriod = CandleSettings.Get(CandleSettingType.Equal).AveragePeriod;
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="InNeck"/> class.
/// </summary>
public InNeck()
: this("INNECK")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _equalAveragePeriod)
{
_equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]);
}
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[1]);
}
return 0m;
}
decimal value;
if (
// 1st: black
GetCandleColor(window[1]) == CandleColor.Black &&
// long
GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[1]) &&
// 2nd: white
GetCandleColor(input) == CandleColor.White &&
// open below prior low
input.Open < window[1].Low &&
// close slightly into prior body
input.Close <= window[1].Close + GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1]) &&
input.Close >= window[1].Close
)
value = -1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]) -
GetCandleRange(CandleSettingType.Equal, window[_equalAveragePeriod + 1]);
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[1]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 1]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_equalPeriodTotal = 0m;
_bodyLongPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,142 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Inverted Hammer candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - small real body
/// - long upper shadow
/// - no, or very short, lower shadow
/// - gap down
/// The meaning of "short", "very short" and "long" is specified with SetCandleSettings;
/// The returned value is positive(+1): inverted hammer is always bullish;
/// The user should consider that an inverted hammer must appear in a downtrend, while this function does not consider it
/// </remarks>
public class InvertedHammer : CandlestickPattern
{
private readonly int _bodyShortAveragePeriod;
private readonly int _shadowLongAveragePeriod;
private readonly int _shadowVeryShortAveragePeriod;
private decimal _bodyShortPeriodTotal;
private decimal _shadowLongPeriodTotal;
private decimal _shadowVeryShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="InvertedHammer"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public InvertedHammer(string name)
: base(name, Math.Max(Math.Max(CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod),
CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod) + 1 + 1)
{
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_shadowLongAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod;
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="InvertedHammer"/> class.
/// </summary>
public InvertedHammer()
: this("INVERTEDHAMMER")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyShortAveragePeriod)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
if (Samples >= Period - _shadowLongAveragePeriod)
{
_shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, input);
}
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
return 0m;
}
decimal value;
if (
// small rb
GetRealBody(input) < GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
// long upper shadow
GetUpperShadow(input) > GetCandleAverage(CandleSettingType.ShadowLong, _shadowLongPeriodTotal, input) &&
// very short lower shadow
GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input) &&
// gap down
GetRealBodyGapDown(input, window[1])
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
_shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, input) -
GetCandleRange(CandleSettingType.ShadowLong, window[_shadowLongAveragePeriod]);
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[_shadowVeryShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyShortPeriodTotal = 0m;
_shadowLongPeriodTotal = 0m;
_shadowVeryShortPeriodTotal = 0m;
base.Reset();
}
}
}
+141
View File
@@ -0,0 +1,141 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Kicking candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: marubozu
/// - second candle: opposite color marubozu
/// - gap between the two candles: upside gap if black then white, downside gap if white then black
/// The meaning of "long body" and "very short shadow" is specified with SetCandleSettings
/// The returned value is positive(+1) when bullish or negative(-1) when bearish
/// </remarks>
public class Kicking : CandlestickPattern
{
private readonly int _shadowVeryShortAveragePeriod;
private readonly int _bodyLongAveragePeriod;
private decimal[] _shadowVeryShortPeriodTotal = new decimal[2];
private decimal[] _bodyLongPeriodTotal = new decimal[2];
/// <summary>
/// Initializes a new instance of the <see cref="Kicking"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public Kicking(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod) + 1 + 1)
{
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="Kicking"/> class.
/// </summary>
public Kicking()
: this("KICKING")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal[1] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[1]);
_shadowVeryShortPeriodTotal[0] += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal[1] += GetCandleRange(CandleSettingType.BodyLong, window[1]);
_bodyLongPeriodTotal[0] += GetCandleRange(CandleSettingType.BodyLong, input);
}
return 0m;
}
decimal value;
if (
// opposite candles
(int)GetCandleColor(window[1]) == -(int)GetCandleColor(input) &&
// 1st marubozu
GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal[1], window[1]) &&
GetUpperShadow(window[1]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[1], window[1]) &&
GetLowerShadow(window[1]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[1], window[1]) &&
// 2nd marubozu
GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal[0], input) &&
GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[0], input) &&
GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[0], input) &&
// gap
(
(GetCandleColor(window[1]) == CandleColor.Black && GetCandleGapUp(input, window[1]))
||
(GetCandleColor(window[1]) == CandleColor.White && GetCandleGapDown(input, window[1]))
)
)
value = (int)GetCandleColor(input);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
for (var i = 1; i >= 0; i--)
{
_shadowVeryShortPeriodTotal[i] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[i]) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[i + _shadowVeryShortAveragePeriod]);
_bodyLongPeriodTotal[i] += GetCandleRange(CandleSettingType.BodyLong, window[i]) -
GetCandleRange(CandleSettingType.BodyLong, window[i + _bodyLongAveragePeriod]);
}
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_shadowVeryShortPeriodTotal = new decimal[2];
_bodyLongPeriodTotal = new decimal[2];
base.Reset();
}
}
}
@@ -0,0 +1,142 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Kicking (bull/bear determined by the longer marubozu) candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: marubozu
/// - second candle: opposite color marubozu
/// - gap between the two candles: upside gap if black then white, downside gap if white then black
/// The meaning of "long body" and "very short shadow" is specified with SetCandleSettings
/// The returned value is positive(+1) when bullish or negative(-1) when bearish; the longer of the two
/// marubozu determines the bullishness or bearishness of this pattern
/// </remarks>
public class KickingByLength : CandlestickPattern
{
private readonly int _shadowVeryShortAveragePeriod;
private readonly int _bodyLongAveragePeriod;
private decimal[] _shadowVeryShortPeriodTotal = new decimal[2];
private decimal[] _bodyLongPeriodTotal = new decimal[2];
/// <summary>
/// Initializes a new instance of the <see cref="KickingByLength"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public KickingByLength(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod) + 1 + 1)
{
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="KickingByLength"/> class.
/// </summary>
public KickingByLength()
: this("KICKINGBYLENGTH")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal[1] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[1]);
_shadowVeryShortPeriodTotal[0] += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal[1] += GetCandleRange(CandleSettingType.BodyLong, window[1]);
_bodyLongPeriodTotal[0] += GetCandleRange(CandleSettingType.BodyLong, input);
}
return 0m;
}
decimal value;
if (
// opposite candles
(int)GetCandleColor(window[1]) == -(int)GetCandleColor(input) &&
// 1st marubozu
GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal[1], window[1]) &&
GetUpperShadow(window[1]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[1], window[1]) &&
GetLowerShadow(window[1]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[1], window[1]) &&
// 2nd marubozu
GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal[0], input) &&
GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[0], input) &&
GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[0], input) &&
// gap
(
(GetCandleColor(window[1]) == CandleColor.Black && GetCandleGapUp(input, window[1]))
||
(GetCandleColor(window[1]) == CandleColor.White && GetCandleGapDown(input, window[1]))
)
)
value = (int)GetCandleColor(GetRealBody(input) > GetRealBody(window[1]) ? input : window[1]);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
for (var i = 1; i >= 0; i--)
{
_shadowVeryShortPeriodTotal[i] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[i]) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[i + _shadowVeryShortAveragePeriod]);
_bodyLongPeriodTotal[i] += GetCandleRange(CandleSettingType.BodyLong, window[i]) -
GetCandleRange(CandleSettingType.BodyLong, window[i + _bodyLongAveragePeriod]);
}
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_shadowVeryShortPeriodTotal = new decimal[2];
_bodyLongPeriodTotal = new decimal[2];
base.Reset();
}
}
}
@@ -0,0 +1,125 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Ladder Bottom candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - three black candlesticks with consecutively lower opens and closes
/// - fourth candle: black candle with an upper shadow(it's supposed to be not very short)
/// - fifth candle: white candle that opens above prior candle's body and closes above prior candle's high
/// The meaning of "very short" is specified with SetCandleSettings
/// The returned value is positive (+1): ladder bottom is always bullish;
/// The user should consider that ladder bottom is significant when it appears in a downtrend,
/// while this function does not consider it
/// </remarks>
public class LadderBottom : CandlestickPattern
{
private readonly int _shadowVeryShortAveragePeriod;
private decimal _shadowVeryShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="LadderBottom"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public LadderBottom(string name)
: base(name, CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod + 4 + 1)
{
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="LadderBottom"/> class.
/// </summary>
public LadderBottom()
: this("LADDERBOTTOM")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, window[1]);
}
return 0m;
}
decimal value;
if (
// 3 black candlesticks
GetCandleColor(window[4]) == CandleColor.Black &&
GetCandleColor(window[3]) == CandleColor.Black &&
GetCandleColor(window[2]) == CandleColor.Black &&
// with consecutively lower opens
window[4].Open > window[3].Open && window[3].Open > window[2].Open &&
// and closes
window[4].Close > window[3].Close && window[3].Close > window[2].Close &&
// 4th: black with an upper shadow
GetCandleColor(window[1]) == CandleColor.Black &&
GetUpperShadow(window[1]) > GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, window[1]) &&
// 5th: white
GetCandleColor(input) == CandleColor.White &&
// that opens above prior candle's body
input.Open > window[1].Open &&
// and closes above prior candle's high
input.Close > window[1].High
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, window[1]) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[_shadowVeryShortAveragePeriod + 1]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_shadowVeryShortPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,122 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Long Legged Doji candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - doji body
/// - one or two long shadows
/// The meaning of "doji" is specified with SetCandleSettings
/// The returned value is always positive(+1) but this does not mean it is bullish: long legged doji shows uncertainty
/// </remarks>
public class LongLeggedDoji : CandlestickPattern
{
private readonly int _bodyDojiAveragePeriod;
private readonly int _shadowLongAveragePeriod;
private decimal _bodyDojiPeriodTotal;
private decimal _shadowLongPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="LongLeggedDoji"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public LongLeggedDoji(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod) + 1)
{
_bodyDojiAveragePeriod = CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod;
_shadowLongAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="LongLeggedDoji"/> class.
/// </summary>
public LongLeggedDoji()
: this("LONGLEGGEDDOJI")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyDojiAveragePeriod)
{
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input);
}
if (Samples >= Period - _shadowLongAveragePeriod)
{
_shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, input);
}
return 0m;
}
decimal value;
if (GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, input) &&
(GetLowerShadow(input) > GetCandleAverage(CandleSettingType.ShadowLong, _shadowLongPeriodTotal, input)
||
GetUpperShadow(input) > GetCandleAverage(CandleSettingType.ShadowLong, _shadowLongPeriodTotal, input)
)
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input) -
GetCandleRange(CandleSettingType.BodyDoji, window[_bodyDojiAveragePeriod]);
_shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, input) -
GetCandleRange(CandleSettingType.ShadowLong, window[_shadowLongAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyDojiPeriodTotal = 0m;
_shadowLongPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,120 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Long Line Candle candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - long real body
/// - short upper and lower shadow
/// The meaning of "long" and "short" is specified with SetCandleSettings
/// The returned value is positive(+1) when white(bullish), negative(-1) when black(bearish)
/// </remarks>
public class LongLineCandle : CandlestickPattern
{
private readonly int _bodyLongAveragePeriod;
private readonly int _shadowShortAveragePeriod;
private decimal _bodyLongPeriodTotal;
private decimal _shadowShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="LongLineCandle"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public LongLineCandle(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowShort).AveragePeriod) + 1)
{
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_shadowShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="LongLineCandle"/> class.
/// </summary>
public LongLineCandle()
: this("LONGLINECANDLE")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
}
if (Samples >= Period - _shadowShortAveragePeriod)
{
_shadowShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowShort, input);
}
return 0m;
}
decimal value;
if (GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, input) &&
GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowShort, _shadowShortPeriodTotal, input) &&
GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowShort, _shadowShortPeriodTotal, input)
)
value = (int)GetCandleColor(input);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod]);
_shadowShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowShort, input) -
GetCandleRange(CandleSettingType.ShadowShort, window[_shadowShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0m;
_shadowShortPeriodTotal = 0m;
base.Reset();
}
}
}
+120
View File
@@ -0,0 +1,120 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Marubozu candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - long real body
/// - no or very short upper and lower shadow
/// The meaning of "long" and "very short" is specified with SetCandleSettings
/// The returned value is positive(+1) when white(bullish), negative(-1) when black(bearish)
/// </remarks>
public class Marubozu : CandlestickPattern
{
private readonly int _bodyLongAveragePeriod;
private readonly int _shadowVeryShortAveragePeriod;
private decimal _bodyLongPeriodTotal;
private decimal _shadowVeryShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="Marubozu"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public Marubozu(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod) + 1)
{
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="Marubozu"/> class.
/// </summary>
public Marubozu()
: this("MARUBOZU")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
}
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
return 0m;
}
decimal value;
if (GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, input) &&
GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input) &&
GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input)
)
value = (int)GetCandleColor(input);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod]);
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[_shadowVeryShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0m;
_shadowVeryShortPeriodTotal = 0m;
base.Reset();
}
}
}
+168
View File
@@ -0,0 +1,168 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Mat Hold candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long white candle
/// - upside gap between the first and the second bodies
/// - second candle: small black candle
/// - third and fourth candles: falling small real body candlesticks(commonly black) that hold within the long
/// white candle's body and are higher than the reaction days of the rising three methods
/// - fifth candle: white candle that opens above the previous small candle's close and closes higher than the
/// high of the highest reaction day
/// The meaning of "short" and "long" is specified with SetCandleSettings;
/// "hold within" means "a part of the real body must be within";
/// penetration is the maximum percentage of the first white body the reaction days can penetrate(it is
/// to specify how much the reaction days should be "higher than the reaction days of the rising three methods")
/// The returned value is positive(+1): mat hold is always bullish
/// </remarks>
public class MatHold : CandlestickPattern
{
private readonly decimal _penetration;
private readonly int _bodyShortAveragePeriod;
private readonly int _bodyLongAveragePeriod;
private decimal[] _bodyPeriodTotal = new decimal[5];
/// <summary>
/// Initializes a new instance of the <see cref="MatHold"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
/// <param name="penetration">Percentage of penetration of a candle within another candle</param>
public MatHold(string name, decimal penetration = 0.5m)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod) + 4 + 1)
{
_penetration = penetration;
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="MatHold"/> class.
/// </summary>
/// <param name="penetration">Percentage of penetration of a candle within another candle</param>
public MatHold(decimal penetration)
: this("MATHOLD", penetration)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MatHold"/> class.
/// </summary>
public MatHold()
: this("MATHOLD")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples > Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples > Period - _bodyShortAveragePeriod)
{
_bodyPeriodTotal[3] += GetCandleRange(CandleSettingType.BodyShort, window[3]);
_bodyPeriodTotal[2] += GetCandleRange(CandleSettingType.BodyShort, window[2]);
_bodyPeriodTotal[1] += GetCandleRange(CandleSettingType.BodyShort, window[1]);
}
if (Samples > Period - _bodyLongAveragePeriod)
{
_bodyPeriodTotal[4] += GetCandleRange(CandleSettingType.BodyLong, window[4]);
}
return 0m;
}
decimal value;
if (
// 1st long, then 3 small
GetRealBody(window[4]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyPeriodTotal[4], window[4]) &&
GetRealBody(window[3]) < GetCandleAverage(CandleSettingType.BodyShort, _bodyPeriodTotal[3], window[3]) &&
GetRealBody(window[2]) < GetCandleAverage(CandleSettingType.BodyShort, _bodyPeriodTotal[2], window[2]) &&
GetRealBody(window[1]) < GetCandleAverage(CandleSettingType.BodyShort, _bodyPeriodTotal[1], window[1]) &&
// white, black, 2 black or white, white
GetCandleColor(window[4]) == CandleColor.White &&
GetCandleColor(window[3]) == CandleColor.Black &&
GetCandleColor(input) == CandleColor.White &&
// upside gap 1st to 2nd
GetRealBodyGapUp(window[3], window[4]) &&
// 3rd to 4th hold within 1st: a part of the real body must be within 1st real body
Math.Min(window[2].Open, window[2].Close) < window[4].Close &&
Math.Min(window[1].Open, window[1].Close) < window[4].Close &&
// reaction days penetrate first body less than optInPenetration percent
Math.Min(window[2].Open, window[2].Close) > window[4].Close - GetRealBody(window[4]) * _penetration &&
Math.Min(window[1].Open, window[1].Close) > window[4].Close - GetRealBody(window[4]) * _penetration &&
// 2nd to 4th are falling
Math.Max(window[2].Close, window[2].Open) < window[3].Open &&
Math.Max(window[1].Close, window[1].Open) < Math.Max(window[2].Close, window[2].Open) &&
// 5th opens above the prior close
input.Open > window[1].Close &&
// 5th closes above the highest high of the reaction days
input.Close > Math.Max(Math.Max(window[3].High, window[2].High), window[1].High)
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyPeriodTotal[4] += GetCandleRange(CandleSettingType.BodyLong, window[4]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 4]);
for (var i = 3; i >= 1; i--)
{
_bodyPeriodTotal[i] += GetCandleRange(CandleSettingType.BodyShort, window[i]) -
GetCandleRange(CandleSettingType.BodyShort, window[i + _bodyShortAveragePeriod]);
}
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyPeriodTotal = new decimal[5];
base.Reset();
}
}
}
@@ -0,0 +1,112 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Matching Low candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: black candle
/// - second candle: black candle with the close equal to the previous close
/// The meaning of "equal" is specified with SetCandleSettings
/// The returned value is always positive(+1): matching low is always bullish;
/// </remarks>
public class MatchingLow : CandlestickPattern
{
private readonly int _equalAveragePeriod;
private decimal _equalPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="MatchingLow"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public MatchingLow(string name)
: base(name, CandleSettings.Get(CandleSettingType.Equal).AveragePeriod + 1 + 1)
{
_equalAveragePeriod = CandleSettings.Get(CandleSettingType.Equal).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="MatchingLow"/> class.
/// </summary>
public MatchingLow()
: this("MATCHINGLOW")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _equalAveragePeriod)
{
_equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]);
}
return 0m;
}
decimal value;
if (
// first black
GetCandleColor(window[1]) == CandleColor.Black &&
// second black
GetCandleColor(input) == CandleColor.Black &&
// 1st and 2nd same close
input.Close <= window[1].Close + GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1]) &&
input.Close >= window[1].Close - GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1])
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]) -
GetCandleRange(CandleSettingType.Equal, window[_equalAveragePeriod + 1]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_equalPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,166 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Morning Doji Star candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long black real body
/// - second candle: doji gapping down
/// - third candle: white real body that moves well within the first candle's real body
/// The meaning of "doji" and "long" is specified with SetCandleSettings
/// The meaning of "moves well within" is specified with penetration and "moves" should mean the real body should
/// not be short ("short" is specified with SetCandleSettings) - Greg Morris wants it to be long, someone else want
/// it to be relatively long
/// The returned value is positive(+1): morning doji star is always bullish;
/// the user should consider that a morning star is significant when it appears in a downtrend,
/// while this function does not consider the trend
/// </remarks>
public class MorningDojiStar : CandlestickPattern
{
private readonly decimal _penetration;
private readonly int _bodyDojiAveragePeriod;
private readonly int _bodyLongAveragePeriod;
private readonly int _bodyShortAveragePeriod;
private decimal _bodyDojiPeriodTotal;
private decimal _bodyLongPeriodTotal;
private decimal _bodyShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="MorningDojiStar"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
/// <param name="penetration">Percentage of penetration of a candle within another candle</param>
public MorningDojiStar(string name, decimal penetration = 0.3m)
: base(name, Math.Max(Math.Max(CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod),
CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod) + 2 + 1)
{
_penetration = penetration;
_bodyDojiAveragePeriod = CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod;
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="MorningDojiStar"/> class.
/// </summary>
/// <param name="penetration">Percentage of penetration of a candle within another candle</param>
public MorningDojiStar(decimal penetration)
: this("MORNINGDOJISTAR", penetration)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MorningDojiStar"/> class.
/// </summary>
public MorningDojiStar()
: this("MORNINGDOJISTAR")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod - 2 && Samples < Period - 2)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
}
if (Samples >= Period - _bodyDojiAveragePeriod - 1 && Samples < Period - 1)
{
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input);
}
if (Samples >= Period - _bodyShortAveragePeriod)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
return 0m;
}
decimal value;
if (
// 1st: long
GetRealBody(window[2]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[2]) &&
// black
GetCandleColor(window[2]) == CandleColor.Black &&
// 2nd: doji
GetRealBody(window[1]) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, window[1]) &&
// gapping down
GetRealBodyGapDown(window[1], window[2]) &&
// 3rd: longer than short
GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
// white real body
GetCandleColor(input) == CandleColor.White &&
// closing well within 1st rb
input.Close > window[2].Close + GetRealBody(window[2]) * _penetration
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[2]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 2]);
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, window[1]) -
GetCandleRange(CandleSettingType.BodyDoji, window[_bodyDojiAveragePeriod + 1]);
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0;
_bodyDojiPeriodTotal = 0;
_bodyShortPeriodTotal = 0;
base.Reset();
}
}
}
@@ -0,0 +1,159 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Morning Star candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long black real body
/// - second candle: star(Short real body gapping down)
/// - third candle: white real body that moves well within the first candle's real body
/// The meaning of "short" and "long" is specified with SetCandleSettings
/// The meaning of "moves well within" is specified with penetration and "moves" should mean the real body should
/// not be short ("short" is specified with SetCandleSettings) - Greg Morris wants it to be long, someone else want
/// it to be relatively long
/// The returned value is positive(+1): morning star is always bullish;
/// The user should consider that a morning star is significant when it appears in a downtrend,
/// while this function does not consider the trend
/// </remarks>
public class MorningStar : CandlestickPattern
{
private readonly decimal _penetration;
private readonly int _bodyLongAveragePeriod;
private readonly int _bodyShortAveragePeriod;
private decimal _bodyLongPeriodTotal;
private decimal _bodyShortPeriodTotal;
private decimal _bodyShortPeriodTotal2;
/// <summary>
/// Initializes a new instance of the <see cref="MorningStar"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
/// <param name="penetration">Percentage of penetration of a candle within another candle</param>
public MorningStar(string name, decimal penetration = 0.3m)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod) + 2 + 1)
{
_penetration = penetration;
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="MorningStar"/> class.
/// </summary>
/// <param name="penetration">Percentage of penetration of a candle within another candle</param>
public MorningStar(decimal penetration)
: this("MORNINGSTAR", penetration)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MorningStar"/> class.
/// </summary>
public MorningStar()
: this("MORNINGSTAR")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod - 2 && Samples < Period - 2)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
}
if (Samples >= Period - _bodyShortAveragePeriod - 1 && Samples < Period - 1)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
_bodyShortPeriodTotal2 += GetCandleRange(CandleSettingType.BodyShort, window[1]);
}
return 0m;
}
decimal value;
if (
// 1st: long
GetRealBody(window[2]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[2]) &&
// black
GetCandleColor(window[2]) == CandleColor.Black &&
// 2nd: short
GetRealBody(window[1]) <= GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, window[1]) &&
// gapping down
GetRealBodyGapDown(window[1], window[2]) &&
// 3rd: longer than short
GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal2, input) &&
// white real body
GetCandleColor(input) == CandleColor.White &&
// closing well within 1st rb
input.Close > window[2].Close + GetRealBody(window[2]) * _penetration
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[2]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 2]);
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, window[1]) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod + 1]);
_bodyShortPeriodTotal2 += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0;
_bodyShortPeriodTotal = 0;
_bodyShortPeriodTotal2 = 0;
base.Reset();
}
}
}
+131
View File
@@ -0,0 +1,131 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// On-Neck candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long black candle
/// - second candle: white candle with open below previous day low and close equal to previous day low
/// The meaning of "equal" is specified with SetCandleSettings
/// The returned value is negative(-1): on-neck is always bearish
/// The user should consider that on-neck is significant when it appears in a downtrend, while this function
/// does not consider it
/// </remarks>
public class OnNeck : CandlestickPattern
{
private readonly int _equalAveragePeriod;
private readonly int _bodyLongAveragePeriod;
private decimal _equalPeriodTotal;
private decimal _bodyLongPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="OnNeck"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public OnNeck(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.Equal).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod) + 1 + 1)
{
_equalAveragePeriod = CandleSettings.Get(CandleSettingType.Equal).AveragePeriod;
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="OnNeck"/> class.
/// </summary>
public OnNeck()
: this("ONNECK")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _equalAveragePeriod)
{
_equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]);
}
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[1]);
}
return 0m;
}
decimal value;
if (
// 1st: black
GetCandleColor(window[1]) == CandleColor.Black &&
// long
GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[1]) &&
// 2nd: white
GetCandleColor(input) == CandleColor.White &&
// open below prior low
input.Open < window[1].Low &&
// close equal to prior low
input.Close <= window[1].Low + GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1]) &&
input.Close >= window[1].Low - GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1])
)
value = -1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]) -
GetCandleRange(CandleSettingType.Equal, window[_equalAveragePeriod + 1]);
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[1]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 1]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_equalPeriodTotal = 0m;
_bodyLongPeriodTotal = 0m;
base.Reset();
}
}
}
+126
View File
@@ -0,0 +1,126 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Piercing candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long black candle
/// - second candle: long white candle with open below previous day low and close at least at 50% of previous day
/// real body
/// The meaning of "long" is specified with SetCandleSettings
/// The returned value is positive(+1): piercing pattern is always bullish
/// The user should consider that a piercing pattern is significant when it appears in a downtrend, while
/// this function does not consider it
/// </remarks>
public class Piercing : CandlestickPattern
{
private readonly int _bodyLongAveragePeriod;
private decimal[] _bodyLongPeriodTotal = new decimal[2];
/// <summary>
/// Initializes a new instance of the <see cref="Piercing"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public Piercing(string name)
: base(name, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod + 1 + 1)
{
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="Piercing"/> class.
/// </summary>
public Piercing()
: this("PIERCING")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal[1] += GetCandleRange(CandleSettingType.BodyLong, window[1]);
_bodyLongPeriodTotal[0] += GetCandleRange(CandleSettingType.BodyLong, input);
}
return 0m;
}
decimal value;
if (
// 1st: black
GetCandleColor(window[1]) == CandleColor.Black &&
// long
GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal[1], window[1]) &&
// 2nd: white
GetCandleColor(input) == CandleColor.White &&
// long
GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal[0], input) &&
// open below prior low
input.Open < window[1].Low &&
// close within prior body
input.Close < window[1].Open &&
// above midpoint
input.Close > window[1].Close + GetRealBody(window[1]) * 0.5m
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
for (var i = 1; i >= 0; i--)
{
_bodyLongPeriodTotal[i] += GetCandleRange(CandleSettingType.BodyLong, window[i]) -
GetCandleRange(CandleSettingType.BodyLong, window[i + _bodyLongAveragePeriod]);
}
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = new decimal[2];
base.Reset();
}
}
}
@@ -0,0 +1,147 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Rickshaw Man candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - doji body
/// - two long shadows
/// - body near the midpoint of the high-low range
/// The meaning of "doji" and "near" is specified with SetCandleSettings
/// The returned value is always positive(+1) but this does not mean it is bullish: rickshaw man shows uncertainty
/// </remarks>
public class RickshawMan : CandlestickPattern
{
private readonly int _bodyDojiAveragePeriod;
private readonly int _shadowLongAveragePeriod;
private readonly int _nearAveragePeriod;
private decimal _bodyDojiPeriodTotal;
private decimal _shadowLongPeriodTotal;
private decimal _nearPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="RickshawMan"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public RickshawMan(string name)
: base(name, Math.Max(Math.Max(CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod),
CandleSettings.Get(CandleSettingType.Near).AveragePeriod) + 1)
{
_bodyDojiAveragePeriod = CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod;
_shadowLongAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod;
_nearAveragePeriod = CandleSettings.Get(CandleSettingType.Near).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="RickshawMan"/> class.
/// </summary>
public RickshawMan()
: this("RICKSHAWMAN")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyDojiAveragePeriod)
{
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input);
}
if (Samples >= Period - _shadowLongAveragePeriod)
{
_shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, input);
}
if (Samples >= Period - _nearAveragePeriod)
{
_nearPeriodTotal += GetCandleRange(CandleSettingType.Near, input);
}
return 0m;
}
decimal value;
if (
// doji
GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, input) &&
// long shadow
GetLowerShadow(input) > GetCandleAverage(CandleSettingType.ShadowLong, _shadowLongPeriodTotal, input) &&
// long shadow
GetUpperShadow(input) > GetCandleAverage(CandleSettingType.ShadowLong, _shadowLongPeriodTotal, input) &&
// body near midpoint
(
Math.Min(input.Open, input.Close)
<= input.Low + GetHighLowRange(input) / 2 + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, input)
&&
Math.Max(input.Open, input.Close)
>= input.Low + GetHighLowRange(input) / 2 - GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, input)
)
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input) -
GetCandleRange(CandleSettingType.BodyDoji, window[_bodyDojiAveragePeriod]);
_shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, input) -
GetCandleRange(CandleSettingType.ShadowLong, window[_shadowLongAveragePeriod]);
_nearPeriodTotal += GetCandleRange(CandleSettingType.Near, input) -
GetCandleRange(CandleSettingType.Near, window[_nearAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyDojiPeriodTotal = 0;
_shadowLongPeriodTotal = 0;
_nearPeriodTotal = 0;
base.Reset();
}
}
}
@@ -0,0 +1,152 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Rising/Falling Three Methods candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long white (black) candlestick
/// - then: group of falling(rising) small real body candlesticks(commonly black (white)) that hold within
/// the prior long candle's range: ideally they should be three but two or more than three are ok too
/// - final candle: long white(black) candle that opens above(below) the previous small candle's close
/// and closes above(below) the first long candle's close
/// The meaning of "short" and "long" is specified with SetCandleSettings; here only patterns with 3 small candles
/// are considered;
/// The returned value is positive(+1) or negative(-1)
/// </remarks>
public class RiseFallThreeMethods : CandlestickPattern
{
private readonly int _bodyShortAveragePeriod;
private readonly int _bodyLongAveragePeriod;
private decimal[] _bodyPeriodTotal = new decimal[5];
/// <summary>
/// Initializes a new instance of the <see cref="RiseFallThreeMethods"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public RiseFallThreeMethods(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod) + 4 + 1)
{
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="RiseFallThreeMethods"/> class.
/// </summary>
public RiseFallThreeMethods()
: this("RISEFALLTHREEMETHODS")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples > Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples > Period - _bodyShortAveragePeriod)
{
_bodyPeriodTotal[3] += GetCandleRange(CandleSettingType.BodyShort, window[3]);
_bodyPeriodTotal[2] += GetCandleRange(CandleSettingType.BodyShort, window[2]);
_bodyPeriodTotal[1] += GetCandleRange(CandleSettingType.BodyShort, window[1]);
}
if (Samples > Period - _bodyLongAveragePeriod)
{
_bodyPeriodTotal[4] += GetCandleRange(CandleSettingType.BodyLong, window[4]);
_bodyPeriodTotal[0] += GetCandleRange(CandleSettingType.BodyLong, input);
}
return 0m;
}
decimal value;
if (
// 1st long, then 3 small, 5th long
GetRealBody(window[4]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyPeriodTotal[4], window[4]) &&
GetRealBody(window[3]) < GetCandleAverage(CandleSettingType.BodyShort, _bodyPeriodTotal[3], window[3]) &&
GetRealBody(window[2]) < GetCandleAverage(CandleSettingType.BodyShort, _bodyPeriodTotal[2], window[2]) &&
GetRealBody(window[1]) < GetCandleAverage(CandleSettingType.BodyShort, _bodyPeriodTotal[1], window[1]) &&
GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyLong, _bodyPeriodTotal[0], input) &&
// white, 3 black, white || black, 3 white, black
(int)GetCandleColor(window[4]) == -(int)GetCandleColor(window[3]) &&
GetCandleColor(window[3]) == GetCandleColor(window[2]) &&
GetCandleColor(window[2]) == GetCandleColor(window[1]) &&
(int)GetCandleColor(window[1]) == -(int)GetCandleColor(input) &&
// 2nd to 4th hold within 1st: a part of the real body must be within 1st range
Math.Min(window[3].Open, window[3].Close) < window[4].High && Math.Max(window[3].Open, window[3].Close) > window[4].Low &&
Math.Min(window[2].Open, window[2].Close) < window[4].High && Math.Max(window[2].Open, window[2].Close) > window[4].Low &&
Math.Min(window[1].Open, window[1].Close) < window[4].High && Math.Max(window[1].Open, window[1].Close) > window[4].Low &&
// 2nd to 4th are falling (rising)
window[2].Close * (int)GetCandleColor(window[4]) < window[3].Close * (int)GetCandleColor(window[4]) &&
window[1].Close * (int)GetCandleColor(window[4]) < window[2].Close * (int)GetCandleColor(window[4]) &&
// 5th opens above (below) the prior close
input.Open * (int)GetCandleColor(window[4]) > window[1].Close * (int)GetCandleColor(window[4]) &&
// 5th closes above (below) the 1st close
input.Close * (int)GetCandleColor(window[4]) > window[4].Close * (int)GetCandleColor(window[4])
)
value = (int)GetCandleColor(window[4]);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyPeriodTotal[4] += GetCandleRange(CandleSettingType.BodyLong, window[4]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 4]);
for (var i = 3; i >= 1; i--)
{
_bodyPeriodTotal[i] += GetCandleRange(CandleSettingType.BodyShort, window[i]) -
GetCandleRange(CandleSettingType.BodyShort, window[i + _bodyShortAveragePeriod]);
}
_bodyPeriodTotal[0] += GetCandleRange(CandleSettingType.BodyLong, input) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyPeriodTotal = new decimal[5];
base.Reset();
}
}
}
@@ -0,0 +1,151 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Separating Lines candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: black (white) candle
/// - second candle: bullish(bearish) belt hold with the same open as the prior candle
/// The meaning of "long body" and "very short shadow" of the belt hold is specified with SetCandleSettings
/// The returned value is positive(+1) when bullish or negative(-1) when bearish;
/// The user should consider that separating lines is significant when coming in a trend and the belt hold has
/// the same direction of the trend, while this function does not consider it
/// </remarks>
public class SeparatingLines : CandlestickPattern
{
private readonly int _shadowVeryShortAveragePeriod;
private readonly int _bodyLongAveragePeriod;
private readonly int _equalAveragePeriod;
private decimal _shadowVeryShortPeriodTotal;
private decimal _bodyLongPeriodTotal;
private decimal _equalPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="SeparatingLines"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public SeparatingLines(string name)
: base(name, Math.Max(Math.Max(CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod),
CandleSettings.Get(CandleSettingType.Equal).AveragePeriod) + 1 + 1)
{
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_equalAveragePeriod = CandleSettings.Get(CandleSettingType.Equal).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="SeparatingLines"/> class.
/// </summary>
public SeparatingLines()
: this("SEPARATINGLINES")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
}
if (Samples >= Period - _equalAveragePeriod)
{
_equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]);
}
return 0m;
}
decimal value;
if (
// opposite candles
(int)GetCandleColor(window[1]) == -(int)GetCandleColor(input) &&
// same open
input.Open <= window[1].Open + GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1]) &&
input.Open >= window[1].Open - GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1]) &&
// belt hold: long body
GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, input) &&
(
// with no lower shadow if bullish
(GetCandleColor(input) == CandleColor.White &&
GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input)
)
||
// with no upper shadow if bearish
(GetCandleColor(input) == CandleColor.Black &&
GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input)
)
)
)
value = (int)GetCandleColor(input);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[_shadowVeryShortAveragePeriod]);
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod]);
_equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]) -
GetCandleRange(CandleSettingType.Equal, window[_equalAveragePeriod + 1]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_shadowVeryShortPeriodTotal = 0m;
_bodyLongPeriodTotal = 0m;
_equalPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,143 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Shooting Star candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - small real body
/// - long upper shadow
/// - no, or very short, lower shadow
/// - gap up from prior real body
/// The meaning of "short", "very short" and "long" is specified with SetCandleSettings;
/// The returned value is negative(-1): shooting star is always bearish;
/// The user should consider that a shooting star must appear in an uptrend, while this function does not consider it
/// </remarks>
public class ShootingStar : CandlestickPattern
{
private readonly int _bodyShortAveragePeriod;
private readonly int _shadowLongAveragePeriod;
private readonly int _shadowVeryShortAveragePeriod;
private decimal _bodyShortPeriodTotal;
private decimal _shadowLongPeriodTotal;
private decimal _shadowVeryShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="ShootingStar"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public ShootingStar(string name)
: base(name, Math.Max(Math.Max(CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod),
CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod) + 1 + 1)
{
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
_shadowLongAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod;
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="ShootingStar"/> class.
/// </summary>
public ShootingStar()
: this("SHOOTINGSTAR")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyShortAveragePeriod)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
if (Samples >= Period - _shadowLongAveragePeriod)
{
_shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, input);
}
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
return 0m;
}
decimal value;
if (
// small rb
GetRealBody(input) < GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
// long upper shadow
GetUpperShadow(input) > GetCandleAverage(CandleSettingType.ShadowLong, _shadowLongPeriodTotal, input) &&
// very short lower shadow
GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input) &&
// gap up
GetRealBodyGapUp(input, window[1])
)
value = -1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
_shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, input) -
GetCandleRange(CandleSettingType.ShadowLong, window[_shadowLongAveragePeriod]);
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[_shadowVeryShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyShortPeriodTotal = 0;
_shadowLongPeriodTotal = 0;
_shadowVeryShortPeriodTotal = 0;
base.Reset();
}
}
}
@@ -0,0 +1,121 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Short Line Candle candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - short real body
/// - short upper and lower shadow
/// The meaning of "short" is specified with SetCandleSettings
/// The returned value is positive(+1) when white, negative (-1) when black;
/// it does not mean bullish or bearish
/// </remarks>
public class ShortLineCandle : CandlestickPattern
{
private readonly int _bodyShortAveragePeriod;
private readonly int _shadowShortAveragePeriod;
private decimal _bodyShortPeriodTotal;
private decimal _shadowShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="ShortLineCandle"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public ShortLineCandle(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowShort).AveragePeriod) + 1)
{
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
_shadowShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="ShortLineCandle"/> class.
/// </summary>
public ShortLineCandle()
: this("SHORTLINECANDLE")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyShortAveragePeriod)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
if (Samples >= Period - _shadowShortAveragePeriod)
{
_shadowShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowShort, input);
}
return 0m;
}
decimal value;
if (GetRealBody(input) < GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowShort, _shadowShortPeriodTotal, input) &&
GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowShort, _shadowShortPeriodTotal, input)
)
value = (int)GetCandleColor(input);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
_shadowShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowShort, input) -
GetCandleRange(CandleSettingType.ShadowShort, window[_shadowShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyShortPeriodTotal = 0m;
_shadowShortPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,108 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Spinning Top candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - small real body
/// - shadows longer than the real body
/// The meaning of "short" is specified with SetCandleSettings
/// The returned value is positive(+1) when white or negative(-1) when black;
/// it does not mean bullish or bearish
/// </remarks>
public class SpinningTop : CandlestickPattern
{
private readonly int _bodyShortAveragePeriod;
private decimal _bodyShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="SpinningTop"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public SpinningTop(string name)
: base(name, CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod + 1)
{
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="SpinningTop"/> class.
/// </summary>
public SpinningTop()
: this("SPINNINGTOP")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyShortAveragePeriod)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
return 0m;
}
decimal value;
if (GetRealBody(input) < GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
GetUpperShadow(input) > GetRealBody(input) &&
GetLowerShadow(input) > GetRealBody(input)
)
value = (int)GetCandleColor(input);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyShortPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,175 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Stalled Pattern candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - three white candlesticks with consecutively higher closes
/// - first candle: long white
/// - second candle: long white with no or very short upper shadow opening within or near the previous white real body
/// and closing higher than the prior candle
/// - third candle: small white that gaps away or "rides on the shoulder" of the prior long real body(= it's at
/// the upper end of the prior real body)
/// The meanings of "long", "very short", "short", "near" are specified with SetCandleSettings;
/// The returned value is negative(-1): stalled pattern is always bearish;
/// The user should consider that stalled pattern is significant when it appears in uptrend, while this function
/// does not consider it
/// </remarks>
public class StalledPattern : CandlestickPattern
{
private readonly int _bodyLongAveragePeriod;
private readonly int _bodyShortAveragePeriod;
private readonly int _shadowVeryShortAveragePeriod;
private readonly int _nearAveragePeriod;
private decimal[] _bodyLongPeriodTotal = new decimal[3];
private decimal _bodyShortPeriodTotal;
private decimal _shadowVeryShortPeriodTotal;
private decimal[] _nearPeriodTotal = new decimal[3];
/// <summary>
/// Initializes a new instance of the <see cref="StalledPattern"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public StalledPattern(string name)
: base(name, Math.Max(Math.Max(CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod),
Math.Max(CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod, CandleSettings.Get(CandleSettingType.Near).AveragePeriod)) + 2 + 1)
{
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
_nearAveragePeriod = CandleSettings.Get(CandleSettingType.Near).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="StalledPattern"/> class.
/// </summary>
public StalledPattern()
: this("STALLEDPATTERN")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal[2] += GetCandleRange(CandleSettingType.BodyLong, window[2]);
_bodyLongPeriodTotal[1] += GetCandleRange(CandleSettingType.BodyLong, window[1]);
}
if (Samples >= Period - _bodyShortAveragePeriod)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, window[1]);
}
if (Samples >= Period - _nearAveragePeriod)
{
_nearPeriodTotal[2] += GetCandleRange(CandleSettingType.Near, window[2]);
_nearPeriodTotal[1] += GetCandleRange(CandleSettingType.Near, window[1]);
}
return 0m;
}
decimal value;
if (
// 1st white
GetCandleColor(window[2]) == CandleColor.White &&
// 2nd white
GetCandleColor(window[1]) == CandleColor.White &&
// 3rd white
GetCandleColor(input) == CandleColor.White &&
// consecutive higher closes
input.Close > window[1].Close && window[1].Close > window[2].Close &&
// 1st: long real body
GetRealBody(window[2]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal[2], window[2]) &&
// 2nd: long real body
GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal[1], window[1]) &&
// very short upper shadow
GetUpperShadow(window[1]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, window[1]) &&
// opens within/near 1st real body
window[1].Open > window[2].Open &&
window[1].Open <= window[2].Close + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal[2], window[2]) &&
// 3rd: small real body
GetRealBody(input) < GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
// rides on the shoulder of 2nd real body
input.Open >= window[1].Close - GetRealBody(input) - GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal[1], window[1])
)
value = -1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
for (var i = 2; i >= 1; i--)
{
_bodyLongPeriodTotal[i] += GetCandleRange(CandleSettingType.BodyLong, window[i]) -
GetCandleRange(CandleSettingType.BodyLong, window[i + _bodyLongAveragePeriod]);
_nearPeriodTotal[i] += GetCandleRange(CandleSettingType.Near, window[i]) -
GetCandleRange(CandleSettingType.Near, window[i + _nearAveragePeriod]);
}
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, window[1]) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[_bodyShortAveragePeriod + 1]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = new decimal[3];
_bodyShortPeriodTotal = 0;
_shadowVeryShortPeriodTotal = 0;
_nearPeriodTotal = new decimal[3];
base.Reset();
}
}
}
@@ -0,0 +1,119 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Stick Sandwich candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: black candle
/// - second candle: white candle that trades only above the prior close(low > prior close)
/// - third candle: black candle with the close equal to the first candle's close
/// The meaning of "equal" is specified with SetCandleSettings
/// The returned value is always positive(+1): stick sandwich is always bullish;
/// The user should consider that stick sandwich is significant when coming in a downtrend,
/// while this function does not consider it
/// </remarks>
public class StickSandwich : CandlestickPattern
{
private readonly int _equalAveragePeriod;
private decimal _equalPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="StickSandwich"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public StickSandwich(string name)
: base(name, CandleSettings.Get(CandleSettingType.Equal).AveragePeriod + 2 + 1)
{
_equalAveragePeriod = CandleSettings.Get(CandleSettingType.Equal).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="StickSandwich"/> class.
/// </summary>
public StickSandwich()
: this("STICKSANDWICH")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _equalAveragePeriod)
{
_equalPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[2]);
}
return 0m;
}
decimal value;
if (
// first black
GetCandleColor(window[2]) == CandleColor.Black &&
// second white
GetCandleColor(window[1]) == CandleColor.White &&
// third black
GetCandleColor(input) == CandleColor.Black &&
// 2nd low > prior close
window[1].Low > window[2].Close &&
// 1st and 3rd same close
input.Close <= window[2].Close + GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[2]) &&
input.Close >= window[2].Close - GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[2])
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[2]) -
GetCandleRange(CandleSettingType.Equal, window[_equalAveragePeriod + 2]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_equalPeriodTotal = 0m;
base.Reset();
}
}
}
+135
View File
@@ -0,0 +1,135 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Takuri (Dragonfly Doji with very long lower shadow) candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - doji body
/// - open and close at the high of the day = no or very short upper shadow
/// - very long lower shadow
/// The meaning of "doji", "very short" and "very long" is specified with SetCandleSettings
/// The returned value is always positive(+1) but this does not mean it is bullish: takuri must be considered
/// relatively to the trend
/// </remarks>
public class Takuri : CandlestickPattern
{
private readonly int _bodyDojiAveragePeriod;
private readonly int _shadowVeryShortAveragePeriod;
private readonly int _shadowVeryLongAveragePeriod;
private decimal _bodyDojiPeriodTotal;
private decimal _shadowVeryShortPeriodTotal;
private decimal _shadowVeryLongPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="Takuri"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public Takuri(string name)
: base(name, Math.Max(Math.Max(CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod),
CandleSettings.Get(CandleSettingType.ShadowVeryLong).AveragePeriod) + 1)
{
_bodyDojiAveragePeriod = CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod;
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
_shadowVeryLongAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryLong).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="Takuri"/> class.
/// </summary>
public Takuri()
: this("TAKURI")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyDojiAveragePeriod)
{
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input);
}
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
if (Samples >= Period - _shadowVeryLongAveragePeriod)
{
_shadowVeryLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryLong, input);
}
return 0m;
}
decimal value;
if (GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, input) &&
GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input) &&
GetLowerShadow(input) > GetCandleAverage(CandleSettingType.ShadowVeryLong, _shadowVeryLongPeriodTotal, input)
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input) -
GetCandleRange(CandleSettingType.BodyDoji, window[_bodyDojiAveragePeriod]);
_shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[_shadowVeryShortAveragePeriod]);
_shadowVeryLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryLong, input) -
GetCandleRange(CandleSettingType.ShadowVeryLong, window[_shadowVeryLongAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyDojiPeriodTotal = 0m;
_shadowVeryShortPeriodTotal = 0m;
_shadowVeryLongPeriodTotal = 0m;
base.Reset();
}
}
}
+143
View File
@@ -0,0 +1,143 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Tasuki Gap candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - upside (downside) gap
/// - first candle after the window: white(black) candlestick
/// - second candle: black(white) candlestick that opens within the previous real body and closes under(above)
/// the previous real body inside the gap
/// - the size of two real bodies should be near the same
/// The meaning of "near" is specified with SetCandleSettings
/// The returned value is positive(+1) when bullish or negative(-1) when bearish;
/// The user should consider that tasuki gap is significant when it appears in a trend, while this function does
/// not consider it
/// </remarks>
public class TasukiGap : CandlestickPattern
{
private readonly int _nearAveragePeriod;
private decimal _nearPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="TasukiGap"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public TasukiGap(string name)
: base(name, CandleSettings.Get(CandleSettingType.Near).AveragePeriod + 2 + 1)
{
_nearAveragePeriod = CandleSettings.Get(CandleSettingType.Near).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="TasukiGap"/> class.
/// </summary>
public TasukiGap()
: this("TASUKIGAP")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _nearAveragePeriod)
{
_nearPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]);
}
return 0m;
}
decimal value;
if (
(
// upside gap
GetRealBodyGapUp(window[1], window[2]) &&
// 1st: white
GetCandleColor(window[1]) == CandleColor.White &&
// 2nd: black
GetCandleColor(input) == CandleColor.Black &&
// that opens within the white rb
input.Open < window[1].Close && input.Open > window[1].Open &&
// and closes under the white rb
input.Close < window[1].Open &&
// inside the gap
input.Close > Math.Max(window[2].Close, window[2].Open) &&
// size of 2 rb near the same
Math.Abs(GetRealBody(window[1]) - GetRealBody(input)) < GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, window[1])
) ||
(
// downside gap
GetRealBodyGapDown(window[1], window[2]) &&
// 1st: black
GetCandleColor(window[1]) == CandleColor.Black &&
// 2nd: white
GetCandleColor(input) == CandleColor.White &&
// that opens within the black rb
input.Open < window[1].Open && input.Open > window[1].Close &&
// and closes above the black rb
input.Close > window[1].Open &&
// inside the gap
input.Close < Math.Min(window[2].Close, window[2].Open) &&
// size of 2 rb near the same
Math.Abs(GetRealBody(window[1]) - GetRealBody(input)) < GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, window[1])
)
)
value = (int)GetCandleColor(window[1]);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_nearPeriodTotal += GetCandleRange(CandleSettingType.Near, window[1]) -
GetCandleRange(CandleSettingType.Near, window[_nearAveragePeriod + 1]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_nearPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,138 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Three Black Crows candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - three consecutive and declining black candlesticks
/// - each candle must have no or very short lower shadow
/// - each candle after the first must open within the prior candle's real body
/// - the first candle's close should be under the prior white candle's high
/// The meaning of "very short" is specified with SetCandleSettings
/// The returned value is negative (-1): three black crows is always bearish;
/// The user should consider that 3 black crows is significant when it appears after a mature advance or at high levels,
/// while this function does not consider it
/// </remarks>
public class ThreeBlackCrows : CandlestickPattern
{
private readonly int _shadowVeryShortAveragePeriod;
private decimal[] _shadowVeryShortPeriodTotal = new decimal[3];
/// <summary>
/// Initializes a new instance of the <see cref="ThreeBlackCrows"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public ThreeBlackCrows(string name)
: base(name, CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod + 3 + 1)
{
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="ThreeBlackCrows"/> class.
/// </summary>
public ThreeBlackCrows()
: this("THREEBLACKCROWS")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal[2] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[2]);
_shadowVeryShortPeriodTotal[1] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[1]);
_shadowVeryShortPeriodTotal[0] += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
return 0m;
}
decimal value;
if (
// white
GetCandleColor(window[3]) == CandleColor.White &&
// 1st black
GetCandleColor(window[2]) == CandleColor.Black &&
// very short lower shadow
GetLowerShadow(window[2]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[2], window[2]) &&
// 2nd black
GetCandleColor(window[1]) == CandleColor.Black &&
// very short lower shadow
GetLowerShadow(window[1]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[1], window[1]) &&
// 3rd black
GetCandleColor(input) == CandleColor.Black &&
// very short lower shadow
GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[0], input) &&
// 2nd black opens within 1st black's rb
window[1].Open < window[2].Open && window[1].Open > window[2].Close &&
// 3rd black opens within 2nd black's rb
input.Open < window[1].Open && input.Open > window[1].Close &&
// 1st black closes under prior candle's high
window[3].High > window[2].Close &&
// three declining
window[2].Close > window[1].Close &&
// three declining
window[1].Close > input.Close
)
value = -1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
for (var i = 2; i >= 0; i--)
{
_shadowVeryShortPeriodTotal[i] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[i]) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[i + _shadowVeryShortAveragePeriod]);
}
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_shadowVeryShortPeriodTotal = new decimal[3];
base.Reset();
}
}
}
@@ -0,0 +1,133 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Three Inside Up/Down candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long white(black) real body
/// - second candle: short real body totally engulfed by the first
/// - third candle: black(white) candle that closes lower(higher) than the first candle's open
/// The meaning of "short" and "long" is specified with SetCandleSettings
/// The returned value is positive (+1) for the three inside up or negative (-1) for the three inside down;
/// The user should consider that a three inside up is significant when it appears in a downtrend and a three inside
/// down is significant when it appears in an uptrend, while this function does not consider the trend
/// </remarks>
public class ThreeInside : CandlestickPattern
{
private readonly int _bodyLongAveragePeriod;
private readonly int _bodyShortAveragePeriod;
private decimal _bodyLongPeriodTotal;
private decimal _bodyShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="ThreeInside"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public ThreeInside(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod) + 2 + 1)
{
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="ThreeInside"/> class.
/// </summary>
public ThreeInside()
: this("THREEINSIDE")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod - 2 && Samples < Period - 2)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
}
if (Samples >= Period - _bodyShortAveragePeriod - 1 && Samples < Period - 1)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
return 0m;
}
decimal value;
if (
// 1st: long
GetRealBody(window[2]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[2]) &&
// 2nd: short
GetRealBody(window[1]) <= GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, window[1]) &&
// engulfed by 1st
Math.Max(window[1].Close, window[1].Open) < Math.Max(window[2].Close, window[2].Open) &&
Math.Min(window[1].Close, window[1].Open) > Math.Min(window[2].Close, window[2].Open) &&
// 3rd: opposite to 1st
((GetCandleColor(window[2]) == CandleColor.White && GetCandleColor(input) == CandleColor.Black && input.Close < window[2].Open) ||
// and closing out
(GetCandleColor(window[2]) == CandleColor.Black && GetCandleColor(input) == CandleColor.White && input.Close > window[2].Open)
)
)
value = -(int)GetCandleColor(window[2]);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[2]) -
GetCandleRange(CandleSettingType.BodyLong, window[2 + _bodyLongAveragePeriod]);
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, window[1]) -
GetCandleRange(CandleSettingType.BodyShort, window[1 + _bodyShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0;
_bodyShortPeriodTotal = 0;
base.Reset();
}
}
}
@@ -0,0 +1,147 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Three Line Strike candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - three white soldiers (three black crows): three white (black) candlesticks with consecutively higher (lower) closes,
/// each opening within or near the previous real body
/// - fourth candle: black (white) candle that opens above (below) prior candle's close and closes below (above)
/// the first candle's open
/// The meaning of "near" is specified with SetCandleSettings;
/// The returned value is positive (+1) when bullish or negative (-1) when bearish;
/// The user should consider that 3-line strike is significant when it appears in a trend in the same direction of
/// the first three candles, while this function does not consider it
/// </remarks>
public class ThreeLineStrike : CandlestickPattern
{
private readonly int _nearAveragePeriod;
private decimal[] _nearPeriodTotal = new decimal[4];
/// <summary>
/// Initializes a new instance of the <see cref="ThreeLineStrike"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public ThreeLineStrike(string name)
: base(name, CandleSettings.Get(CandleSettingType.Near).AveragePeriod + 3 + 1)
{
_nearAveragePeriod = CandleSettings.Get(CandleSettingType.Near).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="ThreeLineStrike"/> class.
/// </summary>
public ThreeLineStrike()
: this("THREELINESTRIKE")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _nearAveragePeriod)
{
_nearPeriodTotal[3] += GetCandleRange(CandleSettingType.Near, window[3]);
_nearPeriodTotal[2] += GetCandleRange(CandleSettingType.Near, window[2]);
}
return 0m;
}
decimal value;
if (
// three with same color
GetCandleColor(window[3]) == GetCandleColor(window[2]) &&
GetCandleColor(window[2]) == GetCandleColor(window[1]) &&
// 4th opposite color
(int)GetCandleColor(input) == -(int)GetCandleColor(window[1]) &&
// 2nd opens within/near 1st rb
window[2].Open >= Math.Min(window[3].Open, window[3].Close) - GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal[3], window[3]) &&
window[2].Open <= Math.Max(window[3].Open, window[3].Close) + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal[3], window[3]) &&
// 3rd opens within/near 2nd rb
window[1].Open >= Math.Min(window[2].Open, window[2].Close) - GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal[2], window[2]) &&
window[1].Open <= Math.Max(window[2].Open, window[2].Close) + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal[2], window[2]) &&
(
(
// if three white
GetCandleColor(window[1]) == CandleColor.White &&
// consecutive higher closes
window[1].Close > window[2].Close && window[2].Close > window[3].Close &&
// 4th opens above prior close
input.Open > window[1].Close &&
// 4th closes below 1st open
input.Close < window[3].Open
) ||
(
// if three black
GetCandleColor(window[1]) == CandleColor.Black &&
// consecutive lower closes
window[1].Close < window[2].Close && window[2].Close < window[3].Close &&
// 4th opens below prior close
input.Open < window[1].Close &&
// 4th closes above 1st open
input.Close > window[3].Open
)
)
)
value = (int)GetCandleColor(window[1]);
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
for (var i = 3; i >= 2; i--)
{
_nearPeriodTotal[i] += GetCandleRange(CandleSettingType.Near, window[i]) -
GetCandleRange(CandleSettingType.Near, window[i + _nearAveragePeriod]);
}
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_nearPeriodTotal = new decimal[4];
base.Reset();
}
}
}
@@ -0,0 +1,98 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Three Outside Up/Down candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first: black(white) real body
/// - second: white(black) real body that engulfs the prior real body
/// - third: candle that closes higher(lower) than the second candle
/// The returned value is positive (+1) for the three outside up or negative (-1) for the three outside down;
/// The user should consider that a three outside up must appear in a downtrend and three outside down must appear
/// in an uptrend, while this function does not consider it
/// </remarks>
public class ThreeOutside : CandlestickPattern
{
/// <summary>
/// Initializes a new instance of the <see cref="ThreeOutside"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public ThreeOutside(string name)
: base(name, 3)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ThreeOutside"/> class.
/// </summary>
public ThreeOutside()
: this("THREEOUTSIDE")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
return 0m;
}
decimal value;
if (
(
// white engulfs black
GetCandleColor(window[1]) == CandleColor.White && GetCandleColor(window[2]) == CandleColor.Black &&
window[1].Close > window[2].Open && window[1].Open < window[2].Close &&
// third candle higher
input.Close > window[1].Close
)
||
(
// black engulfs white
GetCandleColor(window[1]) == CandleColor.Black && GetCandleColor(window[2]) == CandleColor.White &&
window[1].Open > window[2].Close && window[1].Close < window[2].Open &&
// third candle lower
input.Close < window[1].Close
)
)
value = (int)GetCandleColor(window[1]);
else
value = 0;
return value;
}
}
}
@@ -0,0 +1,178 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Three Stars In The South candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long black candle with long lower shadow
/// - second candle: smaller black candle that opens higher than prior close but within prior candle's range
/// and trades lower than prior close but not lower than prior low and closes off of its low(it has a shadow)
/// - third candle: small black marubozu(or candle with very short shadows) engulfed by prior candle's range
/// The meanings of "long body", "short body", "very short shadow" are specified with SetCandleSettings;
/// The returned value is positive (+1): 3 stars in the south is always bullish;
/// The user should consider that 3 stars in the south is significant when it appears in downtrend, while this function
/// does not consider it
/// </remarks>
public class ThreeStarsInSouth : CandlestickPattern
{
private readonly int _bodyLongAveragePeriod;
private readonly int _shadowLongAveragePeriod;
private readonly int _shadowVeryShortAveragePeriod;
private readonly int _bodyShortAveragePeriod;
private decimal _bodyLongPeriodTotal;
private decimal _shadowLongPeriodTotal;
private decimal[] _shadowVeryShortPeriodTotal = new decimal[2];
private decimal _bodyShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="ThreeStarsInSouth"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public ThreeStarsInSouth(string name)
: base(name, Math.Max(Math.Max(CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod, CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod),
Math.Max(CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod)) + 2 + 1)
{
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_shadowLongAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowLong).AveragePeriod;
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="ThreeStarsInSouth"/> class.
/// </summary>
public ThreeStarsInSouth()
: this("THREESTARSINSOUTH")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[2]);
}
if (Samples >= Period - _shadowLongAveragePeriod)
{
_shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, window[2]);
}
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal[1] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[1]);
_shadowVeryShortPeriodTotal[0] += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
if (Samples >= Period - _bodyShortAveragePeriod)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
return 0m;
}
decimal value;
if (
// 1st black
GetCandleColor(window[2]) == CandleColor.Black &&
// 2nd black
GetCandleColor(window[1]) == CandleColor.Black &&
// 3rd black
GetCandleColor(input) == CandleColor.Black &&
// 1st: long
GetRealBody(window[2]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[2]) &&
// with long lower shadow
GetLowerShadow(window[2]) > GetCandleAverage(CandleSettingType.ShadowLong, _shadowLongPeriodTotal, window[2]) &&
// 2nd: smaller candle
GetRealBody(window[1]) < GetRealBody(window[2]) &&
// that opens higher but within 1st range
window[1].Open > window[2].Close && window[1].Open <= window[2].High &&
// and trades lower than 1st close
window[1].Low < window[2].Close &&
// but not lower than 1st low
window[1].Low >= window[2].Low &&
// and has a lower shadow
GetLowerShadow(window[1]) > GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[1], window[1]) &&
// 3rd: small marubozu
GetRealBody(input) < GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[0], input) &&
GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[0], input) &&
// engulfed by prior candle's range
input.Low > window[1].Low && input.High < window[1].High
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[2]) -
GetCandleRange(CandleSettingType.BodyLong, window[2 + _bodyLongAveragePeriod]);
_shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, window[2]) -
GetCandleRange(CandleSettingType.ShadowLong, window[2 + _shadowLongAveragePeriod]);
for (var i = 1; i >= 0; i--)
{
_shadowVeryShortPeriodTotal[i] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[i]) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[i + _shadowVeryShortAveragePeriod]);
}
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0;
_shadowLongPeriodTotal = 0;
_shadowVeryShortPeriodTotal = new decimal[2];
_bodyShortPeriodTotal = 0;
base.Reset();
}
}
}
@@ -0,0 +1,189 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Three Advancing White Soldiers candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - three white candlesticks with consecutively higher closes
/// - Greg Morris wants them to be long, Steve Nison doesn't; anyway they should not be short
/// - each candle opens within or near the previous white real body
/// - each candle must have no or very short upper shadow
/// - to differentiate this pattern from advance block, each candle must not be far shorter than the prior candle
/// The meanings of "not short", "very short shadow", "far" and "near" are specified with SetCandleSettings;
/// here the 3 candles must be not short, if you want them to be long use SetCandleSettings on BodyShort;
/// The returned value is positive (+1): advancing 3 white soldiers is always bullish;
/// The user should consider that 3 white soldiers is significant when it appears in downtrend, while this function
/// does not consider it
/// </remarks>
public class ThreeWhiteSoldiers : CandlestickPattern
{
private readonly int _shadowVeryShortAveragePeriod;
private readonly int _nearAveragePeriod;
private readonly int _farAveragePeriod;
private readonly int _bodyShortAveragePeriod;
private decimal[] _shadowVeryShortPeriodTotal = new decimal[3];
private decimal[] _nearPeriodTotal = new decimal[3];
private decimal[] _farPeriodTotal = new decimal[3];
private decimal _bodyShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="ThreeWhiteSoldiers"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public ThreeWhiteSoldiers(string name)
: base(name, Math.Max(Math.Max(CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod),
Math.Max(CandleSettings.Get(CandleSettingType.Far).AveragePeriod, CandleSettings.Get(CandleSettingType.Near).AveragePeriod)) + 2 + 1)
{
_shadowVeryShortAveragePeriod = CandleSettings.Get(CandleSettingType.ShadowVeryShort).AveragePeriod;
_nearAveragePeriod = CandleSettings.Get(CandleSettingType.Near).AveragePeriod;
_farAveragePeriod = CandleSettings.Get(CandleSettingType.Far).AveragePeriod;
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="ThreeWhiteSoldiers"/> class.
/// </summary>
public ThreeWhiteSoldiers()
: this("THREEWHITESOLDIERS")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _shadowVeryShortAveragePeriod)
{
_shadowVeryShortPeriodTotal[2] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[2]);
_shadowVeryShortPeriodTotal[1] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[1]);
_shadowVeryShortPeriodTotal[0] += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
}
if (Samples >= Period - _nearAveragePeriod)
{
_nearPeriodTotal[2] += GetCandleRange(CandleSettingType.Near, window[2]);
_nearPeriodTotal[1] += GetCandleRange(CandleSettingType.Near, window[1]);
}
if (Samples >= Period - _farAveragePeriod)
{
_farPeriodTotal[2] += GetCandleRange(CandleSettingType.Far, window[2]);
_farPeriodTotal[1] += GetCandleRange(CandleSettingType.Far, window[1]);
}
if (Samples >= Period - _bodyShortAveragePeriod)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
return 0m;
}
decimal value;
if (
// 1st white
GetCandleColor(window[2]) == CandleColor.White &&
// very short upper shadow
GetUpperShadow(window[2]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[2], window[2]) &&
// 2nd white
GetCandleColor(window[1]) == CandleColor.White &&
// very short upper shadow
GetUpperShadow(window[1]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[1], window[1]) &&
// 3rd white
GetCandleColor(input) == CandleColor.White &&
// very short upper shadow
GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[0], input) &&
// consecutive higher closes
input.Close > window[1].Close && window[1].Close > window[2].Close &&
// 2nd opens within/near 1st real body
window[1].Open > window[2].Open &&
window[1].Open <= window[2].Close + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal[2], window[2]) &&
// 3rd opens within/near 2nd real body
input.Open > window[1].Open &&
input.Open <= window[1].Close + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal[1], window[1]) &&
// 2nd not far shorter than 1st
GetRealBody(window[1]) > GetRealBody(window[2]) - GetCandleAverage(CandleSettingType.Far, _farPeriodTotal[2], window[2]) &&
// 3rd not far shorter than 2nd
GetRealBody(input) > GetRealBody(window[1]) - GetCandleAverage(CandleSettingType.Far, _farPeriodTotal[1], window[1]) &&
// not short real body
GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input)
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
for (var i = 2; i >= 0; i--)
{
_shadowVeryShortPeriodTotal[i] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[i]) -
GetCandleRange(CandleSettingType.ShadowVeryShort, window[i + _shadowVeryShortAveragePeriod]);
}
for (var i = 2; i >= 1; i--)
{
_farPeriodTotal[i] += GetCandleRange(CandleSettingType.Far, window[i]) -
GetCandleRange(CandleSettingType.Far, window[i + _farAveragePeriod]);
}
for (var i = 2; i >= 1; i--)
{
_nearPeriodTotal[i] += GetCandleRange(CandleSettingType.Near, window[i]) -
GetCandleRange(CandleSettingType.Near, window[i + _nearAveragePeriod]);
}
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_shadowVeryShortPeriodTotal = new decimal[3];
_nearPeriodTotal = new decimal[3];
_farPeriodTotal = new decimal[3];
_bodyShortPeriodTotal = 0;
base.Reset();
}
}
}
+134
View File
@@ -0,0 +1,134 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Thrusting candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long black candle
/// - second candle: white candle with open below previous day low and close into previous day body under the midpoint;
/// to differentiate it from in-neck the close should not be equal to the black candle's close
/// The meaning of "equal" is specified with SetCandleSettings
/// The returned value is negative(-1): thrusting pattern is always bearish
/// The user should consider that the thrusting pattern is significant when it appears in a downtrend and it could be
/// even bullish "when coming in an uptrend or occurring twice within several days" (Steve Nison says), while this
/// function does not consider the trend
/// </remarks>
public class Thrusting : CandlestickPattern
{
private readonly int _equalAveragePeriod;
private readonly int _bodyLongAveragePeriod;
private decimal _equalPeriodTotal;
private decimal _bodyLongPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="Thrusting"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public Thrusting(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.Equal).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod) + 1 + 1)
{
_equalAveragePeriod = CandleSettings.Get(CandleSettingType.Equal).AveragePeriod;
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="Thrusting"/> class.
/// </summary>
public Thrusting()
: this("THRUSTING")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _equalAveragePeriod)
{
_equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]);
}
if (Samples >= Period - _bodyLongAveragePeriod)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[1]);
}
return 0m;
}
decimal value;
if (
// 1st: black
GetCandleColor(window[1]) == CandleColor.Black &&
// long
GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[1]) &&
// 2nd: white
GetCandleColor(input) == CandleColor.White &&
// open below prior low
input.Open < window[1].Low &&
// close into prior body
input.Close > window[1].Close + GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1]) &&
// under the midpoint
input.Close <= window[1].Close + GetRealBody(window[1]) * 0.5m
)
value = -1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]) -
GetCandleRange(CandleSettingType.Equal, window[_equalAveragePeriod + 1]);
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[1]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 1]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_equalPeriodTotal = 0m;
_bodyLongPeriodTotal = 0m;
base.Reset();
}
}
}
+127
View File
@@ -0,0 +1,127 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Tristar candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - 3 consecutive doji days
/// - the second doji is a star
/// The meaning of "doji" is specified with SetCandleSettings
/// The returned value is positive(+1) when bullish or negative(-1) when bearish
/// </remarks>
public class Tristar : CandlestickPattern
{
private readonly int _bodyDojiAveragePeriod;
private decimal _bodyDojiPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="Tristar"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public Tristar(string name)
: base(name, CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod + 2 + 1)
{
_bodyDojiAveragePeriod = CandleSettings.Get(CandleSettingType.BodyDoji).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="Tristar"/> class.
/// </summary>
public Tristar()
: this("TRISTAR")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyDojiAveragePeriod - 2 && Samples < Period - 2)
{
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input);
}
return 0m;
}
decimal value;
if (
// 1st: doji
GetRealBody(window[2]) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, window[2]) &&
// 2nd: doji
GetRealBody(window[1]) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, window[2]) &&
// 3rd: doji
GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, window[2]))
{
value = 0;
if (
// 2nd gaps up
GetRealBodyGapUp(window[1], window[2]) &&
// 3rd is not higher than 2nd
Math.Max(input.Open, input.Close) < Math.Max(window[1].Open, window[1].Close)
)
value = -1m;
if (
// 2nd gaps down
GetRealBodyGapDown(window[1], window[2]) &&
// 3rd is not lower than 2nd
Math.Min(input.Open, input.Close) > Math.Min(window[1].Open, window[1].Close)
)
value = 1m;
}
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, window[2]) -
GetCandleRange(CandleSettingType.BodyDoji, window[_bodyDojiAveragePeriod + 2]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyDojiPeriodTotal = 0m;
base.Reset();
}
}
}
+122
View File
@@ -0,0 +1,122 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Two Crows candlestick pattern indicator
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long white candle
/// - second candle: black real body
/// - gap between the first and the second candle's real bodies
/// - third candle: black candle that opens within the second real body and closes within the first real body
/// The meaning of "long" is specified with SetCandleSettings
/// The returned value is negative (-1): two crows is always bearish;
/// The user should consider that two crows is significant when it appears in an uptrend, while this function
/// does not consider the trend.
/// </remarks>
public class TwoCrows : CandlestickPattern
{
private readonly int _bodyLongAveragePeriod;
private decimal _bodyLongPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="TwoCrows"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public TwoCrows(string name)
: base(name, CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod + 2 + 1)
{
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="TwoCrows"/> class.
/// </summary>
public TwoCrows()
: this("TWOCROWS")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod - 2 && Samples < Period - 2)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
}
return 0m;
}
decimal value;
if (
// 1st: white
GetCandleColor(window[2]) == CandleColor.White &&
// long
GetRealBody(window[2]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[2]) &&
// 2nd: black
GetCandleColor(window[1]) == CandleColor.Black &&
// gapping up
GetRealBodyGapUp(window[1], window[2]) &&
// 3rd: black
GetCandleColor(input) == CandleColor.Black &&
// opening within 2nd rb
input.Open < window[1].Open && input.Open > window[1].Close &&
// closing within 1st rb
input.Close > window[2].Open && input.Close < window[2].Close
)
value = -1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[2]) -
GetCandleRange(CandleSettingType.BodyLong, window[2 + _bodyLongAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0m;
base.Reset();
}
}
}
@@ -0,0 +1,137 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Unique Three River candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: long black candle
/// - second candle: black harami candle with a lower low than the first candle's low
/// - third candle: small white candle with open not lower than the second candle's low, better if its open and
/// close are under the second candle's close
/// The meaning of "short" and "long" is specified with SetCandleSettings
/// The returned value is positive(+1): unique 3 river is always bullish and should appear in a downtrend
/// to be significant, while this function does not consider the trend
/// </remarks>
public class UniqueThreeRiver : CandlestickPattern
{
private readonly int _bodyLongAveragePeriod;
private readonly int _bodyShortAveragePeriod;
private decimal _bodyLongPeriodTotal;
private decimal _bodyShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="UniqueThreeRiver"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public UniqueThreeRiver(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod) + 2 + 1)
{
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="UniqueThreeRiver"/> class.
/// </summary>
public UniqueThreeRiver()
: this("UNIQUETHREERIVER")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod - 2 && Samples < Period - 2)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
}
if (Samples >= Period - _bodyShortAveragePeriod)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
return 0m;
}
decimal value;
if (
// 1st: long
GetRealBody(window[2]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[2]) &&
// black
GetCandleColor(window[2]) == CandleColor.Black &&
// 2nd: black
GetCandleColor(window[1]) == CandleColor.Black &&
// harami
window[1].Close > window[2].Close && window[1].Open <= window[2].Open &&
// lower low
window[1].Low < window[2].Low &&
// 3rd: short
GetRealBody(input) < GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
// white
GetCandleColor(input) == CandleColor.White &&
// open not lower
input.Open > window[1].Low
)
value = 1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[2]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 2]);
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0;
_bodyShortPeriodTotal = 0;
base.Reset();
}
}
}
@@ -0,0 +1,108 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Up/Down Gap Three Methods candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: white (black) candle
/// - second candle: white(black) candle
/// - upside(downside) gap between the first and the second real bodies
/// - third candle: black(white) candle that opens within the second real body and closes within the first real body
/// The returned value is positive(+1) when bullish or negative(-1) when bearish;
/// The user should consider that up/downside gap 3 methods is significant when it appears in a trend, while this
/// function does not consider it
/// </remarks>
public class UpDownGapThreeMethods : CandlestickPattern
{
/// <summary>
/// Initializes a new instance of the <see cref="UpDownGapThreeMethods"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public UpDownGapThreeMethods(string name)
: base(name, 2 + 1)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="UpDownGapThreeMethods"/> class.
/// </summary>
public UpDownGapThreeMethods()
: this("UPDOWNGAPTHREEMETHODS")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
return 0m;
}
decimal value;
if (
// 1st and 2nd of same color
GetCandleColor(window[2]) == GetCandleColor(window[1]) &&
// 3rd opposite color
(int)GetCandleColor(window[1]) == -(int)GetCandleColor(input) &&
// 3rd opens within 2nd rb
input.Open < Math.Max(window[1].Close, window[1].Open) &&
input.Open > Math.Min(window[1].Close, window[1].Open) &&
// 3rd closes within 1st rb
input.Close < Math.Max(window[2].Close, window[2].Open) &&
input.Close > Math.Min(window[2].Close, window[2].Open) &&
((
// when 1st is white
GetCandleColor(window[2]) == CandleColor.White &&
// upside gap
GetRealBodyGapUp(window[1], window[2])
) ||
(
// when 1st is black
GetCandleColor(window[2]) == CandleColor.Black &&
// downside gap
GetRealBodyGapDown(window[1], window[2])
)
)
)
value = (int)GetCandleColor(window[2]);
else
value = 0;
return value;
}
}
}
@@ -0,0 +1,139 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators.CandlestickPatterns
{
/// <summary>
/// Upside Gap Two Crows candlestick pattern
/// </summary>
/// <remarks>
/// Must have:
/// - first candle: white candle, usually long
/// - second candle: small black real body
/// - gap between the first and the second candle's real bodies
/// - third candle: black candle with a real body that engulfs the preceding candle
/// and closes above the white candle's close
/// The meaning of "short" and "long" is specified with SetCandleSettings
/// The returned value is negative(-1): upside gap two crows is always bearish;
/// The user should consider that an upside gap two crows is significant when it appears in an uptrend,
/// while this function does not consider the trend
/// </remarks>
public class UpsideGapTwoCrows : CandlestickPattern
{
private readonly int _bodyLongAveragePeriod;
private readonly int _bodyShortAveragePeriod;
private decimal _bodyLongPeriodTotal;
private decimal _bodyShortPeriodTotal;
/// <summary>
/// Initializes a new instance of the <see cref="UpsideGapTwoCrows"/> class using the specified name.
/// </summary>
/// <param name="name">The name of this indicator</param>
public UpsideGapTwoCrows(string name)
: base(name, Math.Max(CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod, CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod) + 2 + 1)
{
_bodyLongAveragePeriod = CandleSettings.Get(CandleSettingType.BodyLong).AveragePeriod;
_bodyShortAveragePeriod = CandleSettings.Get(CandleSettingType.BodyShort).AveragePeriod;
}
/// <summary>
/// Initializes a new instance of the <see cref="UpsideGapTwoCrows"/> class.
/// </summary>
public UpsideGapTwoCrows()
: this("UPSIDEGAPTWOCROWS")
{
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Samples >= Period; }
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IBaseDataBar> window, IBaseDataBar input)
{
if (!IsReady)
{
if (Samples >= Period - _bodyLongAveragePeriod - 2 && Samples < Period - 2)
{
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
}
if (Samples >= Period - _bodyShortAveragePeriod - 1 && Samples < Period - 1)
{
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
}
return 0m;
}
decimal value;
if (
// 1st: white
GetCandleColor(window[2]) == CandleColor.White &&
// long
GetRealBody(window[2]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[2]) &&
// 2nd: black
GetCandleColor(window[1]) == CandleColor.Black &&
// short
GetRealBody(window[1]) <= GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, window[1]) &&
// gapping up
GetRealBodyGapUp(window[1], window[2]) &&
// 3rd: black
GetCandleColor(input) == CandleColor.Black &&
// 3rd: engulfing prior rb
input.Open > window[1].Open && input.Close < window[1].Close &&
// closing above 1st
input.Close > window[2].Close
)
value = -1m;
else
value = 0m;
// add the current range and subtract the first range: this is done after the pattern recognition
// when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
_bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[2]) -
GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 2]);
_bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, window[1]) -
GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod + 1]);
return value;
}
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_bodyLongPeriodTotal = 0;
_bodyShortPeriodTotal = 0;
base.Reset();
}
}
}