Where to place Update(period) in pivot.lua

Moderator: admin

Where to place Update(period) in pivot.lua

Postby LordTwig » Tue Apr 27, 2010 11:02 am

Hiya,
Need some help here.
Can you please indicate where to correctly place this code below in the indicator pivot.lua so as I can get and use the correct data (periods) to use on calculations. so that it will be displayed/stream correctly in current periods with the Pivot Point in the pivot.lua indicator.

I have finished my indicator and it works perfectly barring the incorrect pivots from Gideons indicator. So I am converting mine into the pivot.lua for use of correct pivots.
BTW... mine is an oscillator so I stripped out unneeded parmeters in pivot.lua and changed output streams to internal streams....to convert to oscillator it works so far.

Indicator calculation routine
function Update(period)
if period >= first and source:hasData(period) then

High = source.high[period]; -- gets the high of the period/bar
low = source.low[period]; -- gets the low of the period/bar
open = source.open[period]; -- gets the open of the period/bar
close = source.close[period]; -- gets the close of the period/bar

local dif = close - open;
local difHL = high - low;

if difHL > pips then
if dif >= 0 then
destStream[period] = 1;
else
destStream[period] = -1;
end
else
destStream[period] = 0;
end
end

end
-- ends function update .......where would this end be placed in the pivot indicator ????

Can you help me out in where to actually place/position it as everywhere I have tried doesn't work?

Cheers
LordTwig
Cheers
LordTwig
LordTwig
FXCodeBase: Confirmed User
 
Posts: 157
Joined: Fri Mar 12, 2010 3:15 am

Re: Where to place Update(period) in pivot.lua

Postby Nikolay.Gekht » Wed Apr 28, 2010 9:48 am

Looks like there is no way to reuse the indicators which manages the data by themselves. The problem is that pivot:update just starts data loading, so your indicator just does not know how when this loading is finished and indicator's data is available. In the current situation I can see only one way - to implement the data loading and management right in your indicator. This is correct to all indicators which uses other timeframes. I'll prepare an example (or better a template) for such indicator soon. Will try to do it right today.
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1235
Joined: Wed Dec 16, 2009 6:39 pm
Location: Cary, NC

Re: Where to place Update(period) in pivot.lua

Postby LordTwig » Thu Apr 29, 2010 2:02 am

Hmmm.....no wonder I can't do it! I am always looking 'out of the box' with things, and it seems everything is hard in doing so.

That would be great if you can create that 'template' asap, Nikolay.

It needs to be an Oscillator (or I will have to convert it)
Be able to use pivot point data (day) at minimum in calculations.

be able to get these;

High = source.high[period]; -- gets the high of the period/bar
low = source.low[period]; -- gets the low of the period/bar
open = source.open[period]; -- gets the open of the period/bar
close = source.close[period]; -- gets the close of the period/bar

and do calculations........

and finally stream results correctly to chart......

Thanks
LordTwig
Cheers
LordTwig
LordTwig
FXCodeBase: Confirmed User
 
Posts: 157
Joined: Fri Mar 12, 2010 3:15 am

Re: Where to place Update(period) in pivot.lua

Postby Nikolay.Gekht » Thu Apr 29, 2010 4:45 pm

I've played with the task and found that even I can't re-use pivot via indicators. :-) There is just no connection point to know when the pivot has completed data loading and finished recalculation.

So, I can propose the following approach. Just re-use the pivot code instead of creating pivot via core.indicators.

There is the template of the code which calculates very simple oscillator - the distance of the close price to the R1 and S1 levels of the pivot.

I marked all places where you can put your own code (declaring parameters, initialization, calculation). Just access the pivot data via P, R1, R2, R3, R4 and S1, S2, S3, S4 streams.

Code: Select all
function Init()
    indicator:name("Sample Pivot-based oscillator");
    indicator:description("Developed exclusively to show on how to use the pivot as the base of the custom indicator");
    indicator:requiredSource(core.Bar);
    indicator:type(core.Oscillator);

    -- TODO: Add your parameter here

    -- pivot parames
    indicator.parameters:addString("BS", "Timeframe", "", "D1");
    indicator.parameters:setFlag("BS", core.FLAG_PERIODS);
    indicator.parameters:addString("CalcMode", "Pivot mode", "", "Pivot");
    indicator.parameters:addStringAlternative("CalcMode", "Classic", "", "Pivot");
    indicator.parameters:addStringAlternative("CalcMode", "Camarilla", "", "Camarilla");
    indicator.parameters:addStringAlternative("CalcMode", "Woordie", "", "Woodie");

    -- TODO: Add the stream here
    indicator.parameters:addColor("clr1", "Color of the oscillator line", "", core.rgb(192, 0, 0));
    indicator.parameters:addColor("clr2", "Color of the oscillator line", "", core.rgb(0, 192, 0));
