Elder Impulse System

Here you can post and download custom indicators. PLEASE: Do not start topics unless you are posting your own indicator, they will be moved to appropriate section even if you do.

Moderator: admin

Elder Impulse System

Postby Nikolay.Gekht » Sun May 09, 2010 6:28 pm

Note Please take the optimized version of these indicators, especially heat map!

Please, read more about Elder Impulse system here: http://stockstudent.blogspot.com/2008/0 ... ystem.html

elder.png


Download:
Elder_Impulse_System.lua
(3.44 KiB) Downloaded 2308 times

EIS.lua
(4.26 KiB) Downloaded 44 times


See also the signal.

Note: the implementation is a port of the MT4's indicator which uses modified a slightly version of the MACD formula.
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1235
Joined: Wed Dec 16, 2009 6:39 pm
Location: Cary, NC

Re: Elder Impulse System

Postby Hybrid » Fri May 14, 2010 4:53 pm

Thank you for the Oscillator. :)

Can a bigger time frame version be done, please?
Hybrid
 
Posts: 42
Joined: Fri Apr 02, 2010 7:52 am

Re: Elder Impulse System

Postby Alexander.Gettinger » Tue Sep 28, 2010 2:30 am

Bigger timeframe Elder Impulse System:

BF_Elder_Impulse_System.png


Code: Select all
function Init()
    indicator:name("Bigger timeframe Elder Impulse System");
    indicator:description("");
    indicator:requiredSource(core.Bar);
    indicator:type(core.Oscillator);

    indicator.parameters:addGroup("Calculation");
    indicator.parameters:addString("BS", "Time frame to calculate indicator", "", "D1");
    indicator.parameters:setFlag("BS", core.FLAG_PERIODS);
    indicator.parameters:addInteger("EMA", "EMA periods for study", "", 13, 1, 100);
    indicator.parameters:addInteger("MACDF", "MACD periods fast", "", 12, 1, 100);
    indicator.parameters:addInteger("MACDS", "MACD periods slow", "", 26, 1, 100);
    indicator.parameters:addString("Price", "Price", "", "close");
    indicator.parameters:addStringAlternative("Price", "open", "", "open");
    indicator.parameters:addStringAlternative("Price", "close", "", "close");
    indicator.parameters:addStringAlternative("Price", "high", "", "high");
    indicator.parameters:addStringAlternative("Price", "low", "", "low");
    indicator.parameters:addStringAlternative("Price", "typical", "", "typical");
    indicator.parameters:addStringAlternative("Price", "median", "", "median");
    indicator.parameters:addStringAlternative("Price", "weighted", "", "weighted");
   
    indicator.parameters:addGroup("Display");
    indicator.parameters:addColor("UP_color", "Color of up signal", "", core.rgb(0, 255, 0));
    indicator.parameters:addColor("DOWN_color", "Color of down signal", "", core.rgb(255, 0, 0));
    indicator.parameters:addColor("NE_color", "Color of neutral signal", "", core.rgb(0, 0, 255));
end

local source;                   -- the source
local bf_data = nil;          -- the high/low data
local EMA;
local MACDF;
local MACDS;
local BS;
local bf_length;                 -- length of the bigger frame in seconds
local dates;                    -- candle dates
local host;
local day_offset;
local week_offset;
local extent;
local Ind;
local PriceType;

function Prepare()
    source = instance.source;
    host = core.host;

    day_offset = host:execute("getTradingDayOffset");
    week_offset = host:execute("getTradingWeekOffset");

    BS = instance.parameters.BS;
    EMA = instance.parameters.EMA;
    MACDF = instance.parameters.MACDF;
    MACDS = instance.parameters.MACDS;
    PriceType=instance.parameters.Price;
    extent = EMA*2;

    local s, e, s1, e1;

    s, e = core.getcandle(source:barSize(), core.now(), 0, 0);
    s1, e1 = core.getcandle(BS, core.now(), 0, 0);
    assert ((e - s) <= (e1 - s1), "The chosen time frame must be bigger than the chart time frame!");
    bf_length = math.floor((e1 - s1) * 86400 + 0.5);

    local name = profile:id() .. "(" .. source:name() .. "," .. BS ..",".. PriceType .."," .. EMA .. "," .. MACDF .. "," .. MACDS .. ")";
    instance:name(name);
    UP = instance:addStream("UP", core.Bar, name .. "UP", "UP", instance.parameters.UP_color, 0);
    DOWN = instance:addStream("DN", core.Bar, name .. "DN", "DN", instance.parameters.DOWN_color, 0);
    NE = instance:addStream("NE", core.Bar, name .. "NE", "NE", instance.parameters.NE_color, 0);

end


local loading = false;
local loadingFrom, loadingTo;
local pday = nil;

