Saturday 15 August 2020

Candlestick Pattern Scanner Functions

Since my last currency strength candlestick chart post it seemed to make sense to be able to scan said charts for signals, so below is the code for two Octave functions which act as candlestick pattern scanners. The code is fully vectorised and self-contained, and on my machine they can scan more than 300,000 OHLC bars for 27/29 separate patterns in less than 0.5 seconds. Both functions have a self-explanatory help and within the body of the code there are ample comments which describe the patterns. Enjoy!

Bullish Reversal Indicator

## Copyright (C) 2020 dekalog
## 
## This program is free software: you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
## 
## This program is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see
## .

## -*- texinfo -*- 
## @deftypefn {} {@var{bullish_signal_matrix} =} candle_bullish_reversal (@var{high}, @var{low}, @var{close}, @var{open}, @var{downtrend}, @var{avge_hi_lo_range})
##
## The HIGH, LOW, CLOSE and OPEN should be vectors of equal length, and are required.
##
## Internally the DOWNTREND is determined as a bar's CLOSE being lower than the CLOSE
## of the bar 5 bars previously. This can be over-ruled by an optional, user supplied
## vector DOWNTREND of zeros and ones, where one(s) represent a bar in a DOWNTREND.
## If a DOWNTREND vector consists solely of ones, this effectively turns off the
## discriminative ability of the DOWNTREND condition as all bars will be considered
## to be DOWNTREND bars. If the DOWNTREND vector consists solely of zeros, no bar
## will be classified as being in a DOWNTREND and those candle patterns that require a 
## DOWNTREND as a condition will not be indicated.
##
## The AVGE_HI_LO_RANGE is calculated as a rolling 5 bar simple moving average of
## the HI-LO range of bars. A bar is considered a "long line" if its HI-LO range
## is greater than the AVGE_HI_LO_RANGE. This can also be over-ruled, as above, by
## an optional, user supplied vector AVGE_HI_LO_RANGE, which consists of zeros and
## ones, with ones representing "long line" bars. An AVGE_HI_LO_RANGE vector of all
## ones or zeros will have a similar effect as described for the DOWNTREND vector.
##
## The candlestick pattern descriptions are predominantly taken from
##
## https://www.candlescanner.com
##
## and the bullish only patterns implemented are:
##
## Bullish Reversal High Reliability
##
##     01 - Bullish Abandoned Baby
##
##     02 - Concealing Baby Swallow
##
##     03 - Kicking
##
##     04 - Morning Doji Star
##
##     05 - Morning Star
##
##     06 - Piercing Line
##
##     07 - Three Inside Up
##
##     08 - Three Outside Up
##
##     09 - Three White Soldiers
##
## Bullish Reversal Moderate Reliability
##
##     10 - Breakaway
##
##     11 - Counter Attack
##
##     12 - Doji Star
##
##     13 - Dragonfly Doji
##
##     14 - Engulfing
##
##     15 - Gravestone Doji
##
##     16 - Harami Cross
##
##     17 - Homing Pigeon
##
##     18 - Ladder Bottom
##
##     19 - Long Legged Doji
##
##     20 - Matching Low
##
##     21 - Meeting Lines
##
##     22 - Stick Sandwich
##
##     23 - Three Stars in the South
##
##     24 - Tri Star
##
##     25 - Unique Three River Bottom
##
## Bullish Reversal Low Reliability
##
##     26 - Belt Hold
##
##     27 - Hammer
##
##     28 - Harami
##
##     29 - Inverted Hammer
##
## The output BULLISH_SIGNAL_MATRIX has a row length the same as the OHLC
## input vectors and 29 columns. The matrix is a zero filled matrix with the
## value 1 when a candle pattern is indicated. The row ix of the value is the
## row ix of the last candle in the pattern. The column ix corresponds to the
## pattern index given above.
##
## @seealso{candle_bearish_reversal}
## @end deftypefn

## Author: dekalog 
## Created: 2020-08-10

function bullish_signal_matrix = candle_bullish_reversal ( varargin )
 
if ( nargin < 4 || nargin > 6 )
  print_usage () ;
elseif ( nargin == 4 )
  high = varargin{1} ; low = varargin{2} ; close = varargin{3} ; open = varargin{4} ;
  downtrend = close < shift( close , 5 ) ;
  avge_hi_lo_range = filter( [0.2 ; 0.2 ; 0.2 ; 0.2 ; 0.2 ] , 1 , high .- low ) ; ## 5 bar simple moving average
elseif ( nargin == 5 )
  high = varargin{1} ; low = varargin{2} ; close = varargin{3} ; open = varargin{4} ;
  downtrend = varargin{5} ;
  avge_hi_lo_range = filter( [0.2 ; 0.2 ; 0.2 ; 0.2 ; 0.2 ] , 1 , high .- low ) ; ## 5 bar simple moving average
elseif ( nargin == 6 )
  high = varargin{1} ; low = varargin{2} ; close = varargin{3} ; open = varargin{4} ;
  downtrend = varargin{5} ; avge_hi_lo_range = varargin{6} ;
endif
 