end

local source;
local ref;
local instr;
local BS;
local BSLen;
local host;
local offset;
local weekoffset;

-- pivot results
local P;            -- pivot
local H;
local L;
local S1;           -- support levels
local S2;
local S3;
local S4;
local R1;           -- resistance levels
local R2;
local R3;
local R4;

-- pivot modes
local O_PIVOT = 1;
local O_CAM = 2;
local O_WOOD = 3;
local CalcMode;

-- TODO: your indicator output here
local OUT1 = nil;
local OUT2 = nil;

function Prepare()
    InitPivot();

    -- TODO: initialize your indicator here
    -- BTW, the source global variable is already filled by pivot
    --
    local name;
    name = profile:id() .. "(" .. source:name() .. "," .. BS .. "," .. instance.parameters.CalcMode .. ")";
    instance:name(name);
    OUT1 = instance:addStream("O1", core.Line, name .. ".O1", "O1", instance.parameters.clr1, 0);
    OUT2 = instance:addStream("O2", core.Line, name .. ".O2", "O2", instance.parameters.clr2, 0);
end

local loading = false;
local loadingFrom, loadingTo;
local pday = nil;
local d = {};


function Update(period, mode)
    if not(CalcPivot(period)) then
        -- if pivot is not ready yet - just return
        -- Pivot will call us to recalculate when the data
        -- is ready
        return ;
    end

    -- TODO put your code here. Just use P, S* and N* streams to get the pivot data.
    -- our example just shows a distance from the close of the current bar to the
    -- support and to the resistance lines. The crossing of the 0 level means "break".
    OUT1[period] = source.close[period] - S1[period];
    OUT2[period] = R1[period] - source.close[period];
end

function InitPivot()
    host = core.host;
    offset = host:execute("getTradingDayOffset");
    weekoffset = host:execute("getTradingWeekOffset");

    source = instance.source;
    instr = source:instrument();
    BS = instance.parameters.BS;

    -- validate
    local l1, l2;
    local s, e;

    s, e = core.getcandle(source:barSize(), core.now(), 0);
    l1 = e - s;
    s, e = core.getcandle(BS, core.now(), 0);
    l2 = e - s;
    BSLen = l2; -- remember length of the period

    assert(l1 <= l2, "The source frame must be shorter or equal to the pivot timeframe");
    assert(BS ~= "t1", "The pivot period must not be a tick");

    -- decode pivot mode
    if instance.parameters.CalcMode == "Pivot" then
        CalcMode = O_PIVOT;
    elseif instance.parameters.CalcMode == "Camarilla" then
        CalcMode = O_CAM;
    elseif instance.parameters.CalcMode == "Woodie" then
        CalcMode = O_WOOD;
    else
        assert(false, "Unknown mode" .. ": " .. instance.parameters.CalcMode);
    end

    -- pivot
    P = instance:addInternalStream(0, 0);
    -- range
    H = instance:addInternalStream(0, 0);
    L = instance:addInternalStream(0, 0);
    -- levels
    S1 = instance:addInternalStream(0, 0);
    S2 = instance:addInternalStream(0, 0);
    S3 = instance:addInternalStream(0, 0);
    S4 = instance:addInternalStream(0, 0);
    R1 = instance:addInternalStream(0, 0);
    R2 = instance:addInternalStream(0, 0);
    R3 = instance:addInternalStream(0, 0);
    R4 = instance:addInternalStream(0, 0);
end