-- the function which is called to calculate the period
function Update(period, mode)
    -- get date and time of the hi/lo candle in the reference data
    local bf_candle;
    bf_candle = core.getcandle(BS, source:date(period), day_offset, week_offset);

    -- if data for the specific candle are still loading
    -- then do nothing
    if loading and bf_candle >= loadingFrom and (loadingTo == 0 or bf_candle <= loadingTo) then
        return ;
    end

    -- if the period is before the source start
    -- the do nothing
    if period < source:first() then
        return ;
    end

    -- if data is not loaded yet at all
    -- load the data
    if bf_data == nil then
        -- there is no data at all, load initial data
        local to, t;
        local from;

        if (source:isAlive()) then
            -- if the source is subscribed for updates
            -- then subscribe the current collection as well
            to = 0;
        else
            -- else load up to the last currently available date
            t, to = core.getcandle(BS, source:date(period), day_offset, week_offset);
        end

        from = core.getcandle(BS, source:date(source:first()), day_offset, week_offset);
        UP:setBookmark(1, period);
        -- shift so the bigger frame data is able to provide us with the stoch data at the first period
        from = math.floor(from * 86400 - (bf_length * extent) + 0.5) / 86400;
        local nontrading, nontradingend;
        nontrading, nontradingend = core.isnontrading(from, day_offset);
        if nontrading then
            -- if it is non-trading, shift for two days to skip the non-trading periods
            from = math.floor((from - 2) * 86400 - (bf_length * extent) + 0.5) / 86400;
        end
        loading = true;
        loadingFrom = from;
        loadingTo = to;
        bf_data = host:execute("getHistory", 1, source:instrument(), BS, loadingFrom, to, source:isBid());
        if PriceType=="open" then
         Ind = core.indicators:create("ELDER_IMPULSE_SYSTEM", bf_data.open, EMA, MACDF, MACDS);
        elseif PriceType=="close" then
         Ind = core.indicators:create("ELDER_IMPULSE_SYSTEM", bf_data.close, EMA, MACDF, MACDS);
        elseif PriceType=="high" then
         Ind = core.indicators:create("ELDER_IMPULSE_SYSTEM", bf_data.high, EMA, MACDF, MACDS);
        elseif PriceType=="low" then
         Ind = core.indicators:create("ELDER_IMPULSE_SYSTEM", bf_data.low, EMA, MACDF, MACDS);
        elseif PriceType=="typical" then
         Ind = core.indicators:create("ELDER_IMPULSE_SYSTEM", bf_data.typical, EMA, MACDF, MACDS);
        elseif PriceType=="median" then
         Ind = core.indicators:create("ELDER_IMPULSE_SYSTEM", bf_data.median, EMA, MACDF, MACDS);
        else
         Ind = core.indicators:create("ELDER_IMPULSE_SYSTEM", bf_data.weighted, EMA, MACDF, MACDS);
        end
        return ;
    end

    -- check whether the requested candle is before
    -- the reference collection start
    if (bf_candle < bf_data:date(0)) then
        UP:setBookmark(1, period);
        if loading then
            return ;
        end
        -- shift so the bigger frame data is able to provide us with the stoch data at the first period
        from = math.floor(bf_candle * 86400 - (bf_length * extent) + 0.5) / 86400;
        local nontrading, nontradingend;
        nontrading, nontradingend = core.isnontrading(from, day_offset);
        if nontrading then
            -- if it is non-trading, shift for two days to skip the non-trading periods
            from = math.floor((from - 2) * 86400 - (bf_length * extent) + 0.5) / 86400;
        end
        loading = true;
        loadingFrom = from;
        loadingTo = bf_data:date(0);
        host:execute("extendHistory", 1, bf_data, loadingFrom, loadingTo);
        return ;
    end

    -- check whether the requested candle is after
    -- the reference collection end
    if (not(source:isAlive()) and bf_candle > bf_data:date(bf_data:size() - 1)) then
        UP:setBookmark(1, period);
        if loading then
            return ;
        end
        loading = true;
        loadingFrom = bf_data:date(bf_data:size() - 1);
        loadingTo = bf_candle;
        host:execute("extendHistory", 1, bf_data, loadingFrom, loadingTo);
        return ;
    end

    Ind:update(mode);
    local p;
    p = findDateFast(bf_data, bf_candle, true);
    if p == -1 then
        return ;
    end
    if Ind:getStream(0):hasData(p) then
        UP[period] = Ind:getStream(0)[p];
    end
    if Ind:getStream(1):hasData(p) then
        DOWN[period] = Ind:getStream(1)[p];
    end
    if Ind:getStream(2):hasData(p) then
        NE[period] = Ind:getStream(2)[p];
    end
end

-- the function is called when the async operation is finished
function AsyncOperationFinished(cookie)
    local period;

    pday = nil;
    period = UP:getBookmark(1);

    if (period < 0) then
        period = 0;
    end
    loading = false;
    instance:updateFrom(period);
end

function findDateFast(stream, date, precise)
    local datesec = nil;
    local periodsec = nil;
    local min, max, mid;

    datesec = math.floor(date * 86400 + 0.5)

    min = 0;
    max = stream:size() - 1;

    while true do
        mid = math.floor((min + max) / 2);
        periodsec = math.floor(stream:date(mid) * 86400 + 0.5);
        if datesec == periodsec then
            return mid;
        elseif datesec > periodsec then
            min = mid + 1;
        else
            max = mid - 1;
        end
        if min > max then
            if precise then
                return -1;
            else
                return min - 1;
            end
        end
    end
end
Attachments
BF_Elder_Impulse_System.lua
(8.89 KiB) Downloaded 1178 times
Alexander.Gettinger
FXCodeBase: Confirmed User
 
Posts: 3785
Joined: Wed Mar 31, 2010 9:40 pm
Location: Russia, Omsk

Re: Elder Impulse System

Postby Alexander.Gettinger » Tue Sep 28, 2010 2:31 am

Multitimeframe Elder Impulse System Heat Map:

Elder_Impulse_System_Heat_Map.png


Code: Select all
function AddMvaParam(id, frame, EMA, MACDF, MACDS)
    indicator.parameters:addString("B" .. id, "Time frame for avegage " .. id, "", frame);
    indicator.parameters:setFlag("B" .. id, core.FLAG_PERIODS);
    indicator.parameters:addInteger("EMA" .. id, "EMA " .. id .. "EMA ", "", EMA);
    indicator.parameters:addInteger("MACDF" .. id, "MACDF " .. id .. "MACDF ", "", MACDF);
    indicator.parameters:addInteger("MACDS" .. id, "MACDS " .. id .. "MACDS ", "", MACDS);
end