bullish_signal_matrix = zeros( size( close , 1 ) , 29 ) ;

## pre-compute some basic vectors for re-use below, trading memory use for
## speed of execution
downtrend_1 = shift( downtrend , 1 ) ;
downtrend_2 = shift( downtrend , 2 ) ;
downtrend_3 = shift( downtrend , 3 ) ;
long_line = ( high .- low ) > shift( avge_hi_lo_range , 1 ) ;
long_line_1 = shift( long_line , 1 ) ;
long_line_2 = shift( long_line , 2 ) ;
long_line_3 = shift( long_line , 3 ) ;
long_line_4 = shift( long_line , 4 ) ;
open_1 = shift( open , 1 ) ;
open_2 = shift( open , 2 ) ;
open_3 = shift( open , 3 ) ;
open_4 = shift( open , 4 ) ;
open_5 = shift( open , 5 ) ;
high_1 = shift( high , 1 ) ;
high_3 = shift( high , 3 ) ;
low_1 = shift( low ,1 ) ;
low_2 = shift( low ,2 ) ;
low_3 = shift( low , 3 ) ;
close_1 = shift( close , 1 ) ;
close_2 = shift( close , 2 ) ;
close_3 = shift( close , 3 ) ;
close_4 = shift( close , 4 ) ;
black_body = close < open ;
black_body_1 = shift( black_body , 1 ) ;
black_body_2 = shift( black_body , 2 ) ;
black_body_3 = shift( black_body , 3 ) ;
black_body_4 = shift( black_body , 4 ) ;
white_body = close > open ;
white_body_1 = shift( white_body , 1 ) ;
white_body_2 = shift( white_body , 2 ) ;
doji = ( close == open ) ;
doji_1 = shift( doji , 1 ) ;
doji_2 = shift( doji , 2 ) ;
body_high = max( [ open , close ] , [] , 2 ) ;
body_high_1 = shift( body_high , 1 ) ;
body_high_2 = shift( body_high , 2 ) ;
body_low = min( [ open , close ] , [] , 2 ) ;
body_low_1 = shift( body_low , 1 ) ;
body_low_2 = shift( body_low , 2 ) ;
body_range = body_high .- body_low ;
body_range_1 = shift( body_range , 1 ) ;
body_range_2 = shift( body_range , 2 ) ;
body_midpoint = ( body_high .+ body_low ) ./ 2 ;
body_midpoint_1 = shift( body_midpoint , 1 ) ;
body_midpoint_2 = shift( body_midpoint , 2 ) ;
wick_gap_up = ( low > high_1 ) ;
wick_gap_down = ( high < low_1 ) ;
wick_gap_down_1 = shift( wick_gap_down , 1 ) ;
black_marubozu = ( high == open ) .* ( low == close ) ;
black_marubozu_1 = shift( black_marubozu , 1 ) ;
black_marubozu_2 = shift( black_marubozu , 2 ) ;
black_marubozu_3 = shift( black_marubozu , 3 ) ;
white_marubozu = ( high == close ) .* ( low == open ) ;

## 01 - Bullish Abandoned Baby
## First candle
##     a candle in a downtrend
##     black body
## Second candle
##     a doji candle
##     the high price below the prior low price
## Third candle
##     white body
##     the low price above the prior high price
bullish_signal_matrix(:,1) = downtrend_2 .* black_body_2 .* ...
                              doji_1 .* wick_gap_down_1 .* ...
                              white_body .* wick_gap_up ; 
## 02 - Concealing Baby Swallow
## First candle
##     a Black Marubozu candle in a downtrend
## Second candle
##     a Black Marubozu candle
##     candle opens within the prior candle's body
##     candle closes below the prior closing price
## Third candle
##     a High Wave basic candle with no lower shadow
##     candle opens below the prior closing price
##     upper shadow enters the prior candle's body
## Fourth candle
##     black body
##     candle’s body engulfs the prior candle’s body including the shadows
bullish_signal_matrix(:,2) = downtrend_3 .* black_marubozu_3 .* ...
                              black_marubozu_2 .* (open_2 < high_3) .* (open_2 > low_3) .* (close_2 < close_3) .* ...
                              (high_1 .- body_high_1 >= 3.*body_range_1) .* (low_1 == body_low_1) .* (open_1 < close_2) .* (high_1 > body_low_2) .* ...
                              black_body .* (open > high_1) .* (close < low_1) ;
## 03 - Kicking
## First candle
##     a Black Marubozu
##     appears on as a long line
## Second candle
##     a White Marubozu
##     price gaps upward
##     appears on as a long line
bullish_signal_matrix(:,3) = black_marubozu_1 .* long_line_1 .* ...
                              white_marubozu .* (low > high_1) .* long_line ;
## 04 - Morning Doji Star
## First candle
##     a candle in a downtrend
##     black body
## Second candle
##     a doji candle
##     a doji body below the previous candle body
##     the high price above the previous candle low price
## Third candle
##     white body
##     candle body above the previous candle body
##     the closing price above the midpoint of the first candle body
bullish_signal_matrix(:,4) = downtrend_2 .* black_body_2 .* ...
                              doji_1 .* (open_1 < body_low_2) .* (high_1 > low_2) .* ...
                              white_body .* (body_low > body_high_1) .* (close > body_midpoint_2) ;
