Problems with using multiple price sources
Posted: Thu Sep 11, 2014 9:15 am
I have been working on indicators using multiple price sources, and I've been using getHistory and getSyncHistory to get all the data. Many times the last six bars or so of the indicator are skewed because not all of the price sources have data. Sometimes, though, it works just fine. To me this looks like a bug. Here is an example of the code I am using (this doesn't actually do much of anything, but on my system it displays the error):
I have also attached a picture of the output with GBP/NZD, GBP/AUD, GBP/CAD, EUR/GBP, GBP/JPY, and GBP/USD currencies used as inputs.
- Code: Select all
function Init()
indicator:name("BSKT");
indicator:description("Index of a basket including this pair.");
indicator:requiredSource(core.Bar);
indicator:type(core.Oscillator);
indicator:setTag("group", "Trend");
--indicator:setTag("replaceSource", "t");
indicator.parameters:addGroup("Basket");
indicator.parameters:addString("BC", "Base, or Counter", "Base (1st) or counter (2nd) currency.", "base");
indicator.parameters:addStringAlternative("BC", "base", "", "base");
indicator.parameters:addStringAlternative("BC", "counter", "", "counter");
end
local first;
local source = nil;
local source1 = nil;
local source2 = nil;
local source3 = nil;
local source4 = nil;
local source5 = nil;
local loading1 = false;
local loading2 = false;
local loading3 = false;
local loading4 = false;
local loading5 = false;
local basket;
local basket_array = {};
local open, high, low, close; --candle elements, open high, low,close
function Prepare()
source = instance.source;
first = source:first();
if instance.parameters.BC == "base" then
basket = string.match(source:instrument(), "(%u*)/%u*");
elseif instance.parameters.BC == "counter" then
basket = string.match(source:instrument(), "%u*/(%u*)");
end
local name = profile:id() .. "(" .. basket .. ")";
instance:name(name);
local enum, row;
enum = core.host:findTable("Offers"):enumerator();
while true do
row = enum:next();
if row == nil or
row == NULL then
break;
end
if row.Instrument ~= source:instrument() then
if basket == string.match(row.Instrument, "(%u*)/%u*") then
table.insert(basket_array, #basket_array + 1, row.Instrument);
elseif basket == string.match(row.Instrument, "%u*/(%u*)") then
table.insert(basket_array, #basket_array + 1, row.Instrument);
end
end
end
for i = 1, #basket_array do
if i == 1 then
source1 = core.host:execute("getSyncHistory", basket_array[1], source:barSize(), source:isBid(), 0, 1, 11);
end
if i == 2 then
source2 = core.host:execute("getSyncHistory", basket_array[2], source:barSize(), source:isBid(), 0, 2, 12);
end
if i == 3 then
source3 = core.host:execute("getSyncHistory", basket_array[3], source:barSize(), source:isBid(), 0, 3, 13);
end
if i == 4 then
source4 = core.host:execute("getSyncHistory", basket_array[4], source:barSize(), source:isBid(), 0, 4, 14);
end
if i == 5 then
source5 = core.host:execute("getSyncHistory", basket_array[5], source:barSize(), source:isBid(), 0, 5, 15);
end
end
open = instance:addStream("OPEN", core.Line, name .. ".OPEN", "OPEN", core.rgb(255,0,0), 0);
high = instance:addStream("HIGH", core.Line, name .. ".HIGH", "HIGH", core.rgb(255,0,0), 0);
low = instance:addStream("LOW", core.Line, name .. ".LOW", "LOW", core.rgb(255,0,0), 0);
close = instance:addStream("CLOSE", core.Line, name .. ".CLOSE", "CLOSE", core.rgb(255,0,0), 0);
instance:createCandleGroup(name, "BSKT", open, high, low, close);
end
-- Indicator calculation routine
function Update(period, mode)
if loading1 or
loading2 or
loading3 or
loading4 or
loading5 then
return;
end
open[period] = 0;
high[period] = 0;
low[period] = 0;
close[period] = 0;
if basket == string.match(source:instrument(), "(%u*)/%u*") then
open[period] = open[period] + source.open[period];
high[period] = high[period] + source.high[period];
low[period] = low[period] + source.low[period];
close[period] = close[period] + source.close[period];
elseif basket == string.match(source:instrument(), "%u*/(%u*)") then
open[period] = open[period] - source.open[period];
high[period] = high[period] - source.high[period];
low[period] = low[period] - source.low[period];
close[period] = close[period] - source.close[period];
end
for i = 1, #basket_array do
if i == 1 then
if not source1:hasData(period) then
core.host:trace("No data for " .. basket_array[i] .. " at period " .. period .. ".\n");
return;
end
if basket == string.match(basket_array[1], "(%u*)/%u*") then
open[period] = open[period] + source1.open[period];
high[period] = high[period] + source1.high[period];
low[period] = low[period] + source1.low[period];
close[period] = close[period] + source1.close[period];
elseif basket == string.match(basket_array[1], "%u*/(%u*)") then
open[period] = open[period] - source1.open[period];
high[period] = high[period] - source1.high[period];
low[period] = low[period] - source1.low[period];
close[period] = close[period] - source1.close[period];
end
elseif i == 2 then
if not source2:hasData(period) then
core.host:trace("No data for " .. basket_array[i] .. " at period " .. period .. ".\n");
return;
end
if basket == string.match(basket_array[2], "(%u*)/%u*") then
open[period] = open[period] + source2.open[period];
high[period] = high[period] + source2.high[period];
low[period] = low[period] + source2.low[period];
close[period] = close[period] + source2.close[period];
elseif basket == string.match(basket_array[2], "%u*/(%u*)") then
open[period] = open[period] - source2.open[period];
high[period] = high[period] - source2.high[period];
low[period] = low[period] - source2.low[period];
close[period] = close[period] - source2.close[period];
end
elseif i == 3 then
if not source3:hasData(period) then
core.host:trace("No data for " .. basket_array[i] .. " at period " .. period .. ".\n");
return;
end
if basket == string.match(basket_array[3], "(%u*)/%u*") then
open[period] = open[period] + source3.open[period];
high[period] = high[period] + source3.high[period];
low[period] = low[period] + source3.low[period];
close[period] = close[period] + source3.close[period];
elseif basket == string.match(basket_array[3], "%u*/(%u*)") then
open[period] = open[period] - source3.open[period];
high[period] = high[period] - source3.high[period];
low[period] = low[period] - source3.low[period];
close[period] = close[period] - source3.close[period];
end
elseif i == 4 then
if not source4:hasData(period) then
core.host:trace("No data for " .. basket_array[i] .. " at period " .. period .. ".\n");
return;
end
if basket == string.match(basket_array[4], "(%u*)/%u*") then
open[period] = open[period] + source4.open[period];
high[period] = high[period] + source4.high[period];
low[period] = low[period] + source4.low[period];
close[period] = close[period] + source4.close[period];
elseif basket == string.match(basket_array[4], "%u*/(%u*)") then
open[period] = open[period] - source4.open[period];
high[period] = high[period] - source4.high[period];
low[period] = low[period] - source4.low[period];
close[period] = close[period] - source4.close[period];
end
elseif i == 5 then
if not source5:hasData(period) then
core.host:trace("No data for " .. basket_array[i] .. " at period " .. period .. ".\n");
return;
end
if basket == string.match(basket_array[5], "(%u*)/%u*") then
open[period] = open[period] + source5.open[period];
high[period] = high[period] + source5.high[period];
low[period] = low[period] + source5.low[period];
close[period] = close[period] + source5.close[period];
elseif basket == string.match(basket_array[5], "%u*/(%u*)") then
open[period] = open[period] - source5.open[period];
high[period] = high[period] - source5.high[period];
low[period] = low[period] - source5.low[period];
close[period] = close[period] - source5.close[period];
end
end
end
end
function AsyncOperationFinished(cookie, success, message)
for i = 1, #basket_array do
if cookie == 1 then
if success then
loading1 = false;
end
end
if cookie == 2 then
if success then
loading2 = false;
end
end
if cookie == 3 then
if success then
loading3 = false;
end
end
if cookie == 4 then
if success then
loading4 = false;
end
end
if cookie == 5 then
if success then
loading5 = false;
end
end
end
for i = 1, #basket_array do
if cookie == 11 then
if success then
loading1 = true;
end
end
if cookie == 12 then
if success then
loading2 = true;
end
end
if cookie == 13 then
if success then
loading3 = true;
end
end
if cookie == 14 then
if success then
loading4 = true;
end
end
if cookie == 15 then
if success then
loading5 = true;
end
end
end
if not loading1 and
not loading2 and
not loading3 and
not loading4 and
not loading5 then
instance:updateFrom(0);
end
end
I have also attached a picture of the output with GBP/NZD, GBP/AUD, GBP/CAD, EUR/GBP, GBP/JPY, and GBP/USD currencies used as inputs.