function Init()
    indicator:name("Multitimeframe Elder Impulse System Heat Map");
    indicator:description("");
    indicator:requiredSource(core.Bar);
    indicator:type(core.Oscillator);

    indicator.parameters:addGroup("Calculation");
    AddMvaParam(1, "H1", 13, 12, 26);
    AddMvaParam(2, "H2", 13, 12, 26);
    AddMvaParam(3, "H4", 13, 12, 26);
    AddMvaParam(4, "H6", 13, 12, 26);
    AddMvaParam(5, "H8", 13, 12, 26);
   
    indicator.parameters:addString("Price", "Price", "", "close");
    indicator.parameters:addStringAlternative("Price", "open", "", "open");
    indicator.parameters:addStringAlternative("Price", "close", "", "close");
    indicator.parameters:addStringAlternative("Price", "high", "", "high");
    indicator.parameters:addStringAlternative("Price", "low", "", "low");
    indicator.parameters:addStringAlternative("Price", "typical", "", "typical");
    indicator.parameters:addStringAlternative("Price", "median", "", "median");
    indicator.parameters:addStringAlternative("Price", "weighted", "", "weighted");
   
    indicator.parameters:addGroup("Display");
    indicator.parameters:addColor("clrUP", "Up color", "", core.rgb(0, 255, 0));
    indicator.parameters:addColor("clrDN", "Down color", "", core.rgb(255, 0, 0));
    indicator.parameters:addColor("clrNE", "Neutral color", "", core.rgb(0, 0, 255));
    indicator.parameters:addColor("clrLBL", "Label color", "", core.COLOR_LABEL);
end

-- list of streams
local streams = {}
-- the indicator source
local source;
local day_offset, week_offset;
local dummy;
local host;
local U = {};
local D = {};
local NE = {};
local L = {};
local Ind = nil;
local PriceType;

function Prepare()
    source = instance.source;
    host = core.host;
    PriceType=instance.parameters.Price;

    day_offset = host:execute("getTradingDayOffset");
    week_offset = host:execute("getTradingWeekOffset");

    CheckBarSize(1);
    CheckBarSize(2);
    CheckBarSize(3);
    CheckBarSize(4);
    CheckBarSize(5);

    local i;
    local name = profile:id() .. "(" .. source:name() .. ",".. PriceType .. ",";
    for i = 1, 5, 1 do
        name = name .. "(" ..
                       instance.parameters:getInteger("EMA" .. i) .. " " .. instance.parameters:getInteger("MACDF" .. i) .. " " .. instance.parameters:getInteger("MACDS" .. i) .. ")";
        L[i] = instance.parameters:getString("B" .. i) .. " " .. instance.parameters:getString("EMA" .. i).. " " .. instance.parameters:getString("MACDF" .. i).. " " .. instance.parameters:getString("MACDS" .. i) .. ")";
    end
    name = name .. ")";
    instance:name(name);
    dummy = instance:addStream("D", core.Line, name .. ".D", "D", instance.parameters.clrLBL, 20);
    dummy:addLevel(0);
    dummy:addLevel(120);
    for i = 1, 5, 1 do
        U[i] = instance:createTextOutput ("U" .. i, "U" .. i, "Wingdings", 10, core.H_Center, core.V_Center, instance.parameters.clrUP, 0);
        D[i] = instance:createTextOutput ("D" .. i, "D" .. i, "Wingdings", 10, core.H_Center, core.V_Center, instance.parameters.clrDN, 0);
        NE[i] = instance:createTextOutput ("NE" .. i, "NE" .. i, "Wingdings", 10, core.H_Center, core.V_Center, instance.parameters.clrNE, 0);
    end
end

function CheckBarSize(id)
    local s, e, s1, e1;
    s, e = core.getcandle(source:barSize(), core.now(), 0, 0);
    s1, e1 = core.getcandle(instance.parameters:getString("B" .. id), core.now(), 0, 0);
    assert ((e - s) <= (e1 - s1), "The chosen time frame must be equal to or bigger than the chart time frame!");
end

function Update(period, mode)
    local i, p, loading;
    -- request for data and create MVA's if they do not exist yet.
    if Ind == nil then
        Ind = {};
        for i = 1, 5, 1 do
            stream = registerStream(i, instance.parameters:getString("B" .. i), instance.parameters:getInteger("EMA" .. i));
            Ind[i] = core.indicators:create("ELDER_IMPULSE_SYSTEM", getPriceStream(stream), instance.parameters:getInteger("EMA" .. i), instance.parameters:getInteger("MACDF" .. i), instance.parameters:getInteger("MACDS" .. i));
        end
    end

    for i = 1, 5, 1 do
        p, loading = getPeriod(i, period);
        if p ~= -1 then
            Ind[i]:update(mode);
            if Ind[i].UP:hasData(p) or Ind[i].DN:hasData(p) or Ind[i].NE:hasData(p) then
             if Ind[i].UP[p]==100 then
              U[i]:set(period, (6 - i) * 20, "\110");
             elseif Ind[i].DN[p]==100 then
              D[i]:set(period, (6 - i) * 20, "\110");
             elseif Ind[i].NE[p]==100 then
              NE[i]:set(period, (6 - i) * 20, "\110");
             end
            end
        end
    end

    if period == source:size() - 1 then
        for i = 1, 5, 1 do
            host:execute("drawLabel", i, source:date(period), (6 - i) * 20, L[i]);
        end
    end
end

function getPriceStream(stream)
    local s = instance.parameters.S;
    return stream;
end

function getPrice(source_)
  if PriceType=="open" then
   return source_.open;
  elseif PriceType=="close" then
   return source_.close;
  elseif PriceType=="high" then
   return source_.high;
  elseif PriceType=="low" then
   return source_.low;
  elseif PriceType=="typical" then
   return source_.typical;
  elseif PriceType=="median" then
   return source_.median;
  elseif PriceType=="weighted" then
   return source_.weighted;
  end
end