## 05 - Morning Star
## First candle
##     a candle in a downtrend
##     black body
## Second candle
##     white or black body
##     the candle body is located below the prior body
## Third candle
##     white body
##     the candle body is located above the prior body
##     the candle closes at least halfway up the body of the first line
bullish_signal_matrix(:,5) = downtrend_2 .* black_body_2 .* ...
                              (body_high_1 < body_low_2) .* ...
                              white_body .* (body_low > body_high_1) .* (close >= body_midpoint_2) ;
## 06 - Piercing Line
## First candle
##     a candle in a downtrend
##     black body
## Second candle
##     white body
##     the opening below or equal of the prior low
##     the closing above the midpoint of the prior candle's body
##     the closing below the previous opening
bullish_signal_matrix(:,6) = downtrend_1 .* black_body_1 .* ...
                              white_body .* (open <= low_1) .* (close > body_midpoint_1) .* (close < open_1) ;
## 07 - Three Inside Up
## First candle
##     a candle in a downtrend
##     black body
## Second candle
##     white body
##     the candle body is engulfed by the prior candle body
## Third candle
##     the closing price is above the previous closing price
bullish_signal_matrix(:,7) = downtrend_2 .* black_body_2 .* ...
                              white_body_1 .* (body_high_1 < body_high_2) .* (body_low_1 > body_low_2) .* ...
                              (close > close_1) ;
## 08 - Three Outside Up
## First candle
##     a candle in a downtrend
##     black body
## Second candle
##     white body
##     candle’s body engulfs the prior (black) candle’s body
## Third candle
##     closing price above the previous closing price
##     white body
bullish_signal_matrix(:,8) = downtrend_2 .* black_body_2 .* ...
                              white_body_1 .* (body_high_1 > body_high_2) .* (body_low_1 < body_low_2) .* ...
                              (close > close_1) .* white_body ;
## 09 - Three White Soldiers
## First candle
##     a candle in a downtrend
##     white body
## Second candle
##     white body
##     the opening price within the previous body
##     the closing price above the previous closing price
## Third candle
##     white body
##     the opening price within the previous body
##     the closing price above the previous closing price
bullish_signal_matrix(:,9) = downtrend_2 .* white_body_2 .* ...
                              white_body_1 .* (open_1 < body_high_2) .* (open_1 > body_low_2) .* (close_1 > close_2) .* ...
                              white_body .* (open < body_high_1) .* (open > body_low_1) .* (close > close_1) ; 
## 10 - Breakaway
## First candle
##     a tall black candle
## Second candle
##     a black candle
##     candle opens below the previous closing price (downward price gap, shadows can overlap)
## Third candle
##     a white or black candle
##     candle opens below the previous opening price
## Fourth candle
##     a black candle
##     candle closes below the previous closing price
## Fifth candle
##     a tall white candle
##     candle opens above the previous closing price
##     candle closes above the second line's opening price and below the first line's opening price
bullish_signal_matrix(:,10) = black_body_4 .* long_line_4 .*...
                               black_body_3 .* (open_3 < close_4) .* ...
                               (open_2 < open_3) .* ...
                               black_body_1 .* (close_1 < close_2) .* ...
                               white_body .* long_line .* (open > close_1) .* (close > open_3) .* (close < open_4) ; 
## 11 - Counter Attack
## First candle
##     a candle in a downtrend
##     black body
## Second candle
##     white body
##     the opening price is lower than the previous closing price
##     the closing price is at or higher than the previous closing price
bullish_signal_matrix(:,11) = downtrend_1 .* black_body_1 .* ...
                               white_body .* (open < close_1) .* (close >= close_1) ;
## 12 - Doji Star
## First candle
##     a candle in a downtrend
##     black body
## Second candle
##     a doji candle
##     a body below the first candle's body
bullish_signal_matrix(:,12) = downtrend_1 .* black_body_1 .* ...
                               doji .* (open < body_low_1) ; 
## 13 - Dragonfly Doji
##     Opening, closing and maximum prices are the same or very similar
##     Long lower shadow
##     appears on as a long line
bullish_signal_matrix(:,13) = (open == close) .* (close == high) .* long_line ;

## 14 - Engulfing
## First candle
##     a candle in a downtrend
##     black body
## Second candle
##     white body
##     candle's body engulfs the prior (black) candle's body
bullish_signal_matrix(:,14) = downtrend_1 .* black_body_1 .* ...
                               white_body .* (body_high > body_high_1) .* (body_low < body_low_1) ; 
## 15 - Gravestone Doji
##     Opening, closing and minimum prices are the same or very similar
##     Long upper shadow
##     appears on as a long line
bullish_signal_matrix(:,15) = (open == close) .* (close == low) .* long_line ; 

