Why so many signals work only with already closed bars

Moderator: admin

Why so many signals work only with already closed bars

Postby Nikolay.Gekht » Thu Sep 02, 2010 4:56 pm

Why so many signals and some indicators work only with already closed bars?

As you probably noticed, most signals applied to a particular timeframe check the market conditions and show alerts only when a bar is completely closed. For example, when the signal is applied to 1-hour bars, the signal which appears on 15:00 bar will be shown on 16:00, in other words only when the 15:00 bar has just been closed. It could look pretty inconvenient because it looks like there is an hour delay in the signal.

Is it right? Probably, yes. But just try what really happens in case we check the market conditions on a live bar, which is being permanently changed when every new price (aka tick) appears. Let’s create a simple indicator which shows an arrow on the bars for which the close price of a bar is higher than the close price of the previous bar.

Code: Select all
function Init()
    indicator:name("Show bars where current close is higher than previous");
    indicator:description("");
    indicator:requiredSource(core.Bar);
    indicator:type(core.Indicator);

    indicator.parameters:addColor("clr", "Label Color", "", core.COLOR_LABEL);
end

local source;
local mark;
local first;

function Prepare()
    source = instance.source;
    local name = profile:id();
    instance:name(name);
    first = source:first() + 1;
    mark = instance:createTextOutput ("Mark", "Mark", "Wingdings", 10, core.H_Center, core.V_Top, instance.parameters.clr, 0);
end

function Update(period, mode)
    if period > first then
        if source.close[period] > source.close[period - 1] then
            mark:set(period, source.close[period], "\226");
        end
    end
end


Then apply the indicator on a chart. I recommend choosing 1-minute timeframe because you’ll get the result I want to show you in just a few minutes. When the indicator has just been applied, everything looks ok. Those bars which have higher close are marked with an arrow. But now leave the indicator for a few minutes. Oops... Strange false signals appear. Why? To tell truth, it is easy. The indicator is called every time a new price comes. At the moment of the call, the latest price is shown as a close price of the latest bar... So, even if finally the bar does not match the market condition, in the middle of the time frame the bar can match. Look at the snapshot:

noise1.png

(click on image to enlarge it)

You can see the false signals right after we leave the indicator applied on live data.

So, let’s see. While the indicator is applied on historical data, the update function is called only once, and gets the final version of the bar. But for live bars, the indicator is called as many times as many ticks appeared during the bar. If you imagine how a bar looked while the bar was not finished (look at the last false signal on the snapshot above) – you’ll see that sometimes the bar DID match the signal condition.

So, in short, for almost all signals and for many indicators, the indicator can produce "noise" – in other words, produce a false signal even if in the final version of a bar the signal does not appear. Such noise signals may lead you into wrongful market decisions, so, the best way is to wait while the bar is finished and you can surely check whether the signal condition was met during the bar or not.

How to handle this situation in indicators?

The best way is to process the bar only in case the bar is being closed. To check whether the bar was finished, you can check a "serial number" of the bar and process the latest bar of alive history only in case it is completely finished (it is not the last anymore). Let’s change the indicator above in that way.

Code: Select all
function Init()
    indicator:name("Show bars where current close is higher than previous");
    indicator:description("");
    indicator:requiredSource(core.Bar);
    indicator:type(core.Indicator);

    indicator.parameters:addColor("clr", "Label Color", "", core.COLOR_LABEL);
end

local source;
local mark;
local first;

function Prepare()
    source = instance.source;
    local name = profile:id();
    instance:name(name);
    first = source:first() + 1;
    mark = instance:createTextOutput ("Mark", "Mark", "Wingdings", 10, core.H_Center, core.V_Top, instance.parameters.clr, 0);
end

local serial = nil;

function Update(period, mode)
    if period > first then
        if source:isAlive() and                                 -- if the history we applied to is alive
           period == source:size() - 1 then                     -- and this is the last value (live bar)
           if serial ~= source:serial(source:size() - 1) then   -- and the last bar is a new bar
                serial = source:serial(source:size() - 1);      -- remember a new last bar
                period = period - 1;                            -- and force to process the previous (e.g. the most
                                                                -- recently finished bar
            else
                return;                                         -- the bar is not changed, so
                                                                -- just do not process it
            end
        end
        if source.close[period] > source.close[period - 1] then
            mark:set(period, source.close[period], "\226");
        end
    end
end


Voila, no more noise!

How to handle this situation in signals/strategies?

If you use the subscription management using helper.lua, you have nothing to do. The helper notifies you only when a bar is completely closed.

If you implement the subscription by yourself, just go in the same way as for the indicators – just do not check market conditions until the new bar appears in the subscribed timeframe.
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1235
Joined: Wed Dec 16, 2009 6:39 pm
Location: Cary, NC

Return to Indicator Development

Who is online

Users browsing this forum: No registered users and 11 guests

cron