-- register stream
-- @param barSize       Stream's bar size
-- @param extent        The size of the required exten
-- @return the stream reference
function registerStream(id, barSize, extent)
    local stream = {};
    local s1, e1, length;
    local from, to;

    s1, e1 = core.getcandle(barSize, core.now(), 0, 0);
    length = math.floor((e1 - s1) * 86400 + 0.5);

    -- the size of the source
    if barSize == source:barSize() then
        stream.data = getPrice(source);
        stream.barSize = barSize;
        stream.external = false;
        stream.length = length;
        stream.loading = false;
        stream.extent = extent;
        stream.loading = false;
    else
        stream.data = nil;
        stream.barSize = barSize;
        stream.external = true;
        stream.length = length;
        stream.loading = false;
        stream.extent = extent;
        local from, dataFrom
        from, dataFrom = getFrom(barSize, length, extent);
        if (source:isAlive()) then
            to = 0;
        else
            t, to = core.getcandle(barSize, source:date(source:size() - 1), day_offset, week_offset);
        end
        stream.loading = true;
        stream.loadingFrom = from;
        stream.dataFrom = dataFrom;
        stream.data = getPrice(host:execute("getHistory", id, source:instrument(), barSize, from, to, source:isBid()));
        setBookmark(0);
    end
    streams[id] = stream;
    return stream.data;
end

function getPeriod(id, period)
    local stream = streams[id];
    assert(stream ~= nil, "Stream is not registered");
    local candle, from, dataFrom, to;
    if stream.external then
        candle = core.getcandle(stream.barSize, source:date(period), day_offset, week_offset);
        if candle < stream.dataFrom then
            setBookmark(period);
            if stream.loading then
                return -1, true;
            end
            from, dataFrom = getFrom(stream.barSize, stream.length, stream.extent);
            stream.loading = true;
            stream.loadingFrom = from;
            stream.dataFrom = dataFrom;
            host:execute("extendHistory", id, stream.data, from, stream.data:date(0));
            return -1, true;
        end

        if (not(source:isAlive()) and candle > stream.data:date(stream.data:size() - 1)) then
            setBookmark(period);
            if stream.loading then
                return -1, true;
            end
            stream.loading = true;
            from = bf_data:date(bf_data:size() - 1);
            to = candle;
            host:execute("extendHistory", id, stream.data, from, to);
        end

        local p;
        p = findDateFast(stream.data, candle, true);
        return p, stream.loading;
    else
        return period;
    end
end

function setBookmark(period)
    local bm;
    bm = dummy:getBookmark(1);
    if bm < 0 then
        bm = period;
    else
        bm = math.min(period, bm);
    end
    dummy:setBookmark(1, bm);

end

-- get the from date for the stream using bar size and extent and taking the non-trading periods
-- into account
function getFrom(barSize, length, extent)
    local from, loadFrom;
    local nontrading, nontradingend;

    from = core.getcandle(barSize, source:date(source:first()), day_offset, week_offset);
    loadFrom = math.floor(from * 86400 - length * extent + 0.5) / 86400;
    nontrading, nontradingend = core.isnontrading(from, day_offset);
    if nontrading then
        -- if it is non-trading, shift for two days to skip the non-trading periods
        loadFrom = math.floor((loadFrom - 2) * 86400 - length * extent + 0.5) / 86400;
    end
    return loadFrom, from;
end

-- the function is called when the async operation is finished
function AsyncOperationFinished(cookie)
    local period;
    local stream = streams[cookie];
    if stream == nil then
        return ;
    end
    stream.loading = false;
    period = dummy:getBookmark(1);
    if (period < 0) then
        period = 0;
    end
    loading = false;
    instance:updateFrom(period);
end


-- find the date in the stream using binary search algo.
function findDateFast(stream, date, precise)
    local datesec = nil;
    local periodsec = nil;
    local min, max, mid;

    datesec = math.floor(date * 86400 + 0.5)

    min = 0;
    max = stream:size() - 1;

    if max < 1 then
        return -1;
    end

    while true do
        mid = math.floor((min + max) / 2);
        periodsec = math.floor(stream:date(mid) * 86400 + 0.5);
        if datesec == periodsec then
            return mid;
        elseif datesec > periodsec then
            min = mid + 1;
        else
            max = mid - 1;
        end
        if min > max then
            if precise then
                return -1;
            else
                return min - 1;
            end
        end
    end
end



Elder_Impulse_System_Heat_Map.lua
(10.73 KiB) Downloaded 1410 times

Elder_Impulse_System_Heat_Map With Alert.lua
(16.26 KiB) Downloaded 552 times

If fime frames, flagged as "Alert", reach the "Alert Trigger Level", the alert will be given.
Alexander.Gettinger
FXCodeBase: Confirmed User
 
Posts: 3785
Joined: Wed Mar 31, 2010 9:40 pm
Location: Russia, Omsk

Re: Elder Impulse System

Postby Pride80 » Mon Oct 04, 2010 12:29 pm

Thank you very much, these are great tools :mrgreen:
Pride80
 
Posts: 6
Joined: Tue Sep 14, 2010 7:02 am

Re: Elder Impulse System

Postby Jigit Jigit » Tue Oct 05, 2010 12:23 pm

Now guys that's exactly what I've been looking for.
Thanks a million.

Do you think it would be possible to add one more timeframe?
I trade using 15min timeframe but I would like to see what is going on at the same time on 15min, 30min, 60min, 2hrs, 3hrs and 4hrs charts.

I've tried to modified your code, but as I am no programmer it was pure guessing. Can someone check it for me (or better still do the whole thing over again just with 6 timeframes), please?

Cheers

Code: Select all

function AddMvaParam(id, frame, EMA, MACDF, MACDS)
    indicator.parameters:addString("B" .. id, "Time frame for avegage " .. id, "", frame);
    indicator.parameters:setFlag("B" .. id, core.FLAG_PERIODS);
    indicator.parameters:addInteger("EMA" .. id, "EMA " .. id .. "EMA ", "", EMA);
    indicator.parameters:addInteger("MACDF" .. id, "MACDF " .. id .. "MACDF ", "", MACDF);
    indicator.parameters:addInteger("MACDS" .. id, "MACDS " .. id .. "MACDS ", "", MACDS);