## 16 - Harami Cross
## First candle
##     a candle in a downtrend
##     black body
##     appears on as a long line
## Second candle
##     a doji candle with two shadows
##     the candle (including shadows) is engulfed by the previous candle's body
bullish_signal_matrix(:,16) = downtrend_1 .* black_body_1 .* long_line_1 .* ...
                               doji .* (high > close) .* (low < close) .* (high < body_high_1) .* (low > body_low_1) ;
## 17 - Homing Pigeon
## First candle
##     a candle in a downtrend
##     black body
## Second candle
##     black body
##     candle’s body engulfed by the prior candle’s body
bullish_signal_matrix(:,17) = downtrend_1 .* black_body_1 .* ...
                               black_body .* (body_high < body_high_1) .* (body_low > body_low_1) ;
## 18 - Ladder Bottom
## First candle
##     a tall black candle
## Second candle
##     a tall black candle
##     candle opens below the previous opening price
## Third candle
##     a tall black candle
##     candle opens below the previous opening price
## Fourth candle
##     a black candle
##     candle closes below the previous closing price
##     candle has a long upper shadow
## Fifth candle
##     a tall white candle
##     candle opens above the previous opening price
##     candle closes at or above the third line's opening price and below the first line's opening price
bullish_signal_matrix(:,18) = black_body_4 .* long_line_4 .* ...
                               black_body_3 .* (open_3 < open_4) .* long_line_3 .* ...
                               black_body_2 .* (open_2 < open_3) .* long_line_2 .* ...
                               black_body_1 .* (close_1 < close_2) .* ((high_1 .- body_high_1) > body_range_1) .* ...
                               white_body .* (open > open_1) .* (close >= open_2) .* (close < open_5) ; 
## 19 - Long Legged Doji
##     a doji candle
##     opening and closing prices are the same or similar
##     upper and lower shadow are very long
##     body is located in the middle of the candle or nearly mid-range
##     appears on as a long line
bullish_signal_matrix(:,19) = doji .* ((high .- close) > 0) .* ((close .- low) > 0) .* long_line ;

## 20 - Matching Low
## First candle
##     a candle in a downtrend
##     black body
##     no lower shadow
##     appears as a long line
## Second candle
##     black body
##     the opening price is below the previous opening price
##     the closing price is at the level of the previous closing price
##     no lower shadow
bullish_signal_matrix(:,20) = downtrend_1 .* black_body_1 .* (close_1 == low_1) .* long_line_1 .* ...
                               black_body .* (open < open_1) .* (close == close_1) .* (close == low) ;
## 21 - Meeting Lines
## First candle
##     a candle in a downtrend
##     black body
##     appears as a long line
## Second candle
##     white body
##     the closing price is equal to the previous closing price
bullish_signal_matrix(:,21) = downtrend_1 .* black_body_1 .* long_line_1 .* ...
                               white_body .* (close == close_1) ;
## 22 - Stick Sandwich
## First candle
##     a candle in a downtrend
##     black body
## Second candle
##     white body
##     the opening price is higher than the previous closing price
##     the closing price is higher than the previous opening price
## Third candle
##     black_body
##     the opening price is higher than the previous closing price
##     the closing price is equal to or higher than first line close
bullish_signal_matrix(:,22) = downtrend_2 .* black_body_2 .* ...
                               white_body_1 .* (open_1 > close_2) .* (close_1 > open_2) .* ...
                               black_body .* (open > close_1) .* (close >= close_2) ;
## 23 - Three Stars in the South
## First candle
##     a candle in a downtrend
##     black body
##     long lower shadow
## Second candle
##     black body
##     the opening below the prior opening
##     the closing below or at the prior closing
##     the low above the prior low
## Third candle
##     a marubozu candle with black body
##     appears as a short line
##     a candle is located within the prior candle
bullish_signal_matrix(:,23) = downtrend_2 .* black_body_2 .* ((body_low_2 .- low_2) > body_range_2) .* ...
                               black_body_1 .* (open_1 < open_2) .* (close_1 <= close_2) .* (low_1 > low_2) .* ...
                               black_marubozu .* (high < high_1) .* (low > low_1) ;
## 24 - Tri Star
## First candle
##     a doji candle in a downtrend
## Second candle
##     a doji candle
##     a body below the prior body
## Third candle
##     a doji candle
##     a body above the prior body
bullish_signal_matrix(:,24) = downtrend_2 .* doji_2 .* ...
                               doji_1 .* (open_1 < close_2) .* ...
                               doji .* (open > close_1) ;
## 25 - Unique Three River Bottom
## First candle
##     black candle
##     a candle in a downtrend
## Second candle
##     black candle
##     a body within the prior body
##     the lower shadow is at least twice longer than the body
##     the low price below the prior low price
## Third candle
##     white candle
##     a body located below the prior body
##     the low price above the prior low price
bullish_signal_matrix(:,25) = downtrend_2 .* black_body_2 .* ...
                               black_body_1 .* (body_high_1 < body_high_2) .* (body_low_1 > body_low_2) .* ((body_low_1 .- low_1) >= body_range_1) .* (low_1 < low_2) .* ...
                               white_body .* (body_high < body_low_1) .* (low > low_1) ;
