Let's develop together: Piercing Line pattern detection

Moderator: admin

Let's develop together: Piercing Line pattern detection

Postby Nikolay.Gekht » Tue Jun 15, 2010 11:45 am

Please read first the Let's develop together: Guppy's Multiple Moving Average.

Let's we have a goal to detect the candle, which has:
a) The previous candle is a red candle and is below than it's previous to candle.
b) The current candle is a green candle and is below that the previous candle
c) The current candle closes above it's midpoint
or
a) The previous candle is a green candle and is above than it's previous to candle.
b) The current candle is a red candle and is above that the previous candle
c) The current candle closes below it's midpoint

In short, it's a Bullish and Bearish piercing line candle patterns (see, for example, here http://www.bipasforex.com/files/Candle.pdf).
Image

So, we need to develop a… well, it is indicator too, which will mark the candles which satisfy to the conditions above.

There are two serious distinctions from the “numeric” indicators (like a guppy moving average we developed in the previous article).

1) The indicator does not show lines or bars. It must just mark candles.

To mark the candles we can use the alternative indicator output: the text output. The text output is a set of labels which can be applied on the particular bar at the particular price level.
You can read more in the online documentation. See: instance:createTextOutput

Let’s decide on how mark the candles. I suggest using the down arrow located above the candle for the bearish pierce and the up arrow located below the candle for the bullish pierce. There is the standard font called “Wingdings” which contains characters for arrows (note: for some reason Mozilla does not display windings correctly, so please use Internet Explorer to open the previous link). The up arrow has the code 225 and the down arrow has code 226.

Because the up arrow must be located below and the down arrow must be located above, we need for two outputs with different alignment settings. “Alignment” is a rule which describes how to locate the text against the center of the bar and the price level. For example, “Top” means “Locate the character ABOVE the price”, that is good for the marking above the candle high price, and “Bottom” means “Locate the label BELOW the price”, that is good for marking below the candle low price.

2) The indicator must process the closed candles only.

As you know, the indicator update function is called every time when the candle is changed. So, if there were 100 ticks in a 1-minute candle, the Update function will be called 100 times. In our indicator we should not process such “live” candles at all. We have to process only those candles which were recently closed.

To know when one candle is closed and another candle is started we can use so called “serial” number of the bar. The serial number is a number with is unique for each bar in the history. So, when a bar with a new serial number appears we have to process the previous (the recently closed!) bar.

Well. Nuff said about the theory. Let’s start. :-)

As in the first article we have to “introduce” our indicator. Since we don’t have any parameters, the process is pretty simple. This is an indicator (i.e. we want to show the results immediately on the chart) and this indicator requires for bars.

Code: Select all
function Init()
    indicator:name("Piercing Line detector");
    indicator:description("");
    indicator:requiredSource(core.Bar);
    indicator:type(core.Indicator);

    indicator.parameters:addColor("clr", "Arrows color", "", core.COLOR_LABEL);
end


We have one parameter. It’s a color for the arrows. Pay attention that in this case we don’t specify the certain color. We use the value “core.COLOR_LABEL” instead. This means that the color must be the same as the color specified in the configuration for the labels.

Then we must prepare the indicator to work when the indicator is applied to chart. There is almost nothing to do except creating two text outputs. One for the up candles and another for the down candles.

Code: Select all
local source;
local first;

function Prepare()
    source = instance.source;
    instance:name(profile:id());
    up = instance:createTextOutput ("Up", "Up", "Wingdings", 10, core.H_Center, core.V_Top, instance.parameters.clr, 0);
    down = instance:createTextOutput ("Dn", "Dn", "Wingdings", 10, core.H_Center, core.V_Bottom, instance.parameters.clr, 0);
    first = source:first() + 3;
end


We also remember the source price series in the global variable and calculate the index of the first bar we can recognize (we need two bars before the bar we probe, yeah?). As in the previous indicator we do it just for the better performance.

Now we can start the Update function. First, let’s implement the code which will protect us from multiple calling for the “live” candles.

Code: Select all
-- the variable to keep the serial number of the previous candle
local last = nil;

function Update(period, mode)
    if last == nil or                       -- if it is first call or
       last ~= source:serial(period) then   -- another candle started
        last = source:serial(period);       -- remember the candle
        period = period - 1;                -- and process the previous period (the
                                            -- candle which just has been closed).
    else
        -- if the current candle is being changed - do nothing
        return ;
    end


Please, pay attention on the period = period - 1; line. When we detected that the candle is closed and a new candle appears, the “period” value points us to the newly appeared candle. The recently closed candle is the previous candle. So, we have to subtract one to make “period” pointing to the recently closed candle.

Now we can check whether we have enough candles in history (i.e. period is bigger than the “first” value calculated in the “Init” procedure) and the start to probe the recently closed candle for our conditions.

Let’s translate the conditions into lua.
a) The previous candle is a red candle
source.open[period – 1] > source.close[period – 1]
and is below than it's previous to candle.
source.low[period – 1] < source.low[period – 2] and
source.high[period – 1] < source.high[period – 2]

b) The current candle is a green candle and
source.open[period] < source.close[period]

is below that the previous candle
source.low[period] < source.low[period – 1] and
source.high[period] < source.high[period – 1]

c) The current candle closes above it's midpoint
source.close[period] > (source.high[period] + source.low[period]) / 2

To get the bearish conditions – just invert all comparisons.

If conditions are satisfied – just put the down directed candle (code “226”) above the candle (“up” output, using the high price) or the up directed candle (code “225”) below the candle (“down” output, using the low price).