end

function Init()
    indicator:name("Multitimeframe Elder Impulse System Heat Map");
    indicator:description("");
    indicator:requiredSource(core.Bar);
    indicator:type(core.Oscillator);

    indicator.parameters:addGroup("Calculation");
    AddMvaParam(1, "H1", 13, 12, 26);
    AddMvaParam(2, "H2", 13, 12, 26);
    AddMvaParam(3, "H4", 13, 12, 26);
    AddMvaParam(4, "H6", 13, 12, 26);
    AddMvaParam(5, "H8", 13, 12, 26);
    AddMvaParam(6, "H10", 13, 12, 26);
   
    indicator.parameters:addString("Price", "Price", "", "close");
    indicator.parameters:addStringAlternative("Price", "open", "", "open");
    indicator.parameters:addStringAlternative("Price", "close", "", "close");
    indicator.parameters:addStringAlternative("Price", "high", "", "high");
    indicator.parameters:addStringAlternative("Price", "low", "", "low");
    indicator.parameters:addStringAlternative("Price", "typical", "", "typical");
    indicator.parameters:addStringAlternative("Price", "median", "", "median");
    indicator.parameters:addStringAlternative("Price", "weighted", "", "weighted");
   
    indicator.parameters:addGroup("Display");
    indicator.parameters:addColor("clrUP", "Up color", "", core.rgb(0, 255, 0));
    indicator.parameters:addColor("clrDN", "Down color", "", core.rgb(255, 0, 0));
    indicator.parameters:addColor("clrNE", "Neutral color", "", core.rgb(0, 0, 255));
    indicator.parameters:addColor("clrLBL", "Label color", "", core.COLOR_LABEL);
end

-- list of streams
local streams = {}
-- the indicator source
local source;
local day_offset, week_offset;
local dummy;
local host;
local U = {};
local D = {};
local NE = {};
local L = {};
local Ind = nil;
local PriceType;

function Prepare()
    source = instance.source;
    host = core.host;
    PriceType=instance.parameters.Price;

    day_offset = host:execute("getTradingDayOffset");
    week_offset = host:execute("getTradingWeekOffset");

    CheckBarSize(1);
    CheckBarSize(2);
    CheckBarSize(3);
    CheckBarSize(4);
    CheckBarSize(5);
    CheckBarSize(5);

    local i;
    local name = profile:id() .. "(" .. source:name() .. ",".. PriceType .. ",";
    for i = 1, 6, 1 do
        name = name .. "(" ..
                       instance.parameters:getInteger("EMA" .. i) .. " " .. instance.parameters:getInteger("MACDF" .. i) .. " " .. instance.parameters:getInteger("MACDS" .. i) .. ")";
        L[i] = instance.parameters:getString("B" .. i) .. " " .. instance.parameters:getString("EMA" .. i).. " " .. instance.parameters:getString("MACDF" .. i).. " " .. instance.parameters:getString("MACDS" .. i) .. ")";
    end
    name = name .. ")";
    instance:name(name);
    dummy = instance:addStream("D", core.Line, name .. ".D", "D", instance.parameters.clrLBL, 20);
    dummy:addLevel(0);
    dummy:addLevel(120);
    for i = 1, 6, 1 do
        U[i] = instance:createTextOutput ("U" .. i, "U" .. i, "Wingdings", 10, core.H_Center, core.V_Center, instance.parameters.clrUP, 0);
        D[i] = instance:createTextOutput ("D" .. i, "D" .. i, "Wingdings", 10, core.H_Center, core.V_Center, instance.parameters.clrDN, 0);
        NE[i] = instance:createTextOutput ("NE" .. i, "NE" .. i, "Wingdings", 10, core.H_Center, core.V_Center, instance.parameters.clrNE, 0);
    end
end

function CheckBarSize(id)
    local s, e, s1, e1;
    s, e = core.getcandle(source:barSize(), core.now(), 0, 0);
    s1, e1 = core.getcandle(instance.parameters:getString("B" .. id), core.now(), 0, 0);
    assert ((e - s) <= (e1 - s1), "The chosen time frame must be equal to or bigger than the chart time frame!");
end

function Update(period, mode)
    local i, p, loading;
    -- request for data and create MVA's if they do not exist yet.
    if Ind == nil then
        Ind = {};
        for i = 1, 6, 1 do
            stream = registerStream(i, instance.parameters:getString("B" .. i), instance.parameters:getInteger("EMA" .. i));
            Ind[i] = core.indicators:create("ELDER_IMPULSE_SYSTEM", getPriceStream(stream), instance.parameters:getInteger("EMA" .. i), instance.parameters:getInteger("MACDF" .. i), instance.parameters:getInteger("MACDS" .. i));
        end
    end

    for i = 1, 6, 1 do
        p, loading = getPeriod(i, period);
        if p ~= -1 then
            Ind[i]:update(mode);
            if Ind[i].UP:hasData(p) or Ind[i].DN:hasData(p) or Ind[i].NE:hasData(p) then
             if Ind[i].UP[p]==100 then
              U[i]:set(period, (6 - i) * 20, "\110");
             elseif Ind[i].DN[p]==100 then
              D[i]:set(period, (6 - i) * 20, "\110");
             elseif Ind[i].NE[p]==100 then
              NE[i]:set(period, (6 - i) * 20, "\110");
             end
            end
        end
    end

    if period == source:size() - 1 then
        for i = 1, 6, 1 do
            host:execute("drawLabel", i, source:date(period), (6 - i) * 20, L[i]);
        end
    end
end

function getPriceStream(stream)
    local s = instance.parameters.S;
    return stream;