## 26 - Belt Hold
##     white body
##     no lower shadow
##     short upper shadow
##     appears as a long line
bullish_signal_matrix(:,26) = downtrend .* white_body .* (open == low) .* long_line ;

## 27 - Hammer
##     downtrend
##     white or black candle with a small body
##     no upper shadow or the shadow cannot be longer than the body
##     lower shadow between two to three times longer than the body
##     if the gap is created at the opening or at the closing, it makes the signal stronger
##     appears as a long line
bullish_signal_matrix(:,27) = downtrend .* (doji == 0) .* ((high .- body_high) < body_range) .* ((body_low .- low) > 2.*body_range) .* long_line ;

## 28 - Harami
## First candle
##     a candle in a downtrend
##     black body
## Second candle
##     white body
##     candle's body engulfed by the prior (black) candle's body
bullish_signal_matrix(:,28) = downtrend_1 .* black_body_1 .* ...
                               white_body .* (body_high < body_high_1) .* (body_low > body_low_1) ;
## 29 - Inverted Hammer 
## First candle
##     a candle in a downtrend
##     black body
## Second candle
##     a white or black candle with a small body
##     no lower shadow or the shadow cannot be longer than then body
##     upper shadow at least 2.5 times longer than the body
##     the open below or at the level of the previous candle's close
bullish_signal_matrix(:,29) = downtrend_1 .* black_body_1 .* ...
                               (doji == 0 ) .* ((body_low .- low) < body_range) .* ((high .- body_high) >= 2.5.*body_range) .* (open <= close_1) ;
                               
bullish_signal_matrix( 1 : 10 , : ) = 0 ;

endfunction

and Bearish Reversal Indicator
## Copyright (C) 2020 dekalog
## 
## This program is free software: you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
## 
## This program is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see
## .

## -*- texinfo -*- 
## @deftypefn {} {@var{bearish_signal_matrix} =} candle_bearish_reversal (@var{high}, @var{low}, @var{close}, @var{open}, @var{uptrend}, @var{avge_hi_lo_range})
##
## The HIGH, LOW, CLOSE and OPEN should be vectors of equal length, and are required.
##
## Internally the UPTREND is determined as a bar's CLOSE being higher than the CLOSE
## of the bar 5 bars previously. This can be over-ruled by an optional, user supplied
## vector UPTREND of zeros and ones, where one(s) represent a bar in an UPTREND.
## If an UPTREND vector consists solely of ones, this effectively turns off the
## discriminative ability of the UPTREND condition as all bars will be considered
## to be UPTREND bars. If the UPTREND vector consists solely of zeros, no bar
## will be classified as being in an UPTREND and those candle patterns that require an 
## UPTREND as a condition will not be indicated.
##
## The AVGE_HI_LO_RANGE is calculated as a rolling 5 bar simple moving average of
## the HI-LO range of bars. A bar is considered a "long line" if its HI-LO range
## is greater than the AVGE_HI_LO_RANGE. This can also be over-ruled, as above, by
## an optional, user supplied vector AVGE_HI_LO_RANGE, which consists of zeros and
## ones, with ones representing "long line" bars. An AVGE_HI_LO_RANGE vector of all
## ones or zeros will have a similar effect as described for the UPTREND vector.
##
## The candlestick pattern descriptions are predominantly taken from
##
## https://www.candlescanner.com
##
## and the bearish only patterns implemented are:
##
## Bearish Reversal High Reliability
##
##     01 - Bearish Abandoned Baby
##
##     02 - Dark Cloud Cover
##
##     03 - Evening Doji Star
##
##     04 - Evening Star
##
##     05 - Kicking
##
##     06 - Three Black Crows
##
##     07 - Three Inside Down
##
##     08 - Three Outside Down
##
##     09 - Upside Gap Two Crows
##
## Bearish Reversal Moderate Reliability
##
##     10 - Advance Block
##
##     11 - Breakaway
##
##     12 - Counter Attack
##
##     13 - Deliberation
##
##     14 - Doji Star
##
##     15 - Dragonfly Doji
##
##     16 - Engulfing
##
##     17 - Gravestone Doji
##
##     18 - Harami Cross
##
##     19 - Identical Three Crows
##
##     20 - Long Legged Doji
##
##     21 - Meeting Lines
##
##     22 - Tri Star
##
##     23 - Two Crows
##
## Bearish Reversal Low Reliability
##
##     24 - Belt Hold 
##
##     25 - Hanging Man
##
##     26 - Harami
##
##     27 - Shooting Star
##
## The output BEARISH_SIGNAL_MATRIX has a row length the same as the OHLC
## input vectors and 27 columns. The matrix is a zero filled matrix with the
## value 1 when a candle pattern is indicated. The row ix of the value is the
## row ix of the last candle in the pattern. The column ix corresponds to the
## pattern index given above.
##
## @seealso{candle_bullish_reversal}
## @end deftypefn

## Author: dekalog 
## Created: 2020-08-10

function bearish_signal_matrix = candle_bearish_reversal ( varargin )

if ( nargin < 4 || nargin > 6 )
  print_usage () ;