Code: Select all
    if period > first then
        -- detect piercing line bullish
        -- the recently closed candle must be completely below the previous candle.
        -- the previous candle must be completely below it's previous candle
        -- and the close of the current candle must be above the mid point (H + L / 2)
        if source.low[period] < source.low[period - 1] and
           source.high[period] < source.high[period - 1] and
           source.open[period] < source.close[period] and
           source.low[period - 1] < source.low[period - 2] and
           source.high[period - 1] < source.high[period - 2] and
           source.open[period - 1] > source.close[period - 1] and
           source.close[period] > (source.high[period] + source.low[period]) / 2 then
           down:set(period, source.low[period], "\225");
        end

        -- detect piercing line bearish
        -- the recently closed candle must be completely above the previous candle.
        -- the previous candle must be completely above it's previous candle
        -- and the close of the current candle must be below the mid point (H + L / 2)
        if source.low[period] > source.low[period - 1] and
           source.high[period] > source.high[period - 1] and
           source.open[period] > source.close[period] and
           source.low[period - 1] > source.low[period - 2] and
           source.high[period - 1] > source.high[period - 2] and
           source.open[period - 1] < source.close[period - 1] and
           source.close[period] < (source.high[period] + source.low[period]) / 2 then
           up:set(period, source.high[period], "\226");
        end
    end
end


Let’s see the whole code of the indicator:
Code: Select all
function Init()
    indicator:name("Piercing Line detector");
    indicator:description("");
    indicator:requiredSource(core.Bar);
    indicator:type(core.Indicator);
    indicator.parameters:addColor("clr", "Arrow color", "", core.COLOR_LABEL);
end

local source;
local first;

function Prepare()
    source = instance.source;
    instance:name(profile:id());
    up = instance:createTextOutput ("Up", "Up", "Wingdings", 10, core.H_Center, core.V_Top, instance.parameters.clr, 0);
    down = instance:createTextOutput ("Dn", "Dn", "Wingdings", 10, core.H_Center, core.V_Bottom, instance.parameters.clr, 0);
    first = source:first() + 3;
end

-- the variable to keep the serial number of the previous candle
local last = nil;

function Update(period, mode)
    if last == nil or                       -- if it is first call or
       last ~= source:serial(period) then   -- another candle started
        last = source:serial(period);       -- remember the candle
        period = period - 1;                -- and process the previous period (the
                                            -- candle which just has been closed).
    else
        -- if the current candle is being changed - do nothing
        return ;
    end

    if period > first then
        -- detect piercing line bullish
        -- the recently closed candle must be completely below the previous candle.
        -- the previous candle must be completely below it's previous candle
        -- and the close of the current candle must be above the mid point (H + L / 2)
        if source.low[period] < source.low[period - 1] and
           source.high[period] < source.high[period - 1] and
           source.open[period] < source.close[period] and
           source.low[period - 1] < source.low[period - 2] and
           source.high[period - 1] < source.high[period - 2] and
           source.open[period - 1] > source.close[period - 1] and
           source.close[period] > (source.high[period] + source.low[period]) / 2 then
           down:set(period, source.low[period], "\225");
        end

        -- detect piercing line bearish
        -- the recently closed candle must be completely above the previous candle.
        -- the previous candle must be completely above it's previous candle
        -- and the close of the current candle must be below the mid point (H + L / 2)
        if source.low[period] > source.low[period - 1] and
           source.high[period] > source.high[period - 1] and
           source.open[period] > source.close[period] and
           source.low[period - 1] > source.low[period - 2] and
           source.high[period - 1] > source.high[period - 2] and
           source.open[period - 1] < source.close[period - 1] and
           source.close[period] < (source.high[period] + source.low[period]) / 2 then
           up:set(period, source.high[period], "\226");
        end
    end
end


Download the indicator:
pl_detector.lua
(2.9 KiB) Downloaded 1224 times


pl.png
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1235
Joined: Wed Dec 16, 2009 6:39 pm
Location: Cary, NC

Re: Let's develop together: Piercing Line pattern detection

Postby coldrecs » Tue Nov 23, 2010 3:03 pm

Nikolay,

Thank you very much for these articles from which I learned allot about writing code for custom indicators.

I wanted to suggest that when you will have time, if you propose to write another article, It would be very useful if you could show us how to draw on current chart an indicator from a Bigger Time Frame (something like plotting a 20 period MA from the daily chart on to the 1 minute chart).

Also I would be interested in learning how to write a Heat Map kind of indicator (from multiple bigger time frames onto the current lower time frame).

Thank you very much for your work and your effort!
coldrecs
 
Posts: 5
Joined: Tue Aug 31, 2010 6:17 am

Re: Let's develop together: Piercing Line pattern detection

Postby before2012 » Wed Mar 14, 2012 11:40 pm

I tried to your sample in my computer. but it could not produce same symbol as yours (meant, the up/down arrow), it prints strange symbol. And I also tried "\200" but not "\226", I also saw strange bymbols.

Now the question is "is there anything that we can do to control the symbol to print?"
before2012
 
Posts: 15
Joined: Fri Aug 26, 2011 12:57 am

Re: Let's develop together: Piercing Line pattern detection

Postby sunshine » Thu Mar 15, 2012 3:25 am

It looks like Marketscope cannot find the "Wingdings" font. Please check whether Windows has this font (using Control Panel->Fonts). If there is no this font, please install it (see attached).

You can find the instructions on how to install the font here: Custom Font Installation and Use
Attachments
wingding.ttf
(79.1 KiB) Downloaded 879 times
sunshine
 

Re: Let's develop together: Piercing Line pattern detection

Postby before2012 » Thu Mar 15, 2012 9:21 am

Huh! it works now. thank you again :lol:
before2012
 
Posts: 15
Joined: Fri Aug 26, 2011 12:57 am


Return to Indicator Development

Who is online

Users browsing this forum: No registered users and 8 guests