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