elseif ( nargin == 4 )
  high = varargin{1} ; low = varargin{2} ; close = varargin{3} ; open = varargin{4} ;
  uptrend = close > shift( close , 5 ) ;
  avge_hi_lo_range = filter( [0.2 ; 0.2 ; 0.2 ; 0.2 ; 0.2 ] , 1 , high .- low ) ; ## 5 bar simple moving average
elseif ( nargin == 5 )
  high = varargin{1} ; low = varargin{2} ; close = varargin{3} ; open = varargin{4} ;
  uptrend = varargin{5} ;
  avge_hi_lo_range = filter( [0.2 ; 0.2 ; 0.2 ; 0.2 ; 0.2 ] , 1 , high .- low ) ; ## 5 bar simple moving average
elseif ( nargin == 6 )
  high = varargin{1} ; low = varargin{2} ; close = varargin{3} ; open = varargin{4} ;
  uptrend = varargin{5} ; avge_hi_lo_range = varargin{6} ;
endif

bearish_signal_matrix = zeros( size( close , 1 ) , 27 ) ;

## pre-compute some basic vectors for re-use below, trading memory use for
## speed of execution
uptrend_1 = shift( uptrend , 1 ) ;
uptrend_2 = shift( uptrend , 2 ) ;
long_line = ( high .- low ) > shift( avge_hi_lo_range , 1 ) ;
long_line_1 = shift( long_line , 1 ) ;
long_line_4 = shift( long_line , 4 ) ;
open_1 = shift( open , 1 ) ;
open_2 = shift( open , 2 ) ;
open_3 = shift( open , 3 ) ;
high_1 = shift( high , 1 ) ;
high_2 = shift( high , 2 ) ;
high_4 = shift( high , 4 ) ;
low_1 = shift( low , 1 ) ;
close_1 = shift( close , 1 ) ;
close_2 = shift( close , 2 ) ;
close_4 = shift( close , 4 ) ;
black_body = close < open ;
black_body_1 = shift( black_body , 1 ) ;
black_body_2 = shift( black_body , 2 ) ;
white_body = close > open ;
white_body_1 = shift( white_body , 1 ) ;
white_body_2 = shift( white_body , 2 ) ;
white_body_3 = shift( white_body , 3 ) ;
white_body_4 = shift( white_body , 4 ) ;
doji = ( close == open ) ;
doji_1 = shift( doji , 1 ) ;
doji_2 = shift( doji , 2 ) ;
body_high = max( [ open , close ] , [] , 2 ) ;
body_high_1 = shift( body_high , 1 ) ;
body_high_2 = shift( body_high , 2 ) ;
body_low = min( [ open , close ] , [] , 2 ) ;
body_low_1 = shift( body_low , 1 ) ;
body_low_2 = shift( body_low , 2 ) ;
body_midpoint = ( body_high .+ body_low ) ./ 2 ;
body_midpoint_1 = shift( body_midpoint , 1 ) ;
body_midpoint_2 = shift( body_midpoint , 2 ) ;
candle_midpoint = ( high .+ low ) ./ 2 ;
candle_midpoint_1 = shift( candle_midpoint , 1 ) ; 
body_range = body_high .- body_low ;
wick_gap_up = low > shift( high , 1 ) ;
wick_gap_up_1 = shift( wick_gap_up , 1 ) ;
wick_gap_down = high < shift( low , 1 ) ;
black_marubozu = ( high == open ) .* ( low == close ) ;
white_marubozu = ( high == close ) .* ( low == open ) ;
white_marubozu_1 = shift( white_marubozu , 1 ) ;

## 01 - Bearish Abandoned Baby
## First candle
##     a candle in an uptrend
##     white body
## Second candle
##     a doji candle
##     the low price above the prior high price
## Third candle
##     black body
##     the high price below the prior low price
bearish_signal_matrix(:,1) = uptrend_2 .* white_body_2 .* ...
                              doji_1 .* wick_gap_up_1 .* ...
                              black_body .* wick_gap_down ; 
## 02 - Dark Cloud Cover
## First candle
##     a candle in an uptrend
##     white body
## Second candle
##     black body
##     the opening above or equal of the prior high
##     the closing below the midpoint of the prior candle
##     the closing above the previous opening
bearish_signal_matrix(:,2) = uptrend_1 .* white_body_1 .* ...
                              black_body .* (open >= high_1) .* (close < candle_midpoint_1) .* (close > open_1) ;  
## 03 - Evening Doji Star
## First candle
##     a candle in an uptrend
##     white body
## Second candle
##     a doji candle
##     a doji body above the previous candle body
##     the low price below the previous candle high price
## Third candle
##     black body
##     candle body below the previous candle body
##     the closing price below the midpoint of the first candle body
bearish_signal_matrix(:,3) = uptrend_2 .* white_body_2 .* ...
                              doji_1 .* (open_1 > body_high_2) .* (low_1 < high_2) .* ...
                              black_body .* (body_high < close_1) .* (close < body_midpoint_2) ;