end

function getPrice(source_)
  if PriceType=="open" then
   return source_.open;
  elseif PriceType=="close" then
   return source_.close;
  elseif PriceType=="high" then
   return source_.high;
  elseif PriceType=="low" then
   return source_.low;
  elseif PriceType=="typical" then
   return source_.typical;
  elseif PriceType=="median" then
   return source_.median;
  elseif PriceType=="weighted" then
   return source_.weighted;
  end
end

-- register stream
-- @param barSize       Stream's bar size
-- @param extent        The size of the required exten
-- @return the stream reference
function registerStream(id, barSize, extent)
    local stream = {};
    local s1, e1, length;
    local from, to;

    s1, e1 = core.getcandle(barSize, core.now(), 0, 0);
    length = math.floor((e1 - s1) * 86400 + 0.5);

    -- the size of the source
    if barSize == source:barSize() then
        stream.data = getPrice(source);
        stream.barSize = barSize;
        stream.external = false;
        stream.length = length;
        stream.loading = false;
        stream.extent = extent;
        stream.loading = false;
    else
        stream.data = nil;
        stream.barSize = barSize;
        stream.external = true;
        stream.length = length;
        stream.loading = false;
        stream.extent = extent;
        local from, dataFrom
        from, dataFrom = getFrom(barSize, length, extent);
        if (source:isAlive()) then
            to = 0;
        else
            t, to = core.getcandle(barSize, source:date(source:size() - 1), day_offset, week_offset);
        end
        stream.loading = true;
        stream.loadingFrom = from;
        stream.dataFrom = dataFrom;
        stream.data = getPrice(host:execute("getHistory", id, source:instrument(), barSize, from, to, source:isBid()));
        setBookmark(0);
    end
    streams[id] = stream;
    return stream.data;
end

function getPeriod(id, period)
    local stream = streams[id];
    assert(stream ~= nil, "Stream is not registered");
    local candle, from, dataFrom, to;
    if stream.external then
        candle = core.getcandle(stream.barSize, source:date(period), day_offset, week_offset);
        if candle < stream.dataFrom then
            setBookmark(period);
            if stream.loading then
                return -1, true;
            end
            from, dataFrom = getFrom(stream.barSize, stream.length, stream.extent);
            stream.loading = true;
            stream.loadingFrom = from;
            stream.dataFrom = dataFrom;
            host:execute("extendHistory", id, stream.data, from, stream.data:date(0));
            return -1, true;
        end

        if (not(source:isAlive()) and candle > stream.data:date(stream.data:size() - 1)) then
            setBookmark(period);
            if stream.loading then
                return -1, true;
            end
            stream.loading = true;
            from = bf_data:date(bf_data:size() - 1);
            to = candle;
            host:execute("extendHistory", id, stream.data, from, to);
        end

        local p;
        p = findDateFast(stream.data, candle, true);
        return p, stream.loading;
    else
        return period;
    end
end

function setBookmark(period)
    local bm;
    bm = dummy:getBookmark(1);
    if bm < 0 then
        bm = period;
    else
        bm = math.min(period, bm);
    end
    dummy:setBookmark(1, bm);

end

-- get the from date for the stream using bar size and extent and taking the non-trading periods
-- into account
function getFrom(barSize, length, extent)
    local from, loadFrom;
    local nontrading, nontradingend;

    from = core.getcandle(barSize, source:date(source:first()), day_offset, week_offset);
    loadFrom = math.floor(from * 86400 - length * extent + 0.5) / 86400;
    nontrading, nontradingend = core.isnontrading(from, day_offset);
    if nontrading then
        -- if it is non-trading, shift for two days to skip the non-trading periods
        loadFrom = math.floor((loadFrom - 2) * 86400 - length * extent + 0.5) / 86400;
    end
    return loadFrom, from;
end

-- the function is called when the async operation is finished
function AsyncOperationFinished(cookie)
    local period;
    local stream = streams[cookie];
    if stream == nil then
        return ;
    end
    stream.loading = false;
    period = dummy:getBookmark(1);
    if (period < 0) then
        period = 0;
    end
    loading = false;
    instance:updateFrom(period);
end


-- find the date in the stream using binary search algo.
function findDateFast(stream, date, precise)
    local datesec = nil;
    local periodsec = nil;
    local min, max, mid;

    datesec = math.floor(date * 86400 + 0.5)

    min = 0;
    max = stream:size() - 1;

    if max < 1 then
        return -1;
    end

    while true do
        mid = math.floor((min + max) / 2);
        periodsec = math.floor(stream:date(mid) * 86400 + 0.5);
        if datesec == periodsec then
            return mid;
        elseif datesec > periodsec then
            min = mid + 1;
        else
            max = mid - 1;
        end
        if min > max then
            if precise then
                return -1;
            else
                return min - 1;
            end
        end
    end
end

Jigit Jigit
 
Posts: 54
Joined: Tue Aug 31, 2010 1:04 pm

Re: Elder Impulse System

Postby Apprentice » Tue Oct 05, 2010 2:02 pm

Something like this.
MTF.lua
(9.28 KiB) Downloaded 1229 times

While developing this indicator, I found a bug in the original indicator.
This version inherited this problem.
User avatar
Apprentice
FXCodeBase: Confirmed User
 
Posts: 26559
Joined: Thu Dec 31, 2009 11:59 am
Location: Zagreb, Croatia

Re: Elder Impulse System

Postby Jigit Jigit » Wed Oct 06, 2010 12:49 am

Thanks a million Apprentice.
You're the man.
Jigit Jigit
 
Posts: 54
Joined: Tue Aug 31, 2010 1:04 pm

Re: Elder Impulse System

Postby Jigit Jigit » Wed Oct 06, 2010 1:23 am

