Page 1 of 1

Problems with latest version

PostPosted: Thu Oct 10, 2013 8:58 am
by robocod
I have a problem with one of my indicators and the latest version of MarketScope. It worked fine for the old version.

The indicator overcomes problems of missing gaps, by loading tick data for each session start, so it can determine the correct open/high/low/close.

It's a little bit complex to explain, but basically it uses the getHistory() method to get tick data for the bar containing a "session open" (e.g. new day on DAX CFD). It then extracts the real open/high/low/close from the tick.

Of course, getHistory() is asynchronous, and so the indicator saves the date&time of where it is, so that the updateFrom(period) can be used when returning from the AsyncOperationFinished() method. All was working fine.

However, in the latest version, I find that indicator:update() is called again with period = 0 which seems totally erroneous.

For example, I can see from debug trace that I get something like this...

period = 0, first call
period = 100, loaded tick data for 8/10/13
period = 200, loaded tick data for 9/10/13
period = 300, loaded tick data for 10/10/13
period = 0 <<< where / who called this ?
period = 100, loaded tick data for 8/10/13
period = 200, loaded tick data for 9/10/13
period = 300, loaded tick data for 10/10/13
period = 0 <<< where / who called this ?
...
repeats forever

The AsyncOperationFinished did not ask for the update from period 0 again. It seems the indicator framework did it itself.

I have no idea why update is called again starting from period 0. It causes the current code to start again from the start, and so it ends up in an infinite loop, since as soon as it finishes the whole chart it gets update(0) again !

Any ideas?

Is it something to do with the new "owner drawn indicators"? Maybe you added another call to update() in order to do something?

Thanks.

Re: Problems with latest version

PostPosted: Thu Oct 10, 2013 11:07 am
by robocod
Furthermore on this.

It seems that any time I use getHistory() in an indicator, the platform seems to do 2 passes of update() (i.e. update from 0 ..size-1, and then again from 0..size-1).

I checked some other indicators, and verified that this was indeed happening. It means that the data gets processed twice (waste of time and effort and resources).

Normal indicators will get update() called with 0..size-1 and then every new bar from then.
Indicators using getHistory() seem to get update() called 0..size-1, and then again 0..size-1, and then every new bar.

I tried various methods to use a flag to only compute the values on the 1st pass or the 2nd pass, but this didn't seem to work as expected.

For the "gap" indicator I solved it by caching the values on the 1st pass, and then using the cached values on the next pass. This seemed to work for that indicator. However, I have other indicators that load data in chunks, and I can't use the same technique there (its impossible to cache all the data).

Please explain why the platform seems to be calling update in 2 passes like this. Is it a bug or a feature? Can I stop it? Can I ignore one of the passes ? Any other ideas?

As I said before, this did not happen with the previous version.

Re: Problems with latest version - 2 bugs

PostPosted: Fri Oct 11, 2013 8:30 am
by robocod
Please see the attached file. This is basically the code from the help file example on getHistory(), with a bit of trace/debug code added. Also, I am using the technique of using the bookmark so that I can go back to the correct period. This also no longer works in the latest version (the bookmark seems disappear). I can work around the bookmark issue by storing the date, and then using findDate(), but since bookmarks are supposed to be the suggested method it should probably work.