function CalcPivot(period)
    -- get the previous's candle and load the ref data in case ref data does not exist
    local candle;
    candle = core.getcandle(BS, source:date(period), offset, weekoffset);

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

    -- if data is not loaded yet at all
    -- load the data
    if ref == 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), offset, weekoffset);
        end
        from = core.getcandle(BS, source:date(source:first()), offset, weekoffset);
        loading = true;
        P:setBookmark(1, period);
        from = fixFrom(from);
        loadingFrom = from;
        loadingTo = to;
        ref = host:execute("getHistory", 1, source:instrument(), BS, from, to, source:isBid());
        return false;
    end

    -- check whether the requested candle is before
    -- the reference collection start
    if (candle < ref:date(0)) then
        local from;
        P:setBookmark(1, period);
        if loading then
            return false;
        end
        loading = true;
        from = fixFrom(candle);
        loadingFrom = from;
        loadingTo = ref:date(0);
        host:execute("extendHistory", 1, ref, loadingFrom, loadingTo);
        return false;
    end

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

    -- find the lastest completed period which is not saturday's period (to avoid
    -- collecting the saturday's data
    local prev_i = nil;
    local start;

    if (pday == nil) then
        start = 0;
    elseif ref:date(pday) >= candle then
        start = 0;
    else
        start = pday;
    end

    for i = start, ref:size() - 1, 1 do
        local td;
        -- skip nontrading candles
        if BSLen > 1 or not(core.isnontrading(ref:date(i), offset)) then
            if (ref:date(i) >= candle) then
                break;
            else
                prev_i = i;
            end
        end
    end

    if (prev_i == nil) then
        -- assert(false, "prev_i is nil");
        return false;
    end

    pday = prev_i;
    if CalcMode == O_PIVOT then
        P[period] = (ref.high[prev_i] + ref.close[prev_i] + ref.low[prev_i]) / 3;
    elseif CalcMode == O_CAM then
        -- P[period] = (ref.high[prev_i] + ref.close[prev_i] + ref.low[prev_i]) / 3;
        P[period] = ref.close[prev_i];
    elseif CalcMode == O_WOOD then
        local open;
        if (prev_i == ref:size() - 1) then
            -- for a live day take close as open of the next period
            open = ref.close[prev_i];
        else
            open = ref.close[prev_i + 1];
        end
        P[period] = (ref.high[prev_i] + ref.close[prev_i] + open * 2 ) / 4;
    end
    H[period] = ref.high[prev_i];
    L[period] = ref.low[prev_i];

    CalculateLevels(period);
    return true;
end

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

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

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

function CalculateLevels(period)
    local h, l, p, r;
    p = P[period];
    h = H[period];
    l = L[period];
    r = h - l;

    if CalcMode == O_PIVOT then
        R4[period] = p + r * 3;
        R3[period] = p + r * 2;
        R2[period] = p + r;
        R1[period] = p * 2 - l;

        S1[period] = p * 2 - h;
        S2[period] = p - r;
        S3[period] = p - r * 2;
        S4[period] = p - r * 3;
    elseif CalcMode == O_CAM then
        R4[period] = p + r * 1.1 / 2;
        R3[period] = p + r * 1.1 / 4;
        R2[period] = p + r * 1.1 / 6;
        R1[period] = p + r * 1.1 / 12;

        S1[period] = p - r * 1.1 / 12;
        S2[period] = p - r * 1.1 / 6;
        S3[period] = p - r * 1.1 / 4;
        S4[period] = p - r * 1.1 / 2;
    elseif CalcMode == O_WOOD then
        R4[period] = h + (2 * (p - l) + r);
        R3[period] = h + 2 * (p - l);
        R2[period] = p + r;
        R1[period] = p * 2 - l;

        S1[period] = p * 2 - h;
        S2[period] = p - r;
        S3[period] = l - 2 * (h - p);
        S4[period] = l - (r + 2 * (h - p));
    end
    return ;
end

function fixFrom(date)
    -- skip to the previous period
    date = date - BSLen * 2;
    -- check whether the Friday 17:00 >= period > Sunday 17:00
    -- if so - unwind to the last period of the previous trading
    local nontrading, nontradingend;
    nontrading, nontradingend = core.isnontrading(date, offset);
    if BSLen <= 1 and (nontrading) then
        date = nontradingend - BSLen * 2;
    end
    return date;
end


How does it look:
pivotsample.png
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1235
Joined: Wed Dec 16, 2009 6:39 pm
Location: Cary, NC

Re: Where to place Update(period) in pivot.lua

Postby LordTwig » Sun May 02, 2010 12:08 pm

:D Fantastic.......Many many thanks for that template Nikolay.

Finally I can use correct pivot value easily.
Have placed all my parametres and conditions, All working in Marketscope.

Only having trouble with getting the correct 'end of day' period
I need to get the period immediately before the end of the trading day ie, (last period before the close) if 'H1' I need the 16:00 bar, not the 17:00 bar trading close. or 16.59 bar if 'm1'
It acts as a switch for end of trading day.

Can you help with this and place in correct spot of template.