Oh, just one more thing.
The label makes the indicator somewhat illegible (ever so slightly).
Can you, please, let me know how to remove the label
or move it so that it is above and more to the side of the little squares?

Cheers
Jigit Jigit
 
Posts: 54
Joined: Tue Aug 31, 2010 1:04 pm

Re: Elder Impulse System

Postby Alexander.Gettinger » Thu Oct 07, 2010 3:26 pm

Update for Multitimeframe Elder Impulse System Heat Map.

Code: Select all
function AddMvaParam(id, frame, EMA, MACDF, MACDS)
    indicator.parameters:addString("B" .. id, "Time frame for avegage " .. id, "", frame);
    indicator.parameters:setFlag("B" .. id, core.FLAG_PERIODS);
    indicator.parameters:addInteger("EMA" .. id, "EMA " .. id .. "EMA ", "", EMA);
    indicator.parameters:addInteger("MACDF" .. id, "MACDF " .. id .. "MACDF ", "", MACDF);
    indicator.parameters:addInteger("MACDS" .. id, "MACDS " .. id .. "MACDS ", "", MACDS);
end

function Init()
    indicator:name("Multitimeframe Elder Impulse System Heat Map");
    indicator:description("");
    indicator:requiredSource(core.Bar);
    indicator:type(core.Oscillator);

    indicator.parameters:addGroup("Calculation");
    AddMvaParam(1, "H1", 13, 12, 26);
    AddMvaParam(2, "H2", 13, 12, 26);
    AddMvaParam(3, "H4", 13, 12, 26);
    AddMvaParam(4, "H6", 13, 12, 26);
    AddMvaParam(5, "H8", 13, 12, 26);
   
    indicator.parameters:addString("Price", "Price", "", "close");
    indicator.parameters:addStringAlternative("Price", "open", "", "open");
    indicator.parameters:addStringAlternative("Price", "close", "", "close");
    indicator.parameters:addStringAlternative("Price", "high", "", "high");
    indicator.parameters:addStringAlternative("Price", "low", "", "low");
    indicator.parameters:addStringAlternative("Price", "typical", "", "typical");
    indicator.parameters:addStringAlternative("Price", "median", "", "median");
    indicator.parameters:addStringAlternative("Price", "weighted", "", "weighted");
   
    indicator.parameters:addGroup("Display");
    indicator.parameters:addColor("clrUP", "Up color", "", core.rgb(0, 255, 0));
    indicator.parameters:addColor("clrDN", "Down color", "", core.rgb(255, 0, 0));
    indicator.parameters:addColor("clrNE", "Neutral color", "", core.rgb(0, 0, 255));
    indicator.parameters:addColor("clrLBL", "Label color", "", core.COLOR_LABEL);
end

-- list of streams
local streams = {}
-- the indicator source
local source;
local day_offset, week_offset;
local dummy;
local host;
local U = {};
local D = {};
local NE = {};
local L = {};
local Ind = nil;
local PriceType;

function Prepare()
    source = instance.source;
    host = core.host;
    PriceType=instance.parameters.Price;

    day_offset = host:execute("getTradingDayOffset");
    week_offset = host:execute("getTradingWeekOffset");

    CheckBarSize(1);
    CheckBarSize(2);
    CheckBarSize(3);
    CheckBarSize(4);
    CheckBarSize(5);

    local i;
    local name = profile:id() .. "(" .. source:name() .. ",".. PriceType .. ",";
    for i = 1, 5, 1 do
        name = name .. "(" ..
                       instance.parameters:getInteger("EMA" .. i) .. " " .. instance.parameters:getInteger("MACDF" .. i) .. " " .. instance.parameters:getInteger("MACDS" .. i) .. ")";
        L[i] = instance.parameters:getString("B" .. i) .. " " .. instance.parameters:getString("EMA" .. i).. " " .. instance.parameters:getString("MACDF" .. i).. " " .. instance.parameters:getString("MACDS" .. i) .. ")";
    end
    name = name .. ")";
    instance:name(name);
    dummy = instance:addStream("D", core.Line, name .. ".D", "D", instance.parameters.clrLBL, 20);
    dummy:addLevel(0);
    dummy:addLevel(120);
    for i = 1, 5, 1 do
        U[i] = instance:createTextOutput ("U" .. i, "U" .. i, "Wingdings", 10, core.H_Center, core.V_Center, instance.parameters.clrUP, 0);
        D[i] = instance:createTextOutput ("D" .. i, "D" .. i, "Wingdings", 10, core.H_Center, core.V_Center, instance.parameters.clrDN, 0);
        NE[i] = instance:createTextOutput ("NE" .. i, "NE" .. i, "Wingdings", 10, core.H_Center, core.V_Center, instance.parameters.clrNE, 0);
    end
end

function CheckBarSize(id)
    local s, e, s1, e1;
    s, e = core.getcandle(source:barSize(), core.now(), 0, 0);
    s1, e1 = core.getcandle(instance.parameters:getString("B" .. id), core.now(), 0, 0);
    assert ((e - s) <= (e1 - s1), "The chosen time frame must be equal to or bigger than the chart time frame!");
end

function Update(period, mode)
    local i, p, loading;
    -- request for data and create MVA's if they do not exist yet.
    if Ind == nil then
        Ind = {};
        for i = 1, 5, 1 do
            stream = registerStream(i, instance.parameters:getString("B" .. i), instance.parameters:getInteger("EMA" .. i));
            Ind[i] = core.indicators:create("ELDER_IMPULSE_SYSTEM", getPrice(getPriceStream(stream)), instance.parameters:getInteger("EMA" .. i), instance.parameters:getInteger("MACDF" .. i), instance.parameters:getInteger("MACDS" .. i));
        end
    end

    for i = 1, 5, 1 do
        p, loading = getPeriod(i, period);
        if p ~= -1 then
            Ind[i]:update(mode);
            if Ind[i].UP:hasData(p) or Ind[i].DN:hasData(p) or Ind[i].NE:hasData(p) then
             if Ind[i].UP[p]==100 then
              U[i]:set(period, (6 - i) * 20, "\110");
             elseif Ind[i].DN[p]==100 then
              D[i]:set(period, (6 - i) * 20, "\110");
             elseif Ind[i].NE[p]==100 then
              NE[i]:set(period, (6 - i) * 20, "\110");
             end
            end
        end
    end

    if period == source:size() - 1 then
        for i = 1, 5, 1 do
            host:execute("drawLabel", i, source:date(period), (6 - i) * 20, L[i]);
        end
    end
