Here is an updated version of the test indicator used in the first post in this thread. This one is updated and it works fine in the current TS2 with SDK 2. Like the first one it's not a real indicator; it just illustrates the getSyncHistory method used to create a basket of currency streams to make an indicator from.
In the beta TS2 for SDK 3 this stops on the last getSyncHistory term with the error "Incorrect Instrument selected". The debugger isn't much use here because I need to load five or six currency streams, and I'm not sure if getSyncHistory is understood by the debugger anyway.
I tried setting a trace but since the indicator never gets out the Prepare function it never displays. I tried writing the length of basket_array and it's contents to a file, but this version of TS2 or the JIT or something won't let me open a file to write to either (see another thread I opened on this issue).
I have a print operation in this indicator also. It works fine in the current production TS2. If we can get the getSyncHistory to work maybe we can see about getting the file operations to work also.
- Code: Select all
function Init()
indicator:name("BSKT");
indicator:description("Index of a basket including this pair.");
indicator:requiredSource(core.Bar);
indicator:type(core.Indicator);
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");
indicator.parameters:addBoolean("Print", "Print", "Output file for strategy.", false);
indicator.parameters:addInteger("Periods", "Periods", "Number of periods to print.", 19, 1, 200);
indicator.parameters:addColor("clr", "BSKT color", "", core.rgb(0, 0, 255));
indicator.parameters:addColor("clrA", "Ascending color", "", core.COLOR_UPCANDLE);
indicator.parameters:addColor("clrD", "Descending color", "", core.COLOR_DOWNCANDLE);
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
local n;
function Prepare()
source = instance.source;
n = instance.parameters.Periods;
first = source:first() + n + 1;
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
for i = 1, #basket_array do
if i == 1 then
if first < source1:first() + n + 1 then
first = source1:first() + n + 1;
end
end
if i == 2 then
if first < source2:first() + n + 1 then
first = source2:first() + n + 1;
end
end
if i == 3 then
if first < source3:first() + n + 1 then
first = source3:first() + n + 1;
end
end
if i == 4 then
if first < source4:first() + n + 1 then
first = source4:first() + n + 1;
end
end
if i == 5 then
if first < source5:first() + n + 1 then
first = source5:first() + n + 1;
end
end
end
if period > first then
open[period] = 0;
high[period] = 0;
low[period] = 0;
close[period] = 0;
local date = source:date(period);
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
if open[period] < close[period] then
open:setColor(period, instance.parameters.clrA);
else
open:setColor(period, instance.parameters.clrD);
end
if instance.parameters.Print and
period > first then
local date;
local xdate;
local c = io.open("C:/data/" .. basket .. "_" .. source:barSize() .. "_bskt_test.csv", "w+");
local x = 1;
local last_price = {};
for i = n, 0, -1 do
local time = core.dateToTable(source:date(period - i));
local year = string.format("%i", time.year);
local month;
local day;
local hour;
local min;
month = string.format("%i", time.month);
day = string.format("%i", time.day);
hour = string.format("%i", time.hour);
if time.min < 10 then
min = "0" .. string.format("%i", time.min);
else
min = string.format("%i", time.min);
end
date = month .. "/" .. day .. "/" .. year .." " .. hour .. ":" .. min;
xdate = month .. "/" .. day .. " " .. hour .. ":" .. min;
if time.min < 5 and
(time.hour == 1 or
time.hour == 5 or
time.hour == 9 or
time.hour == 13 or
time.hour == 17 or
time.hour == 21) then
c:write(date .. "," .. open[period - i] .. "," .. high[period - i] .. "," .. low[period - i] .. "," .. close[period - i] .. "," .. xdate .. "," .. x .. "\n");
x = x + 1;
else
c:write(date .. "," .. open[period - i] .. "," .. high[period - i] .. "," .. low[period - i] .. "," .. close[period - i] .. ",," .. x .. "\n");
x = x + 1;
end
last_price = {};
table.insert(last_price, #last_price + 1, date);
table.insert(last_price, #last_price + 1, open[period - i]);
table.insert(last_price, #last_price + 1, high[period - i]);
table.insert(last_price, #last_price + 1, low[period - i]);
table.insert(last_price, #last_price + 1, close[period - i]);
end
c:close();
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