## 04 - Evening Star
## First candle
##     a candle in an uptrend
##     white body
## Second candle
##     white or black body
##     the candle body is located above the prior body
## Third candle
##     black body
##     the candle body is located below the prior body
##     the candle closes at least halfway down the body of the first line
bearish_signal_matrix(:,4) = uptrend_2 .* white_body_2 .* ...
                              (body_low_1 > body_high_2) .* ...
                              black_body .* (body_high < body_low_1) .* (close <= body_midpoint_2) ;
## 05 - Kicking
## First candle
##     a White Marubozu
##     appears on as a long line
## Second candle
##     a Black Marubozu
##     price gaps downward
##     appears on as a long line
bearish_signal_matrix(:,5) = white_marubozu_1 .* long_line_1 .* ...
                              black_marubozu .* (high < low_1) .* long_line ; 
## 06 - Three Black Crows
## First candle
##     a candle in an uptrend
##     black body
## Second candle
##     black body
##     the opening price within the previous body
##     the closing price below the previous closing price
## Third candle
##     black body
##     the opening price within the previous body
##     the closing price below the previous closing price
bearish_signal_matrix(:,6) = uptrend_2 .* black_body_2 .* ...
                              black_body_1 .* (open_1 < body_high_2) .* (open_1 > body_low_2) .* (close_1 < close_2) .* ...
                              black_body .* (open < body_high_1) .* (open > body_low_1) .* (close < close_1) ; 
## 07 - Three Inside Down
## First candle
##     a candle in an uptrend
##     white body
## Second candle
##     black body
##     the candle body is engulfed by the prior candle body
## Third candle
##     black_body
##     the closing price is below the previous closing price
bearish_signal_matrix(:,7) = uptrend_2 .* white_body_2 .* ...
                              black_body_1 .* (body_high_1 < body_high_2) .* (body_low_1 > body_low_2) .* ...
                              black_body .* (close < close_1) ;
## 08 - Three Outside Down
## First candle
##     a candle in an uptrend
##     white body
## Second candle
##     black body
##     candle’s body engulfs the prior (white) candle’s body
## Third candle
##     closing price below the previous closing price
##     black body
bearish_signal_matrix(:,8) = uptrend_2 .* white_body_2 .* ...
                              black_body_1 .* (body_high_1 > body_high_2) .* (body_low_1 < body_low_2) .* ...
                              black_body .* (close < close_1) ;
## 09 - Upside Gap Two Crows
## First candle
##     a candle in an uptrend
##     white body
## Second candle
##     black body
##     candle's body above the previous candle's body
## Third candle
##     black body
##     candle’s body engulfs the prior candle’s body
bearish_signal_matrix(:,9) = uptrend_2 .* white_body_2 .* ...
                              black_body_1 .* (body_low_1 > body_high_2) .* ...
                              black_body .* (body_high > body_high_1) .* (body_low < body_low_1) ;
## 10 - Advance Block
## First candle
##     a candle in an uptrend
##     white body
## Second candle
##     white body
##     the opening price is within the previous body
##     the closing price is above the previous closing price
## Third candle
##     white body
##     the opening price is within the previous body
##     the closing price is above the previous closing price
bearish_signal_matrix(:,10) = uptrend_2 .* white_body_2 .* ...
                               white_body_1 .* (open_1 < body_high_2) .* (open_1 > body_low_2) .* (close_1 > close_2) .* ...
                               white_body .* (open < body_high_1) .* (open > body_low_1) .* (close > close_1) ;
## 11 - Breakaway
## First candle
##     a tall white candle
## Second candle
##     a white candle
##     candle opens above the previous closing price (upward price gap, shadows can overlap)
## Third candle
##     a white or black candle
##     candle opens above the previous opening price
## Fourth candle
##     a white candle
##     candle closes above the previous closing price
## Fifth candle
##     a tall black candle
##     candle opens below the previous closing price
##     candle closes below the second line's opening price and above the first line's closing price
##     the price gap formed between the first and the second line is not closed
bearish_signal_matrix(:,11) = white_body_4 .* long_line_4 .* ...
                               white_body_3 .* (open_3 > close_4) .* ...
                               (open_2 > open_3 ) .* ...
                               white_body_1 .* (close_1 > close_2) .* ...
                               black_body .* long_line .* (open < close_1) .* (close < open_3) .* (close > close_4) .* (low > high_4) ;
## 12 - Counter Attack
## First candle
##     a candle in an uptrend
##     white body
## Second candle
##     black_body
##     the opening price is higher than the previous closing price
##     the closing price is at or lower than the previous closing price
bearish_signal_matrix(:,12) = uptrend_1 .* white_body_1 .* ...
                               black_body .* (open > close_1) .* (close <= close_1) ;
## 13 - Deliberation
## First candle
##     a candle in an uptrend
##     white body
## Second candle
##     white body
##     the opening price is above the previous opening price
##     the closing price is above the previous closing price
## Third candle
##     white body
##     the opening price is slightly lower or higher than the previous closing price
##     the closing price is above the previous closing price
bearish_signal_matrix(:,13) = uptrend_2 .* white_body_2 .* ...
                               white_body_1 .* (open_1 > open_2) .* (close_1 > close_2) .* ...
                               white_body .* (open > body_midpoint_1) .* (close > close_1) ;