end

function getPriceStream(stream)
    local s = instance.parameters.S;
    return stream;
end

function getPrice(source_)
  if PriceType=="open" then
   return source_.open;
  elseif PriceType=="close" then
   return source_.close;
  elseif PriceType=="high" then
   return source_.high;
  elseif PriceType=="low" then
   return source_.low;
  elseif PriceType=="typical" then
   return source_.typical;
  elseif PriceType=="median" then
   return source_.median;
  elseif PriceType=="weighted" then
   return source_.weighted;
  end
end

-- register stream
-- @param barSize       Stream's bar size
-- @param extent        The size of the required exten
-- @return the stream reference
function registerStream(id, barSize, extent)
    local stream = {};
    local s1, e1, length;
    local from, to;

    s1, e1 = core.getcandle(barSize, core.now(), 0, 0);
    length = math.floor((e1 - s1) * 86400 + 0.5);

    -- the size of the source
    if barSize == source:barSize() then
        stream.data = source;
        stream.barSize = barSize;
        stream.external = false;
        stream.length = length;
        stream.loading = false;
        stream.extent = extent;
        stream.loading = false;
    else
        stream.data = nil;
        stream.barSize = barSize;
        stream.external = true;
        stream.length = length;
        stream.loading = false;
        stream.extent = extent;
        local from, dataFrom
        from, dataFrom = getFrom(barSize, length, extent);
        if (source:isAlive()) then
            to = 0;
        else
            t, to = core.getcandle(barSize, source:date(source:size() - 1), day_offset, week_offset);
        end
        stream.loading = true;
        stream.loadingFrom = from;
        stream.dataFrom = dataFrom;
        stream.data = host:execute("getHistory", id, source:instrument(), barSize, from, to, source:isBid());
        setBookmark(0);
    end
    streams[id] = stream;
    return stream.data;
end

function getPeriod(id, period)
    local stream = streams[id];
    assert(stream ~= nil, "Stream is not registered");
    local candle, from, dataFrom, to;
    if stream.external then
        candle = core.getcandle(stream.barSize, source:date(period), day_offset, week_offset);
        if candle < stream.dataFrom then
            setBookmark(period);
            if stream.loading then
                return -1, true;
            end
            from, dataFrom = getFrom(stream.barSize, stream.length, stream.extent);
            stream.loading = true;
            stream.loadingFrom = from;
            stream.dataFrom = dataFrom;
            host:execute("extendHistory", id, stream.data, from, stream.data:date(0));
            return -1, true;
        end

        if (not(source:isAlive()) and candle > stream.data:date(stream.data:size() - 1)) then
            setBookmark(period);
            if stream.loading then
                return -1, true;
            end
            stream.loading = true;
            from = bf_data:date(bf_data:size() - 1);
            to = candle;
            host:execute("extendHistory", id, stream.data, from, to);
        end

        local p;
        p = findDateFast(stream.data, candle, true);
        return p, stream.loading;
    else
        return period;
    end
end

function setBookmark(period)
    local bm;
    bm = dummy:getBookmark(1);
    if bm < 0 then
        bm = period;
    else
        bm = math.min(period, bm);
    end
    dummy:setBookmark(1, bm);

end

-- get the from date for the stream using bar size and extent and taking the non-trading periods
-- into account
function getFrom(barSize, length, extent)
    local from, loadFrom;
    local nontrading, nontradingend;

    from = core.getcandle(barSize, source:date(source:first()), day_offset, week_offset);
    loadFrom = math.floor(from * 86400 - length * extent + 0.5) / 86400;
    nontrading, nontradingend = core.isnontrading(from, day_offset);
    if nontrading then
        -- if it is non-trading, shift for two days to skip the non-trading periods
        loadFrom = math.floor((loadFrom - 2) * 86400 - length * extent + 0.5) / 86400;
    end
    return loadFrom, from;
end

-- the function is called when the async operation is finished
function AsyncOperationFinished(cookie)
    local period;
    local stream = streams[cookie];
    if stream == nil then
        return ;
    end
    stream.loading = false;
    period = dummy:getBookmark(1);
    if (period < 0) then
        period = 0;
    end
    loading = false;
    instance:updateFrom(period);
end


-- find the date in the stream using binary search algo.
function findDateFast(stream, date, precise)
    local datesec = nil;
    local periodsec = nil;
    local min, max, mid;

    datesec = math.floor(date * 86400 + 0.5)

    min = 0;
    max = stream:size() - 1;

    if max < 1 then
        return -1;
    end

    while true do
        mid = math.floor((min + max) / 2);
        periodsec = math.floor(stream:date(mid) * 86400 + 0.5);
        if datesec == periodsec then
            return mid;
        elseif datesec > periodsec then
            min = mid + 1;
        else
            max = mid - 1;
        end
        if min > max then
            if precise then
                return -1;
            else
                return min - 1;
            end
        end
    end
end

Attachments
Elder_Impulse_System_Heat_Map.lua
(10.72 KiB) Downloaded 1267 times
Alexander.Gettinger
FXCodeBase: Confirmed User
 
Posts: 3785
Joined: Wed Mar 31, 2010 9:40 pm
Location: Russia, Omsk

Next

Return to Custom Indicators

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 15 guests