-- sample switch
if TimeEnd == 'period before trade day end' then
EndOfDay = 1; -- true
else
EndOfDay = 0; -- false

I have tried using core.dateToTable but must be using it wrong

Cheers and thanks again for the template, I owe you a slab.....(carton of beer) :)
LordTwig
Cheers
LordTwig
LordTwig
FXCodeBase: Confirmed User
 
Posts: 157
Joined: Fri Mar 12, 2010 3:15 am

Re: Where to place Update(period) in pivot.lua

Postby Nikolay.Gekht » Mon May 03, 2010 6:14 pm

Ok.

Let's assume that the period (m1, m5 and so on...) is stored in the variable myBarSize and the date and time of the bar is stored in myDate

1) You need to calculate the length of the period in seconds:
local s, e;
local myBarLength;

s, e = core.getcandle(myBarSize, 0, 0, 0);
myBarLength = math.floor((e - s) * 86400 + 0.5);

2) You need to get the range of the 1-day candle to which the particular date belongs.

s, e = core.getcandle("D1", myDate, host:execute("getTradingDayOffset"));

here e is the date and time of the beginning of the next candle. Let's convert it to the seconds as well.

e = math.floor(e * 86400 + 0.5);

3) Now we know the length of the candle of our bar size and the date and time of the next candle. Just subtract the length from the beginning of the next candle.

s = e - myBarLength;

That's almost all. Convert it back to the day number instead of second number

s = s / 86400;

Here s - is the beginning of the last candle of the myBarSize time frame of the trading day.

The playing with converting to the number of seconds is required because sometimes the candles which are calculated by Marketscope have period (i.e. xxx.666666666666666666666 instead of xxx.666667) in the fractional part. Converting to the whole second eliminates this period.
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1235
Joined: Wed Dec 16, 2009 6:39 pm
Location: Cary, NC

Re: Where to place Update(period) in pivot.lua

Postby LordTwig » Wed May 12, 2010 10:31 am

There is the template of the code which calculates very simple oscillator - the distance of the close price to the R1 and S1 levels of the pivot.


Hi Nikolay,
1) Is it possible to 'hover' over Oscilator data and have it display the value @ that period and display follows pointer if hover over other periods??

2) Using Oscilator Is it possible to be able to change the Marketscopes candles colors to 'Users' colors if a BUY or SELL is generated ie; normal color up candle is green (BUY signal turns candle blue) normal color down candle is red (Sell signal turns candle yellow) wow!!! that would be nice ??
and when day ends or no signals generated the candles are/return normal default colors.

3) Using Oscilator Is it possible to add text box to chart screen at top left so it stays there if scrolling and it displays in that text box the stream data of lets say.... average of the last five candles??

If so can you please add these to your template that you made above using pivot.lua

Thanks
LordTwig
Cheers
LordTwig
LordTwig
FXCodeBase: Confirmed User
 
Posts: 157
Joined: Fri Mar 12, 2010 3:15 am

Re: Where to place Update(period) in pivot.lua

Postby Nikolay.Gekht » Thu May 13, 2010 9:38 pm

1) To see the data of the period you are currently "hover" you can turn on the "Cursor Data" windows ("Chart" Menu of the marketscope)

2,3) Indicators and oscillators can draw only in their own "areas". Drawing everything and everywhere is rather a kind of "free-form" drawing via the interface similar to Windows GDI... I'm not sure whether it will be possible in the nearest release. I prefer to concentrate on the auto trading. Probably, after the release.

I'll try to use something like http://wxlua.sourceforge.net/ to demonstrate the indicator which shows it's own window. Probably, it would better way than overload Marketscope with the rich application development function, at least right now.
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1235
Joined: Wed Dec 16, 2009 6:39 pm
Location: Cary, NC

Re: Where to place Update(period) in pivot.lua

Postby LordTwig » Thu May 27, 2010 11:22 am

Nikolay.Gekht wrote:Ok.

Let's assume that the period (m1, m5 and so on...) is stored in the variable myBarSize and the date and time of the bar is stored in myDate

1) You need to calculate the length of the period in seconds:
local s, e;
local myBarLength;

s, e = core.getcandle(myBarSize, 0, 0, 0);
myBarLength = math.floor((e - s) * 86400 + 0.5);

2) You need to get the range of the 1-day candle to which the particular date belongs.

s, e = core.getcandle("D1", myDate, host:execute("getTradingDayOffset"));