## 14 - Doji Star
## First candle
##     a candle in an uptrend
##     white body
## Second candle
##     a doji candle
##     a body above the first candle's body
bearish_signal_matrix(:,14) = uptrend_1 .* white_body_1 .* ...
                               doji .* (open > close_1) ; 
## 15 - Dragonfly Doji
##     Opening, closing and maximum prices are the same or very similar
##     Long lower shadow
##     appears on as a long line
bearish_signal_matrix(:,15) = (open == close) .* (close == high) .* long_line ;

## 16 - Engulfing
## First candle
##     a candle in an uptrend
##     white body
## Second candle
##     black body
##     candle's body engulfs the prior (white) candle's body
bearish_signal_matrix(:,16) = uptrend_1 .* white_body_1 .* ...
                               black_body .* (body_high > body_high_1) .* (body_low < body_low_1) ;
## 17 - Gravestone Doji
##     Opening, closing and minimum prices are the same or very similar
##     Long upper shadow
##     appears on as a long line
bearish_signal_matrix(:,17) = (open == close) .* (close == low) .* long_line ;

## 18 - Harami Cross
## First candle
##     a candle in an uptrend
##     white body
## Second candle
##     a doji candle with two shadows
##     candle's body engulfed by the prior (white) candle's body
bearish_signal_matrix(:,18) = uptrend_1 .* white_body_1 .* ...
                               doji .* (high > close) .* (low < close) .* (high < body_high_1) .* (low > body_low_1) ;
## 19 - Identical Three Crows
## First candle
##     a candle in an uptrend
##     black body
## Second candle
##     black body
##     the opening price at or near the prior close
## Third candle
##     black body
##     the opening price at or near the prior close
bearish_signal_matrix(:,19) = uptrend_2 .* black_body_2 .* ...
                               black_body_1 .* (open_1 == close_2) .* ...
                               black_body .* (open == close_1) ;
## 20 - Long Legged Doji
##     a doji candle
##     opening and closing prices are the same or similar
##     upper and lower shadow are very long
##     body is located in the middle of the candle or nearly mid-range
##     appears on as a long line
bearish_signal_matrix(:,20) = doji .* ((high .- close) > 0) .* ((close .- low) > 0) .* long_line ;

## 21 - Meeting Lines
## First candle
##     a candle in an uptrend
##     white body
##     appears as a long line
## Second candle
##     black body
##     the closing price is equal to the previous closing price
bearish_signal_matrix(:,21) = uptrend_1 .* white_body_1 .* long_line_1 .* ...
                               black_body .* (close == close_1) ;
## 22 - Tri Star
## First candle
##     a doji candle in an uptrend
## Second candle
##     a doji candle
##     a body above the prior body
## Third candle
##     a doji candle
##     a body below the prior body
bearish_signal_matrix(:,22) = uptrend_2 .* doji_2 .* ...
                               doji_1 .* (open_1 > close_2) .* ...
                               doji .* (open < close_1) ;
## 23 - Two Crows
## First candle
##     a candle in an uptrend
##     white body
## Second candle
##     black body
##     the closing price above the prior closing price (gap between bodies)
## Third candle
##     black body
##     the opening price within the prior body
##     the closing price within the body of the first line (gap close)
bearish_signal_matrix(:,23) = uptrend_2 .* white_body_2 .* ...
                               black_body_1 .* (close_1 > close_2) .* ...
                               black_body .* (open < body_high_1) .* (open > body_low_1) .* (close < close_2) ;
## 24 - Belt Hold
##     black body
##     no upper shadow
##     short lower shadow
##     appears as a long line
bearish_signal_matrix(:,24) = black_body .* (open == high) .* (low < close) .* long_line ;

## 25 - Hanging Man
##     uptrend
##     white or black candle with a small body
##     no upper shadow or the shadow cannot be longer than the body
##     lower shadow at least two times longer than the body
##     if the gap is created at the opening or at the closing, it makes the signal stronger
##     appears as a long line
##     the body fully located above the trendline
bearish_signal_matrix(:,25) = uptrend .* (doji == 0) .* ((high .- body_high) < body_range) .* ((body_low .- low) >= 2.*body_range) ; 

## 26 - Harami
## First candle
##     a candle in an uptrend
##     white body
## Second candle
##     black body
##     candle's body engulfed by the prior (white) candle's body
bearish_signal_matrix(:,26) = uptrend_1 .* white_body_1 .* ...
                               black_body .* (body_high < body_high_1) .* (body_low > body_low_1) ;
## 27 - Shooting Star
##     white or black candle with a small body
##     no lower shadow or the shadow cannot be longer than the body
##     upper shadow at least two times longer than the body
##     if the gap is created at the opening or the closing, it makes the signal stronger
##     appears as a long line
bearish_signal_matrix(:,27) = (doji == 0) .* ((body_low .- low) < body_range) .* ((high .- body_high) >= 2.*body_range) ;

bearish_signal_matrix( 1 : 10 , : ) = 0 ;

endfunction