code
Code: Select all
function Init()
       indicator:name("Sample oscillator");
       indicator:description(" ");
       indicator:requiredSource(core.Bar);
       indicator:type(core.Oscillator);
 
       indicator.parameters:addString("INST", "The instrument to load", "", "");
       indicator.parameters:setFlag("INST", core.FLAG_INSTRUMENTS);
   end
 
   local source;       -- the indicator source
   local other;        -- the additional data stream
   local loading;      -- flag indicating the other data stream is being loaded
   local load_from;    -- the date/time the data was loaded the last time from
   local instrument;   -- the instrument to be loaded
   local output;       -- the indicator output stream;
   local host;
   local dummy;
 
   function Prepare()
       source = instance.source;
       host = core.host;
 
       instrument = instance.parameters.INST;
       assert(instrument ~= instance.source:instrument(), "Please choose different instrument");
 
       local name;
       name = profile:id() .. "(" .. instrument .. ")";
       instance:name(name);
 
 
       output = instance:addStream("other", core.Line, name, "other", core.rgb(255, 0, 0), source:first());
       
       dummy = instance:addInternalStream(source:first());
   end
 
   function Update(period, mode)
       local from, to;
 
       if period < source:first() then
           return ;
       end
       
        if period == source:first() then
            host:trace(string.format("period == %d, mode = %d", period, mode));
        end
 
       if other == nil then
           -- if the data is not loaded yet at all
           -- load the data
           from = source:date(source:first());   -- oldest data to load
           if source:isAlive() then              -- newest data to load or 0 if the source is "alive"
               to = 0;
           else
               to = source:date(source:size() - 1);
           end
           load_from = from;
           loading = true;
           other = core.host:execute("getHistory", 1, instrument, source:barSize(), from, to, source:isBid());
           return ;
       end
 
       if loading then
           return ;
       end
 
       local curr_date = source:date(period);
       if curr_date < load_from then
           -- if the data we are trying to get is oldest than previously loaded
           -- the extend the history to the oldest data we can request
           from = source:date(source:first());     -- load from the oldest data we have in source
           if other:size() > other:first() then
               to = other:date(other:first());     -- to the oldest data we have in other instrument
           else
               to = load_from;
           end
           load_from = from;
           loading = true;
           core.host:execute("extendHistory", 1, other, from, to);
           dummy:setBookmark(1, period);
           return ;
       end
 
       -- the date is in the loaded range
       -- try to find it
       local other_period = core.findDate(other, curr_date, true);
       if other_period ~= -1 then
           output[period] = other.close[other_period];
       end
   end
 
   function AsyncOperationFinished(cookie, success, message)
       if cookie == 1 then
           loading = false;
           -- update the indicator output when loading is finished
           
            -- Get the bookmarked period
            local period = dummy:getBookmark(1);
            if period == -1 then
                host:trace("Bookmark was not found");
                period = source:first();
            end
           
            host:trace("updating from ".. period);
       
           instance:updateFrom(period);
           return ;
       end
   end


here's the Event log after running (oldest at the bottom)
5: UK100 TEST Trace: 'period == 0, mode = 9'. 11/10/2013 19:17:17
4: UK100 TEST Trace: 'period == 0, mode = 7'. 11/10/2013 19:17:17
3: UK100 TEST Trace: 'updating from 0'. 11/10/2013 19:17:17
2: UK100 TEST Trace: 'Bookmark was not found'. 11/10/2013 19:17:17
1: UK100 TEST Trace: 'period == 0, mode = 9'. 11/10/2013 19:17:15

Line 1 is the first call to the update with period = 0
Line 2 is in the Async function, and the bookmark no longer exists !
Line 3 is in the Async function and we are asking to update from 0
Line 4 is the update() as a result of line 3
Line 5 is totally spurious and un-requested call of update() that seems to occur whenever getHistory was used. WHY? It means the indicator is making 2 passes (you can add debug code and see that this is the case).

This particular indicator still works because:
a) it always starts from 0 anyway. If it it started from say period = 10, then the bookmark method would have failed, and it would have started from 0 again.
b) the getHistory() is only called once, and so after the 2nd pass, the indicator works. In my case I want to call getHistory() again, and since each call to getHistory() seems to cause the spurious call to upate I end up in a loop.

Re: Problems with latest version

PostPosted: Mon Oct 14, 2013 3:39 am
by Valeria
Hi robocod,

Thank you for the report, we will fix the issue in the future release of Trading Station.
Unfortunately, currently there is no workaround. You shouldn't ignore the second call of update all. It can be due to the reconnect, options change, update chart command, indicator parameters change, additional historical data load on the chart (when a user scrolls the chart into the past).
Try to remember the dates of the requested history and do not request the history in the exactly same range in the second time.