here e is the date and time of the beginning of the next candle. Let's convert it to the seconds as well.

e = math.floor(e * 86400 + 0.5);

3) Now we know the length of the candle of our bar size and the date and time of the next candle. Just subtract the length from the beginning of the next candle.

s = e - myBarLength;

That's almost all. Convert it back to the day number instead of second number

s = s / 86400;

Here s - is the beginning of the last candle of the myBarSize time frame of the trading day.

The playing with converting to the number of seconds is required because sometimes the candles which are calculated by Marketscope have period (i.e. xxx.666666666666666666666 instead of xxx.666667) in the fractional part. Converting to the whole second eliminates this period.


Hi Nikolay,
This doesn't work, I have tried and tried, but all it does is stop my streams data from displaying on chart, all I have done is changed locals (s and e) to different names as they are already being used
in pivot.lua.

I placed exact code after function (update mode).
screwed my streams without even adding any of my code or conditions to it.
Can you place and test that it (code) works in your (pivot template) above.

Would be nice to also have it done in (Time Format) HH,MM,SS. so as I can just give it a time to start finish or start from. I would prefer it to work with actual time in fact.

Cheers
LordTwig
Cheers
LordTwig
LordTwig
FXCodeBase: Confirmed User
 
Posts: 157
Joined: Fri Mar 12, 2010 3:15 am

Re: Where to place Update(period) in pivot.lua

Postby Nikolay.Gekht » Thu May 27, 2010 12:33 pm

Here is an example of the indicator which just puts a mark on each last candle of the chosen bigger time frame (for example the last 5 minute candle in a hour, or the last hour candle in a day):

Code: Select all
function Init()
    indicator:name("Demo: Mark last candle in the bigger time frame");
    indicator:description("");
    indicator:requiredSource(core.Bar);
    indicator:type(core.Indicator);

    indicator.parameters:addString("TF", "Bigger time frame", "", "D1");
    indicator.parameters:setFlag("TF", core.FLAG_PERIODS);
    indicator.parameters:addColor("CLR", "Label color", "", core.COLOR_LABEL);
end

local source;
local out;
local TF;
local currLength;   -- length of the current chart bar in seconds
local tfLength;     -- length of the bigger time frame in seconds
local dayOffset;
local weekOffset;

function Prepare()
    TF = instance.parameters.TF;
    source = instance.source;

    dayOffset = core.host:execute("getTradingDayOffset");
    weekOffset = core.host:execute("getTradingWeekOffset");

    local s, e;
    -- get length of the current chart time frame in seconds
    -- note: in fact, for getting the length the dayOffset and weekOffset does not matter.
    s, e = core.getcandle(source:barSize(), core.now(), dayOffset, weekOffset);
    currLength = math.floor((e - s) * 86400 + 0.5);
    -- get length of the bigger time frame in seconds
    s, e = core.getcandle(TF, core.now(), dayOffset, weekOffset);
    tfLength = math.floor((e - s) * 86400 + 0.5);

    assert(currLength < tfLength, "The chosen time frame must be longer than the chart time frame");

    local name = profile:id();
    instance:name(name);
    out = instance:createTextOutput ("out", "out", "Wingdings", 10, core.H_Center, core.V_Top, instance.parameters.CLR, 0);
end

function Update(period, mode)
    local s, e, l, c;

    -- get beginning of the candle of the bigger time frame to which this
    -- canlde belongs (s) and the beginning of the next candle (e)
    s, e = core.getcandle(TF, source:date(period), dayOffset, weekOffset);
    s = math.floor(s * 86400 + 0.5);
    e = math.floor(e * 86400 + 0.5);
    -- calculate the beginning of the last candle of the current timeframe
    -- inside the bigger time frame candle
    l = e - currLength;
    -- convert current candle from days to seconds
    c = math.floor(source:date(period) * 86400 + 0.5);
    if c == l then
        out:set(period, source.median[period], "\164");
    end
end


The logic is not so transparent but, in fact, a million times (:-)) easier to implement and to execute (so faster).

This example is rather demonstrative, but, please, start from this. I'll add an advanced logic which can catch the absent candles (i.e. when the last candle is the period is skipped, for example there is no one ticks during the last minute of an hour). But it will be much easier to start from this sample and then make it more complex. Please feel free to ask any questions.
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1235
Joined: Wed Dec 16, 2009 6:39 pm
Location: Cary, NC

Next

Return to Indicator Development

Who is online

Users browsing this forum: No registered users and 16 guests