function ExtUpdate(id, source, period) does not fire cookie

Section for discussions related to indicators, use of indicators, and building of trading stategies using indicators.

Moderator: admin

function ExtUpdate(id, source, period) does not fire cookie

Postby pipReaper » Tue Nov 27, 2012 9:55 am

I am having some trouble with the attached strategy. I am interested in candle data so I used ExtUpdate and ExtAsyncOperationFinished. Now when I delete an order the cookieCancelEntry does not fire in the ExtAsyncOperationFinished function. However the orders do get deleted as desired but I am unable to say when and so not able to set variables to relay this information.

I see in the original methodology Update and AsyncOperationFinished there exist two further arguments method1 and method2. These arguments contain information on the FixOrder status = exactly what I need to determine the operation occuring. This happens when core.host:execute("subscribeTradeEvents", cookieOrdersTable, "orders"); is subscribed to.

So what to do do I
1/. re-engineer this thing away from ExtUpdate and ExtAsyncOperationFinished - which is supposed to be helpful - and back to Update and AsyncOperationFinished?

or

2/. keep a record of the orders and detect when they are no longer in the table?

3/. Hopefully someone has another plan to exact?

Any help / ideas appreciated.

Code: Select all
function Init()
    strategy:name("Candles");
    strategy:description("This processes just candle events");
    strategy:type(core.Both);
    --Price Parameters
    strategy.parameters:addGroup("Price Parameters");
    --Time Frame
    strategy.parameters:addString("TF", "param_TF_name", "param_TF_description", "m5");
    strategy.parameters:setFlag("TF", core.FLAG_PERIODS);

    -- Indicator Parameters
    strategy.parameters:addGroup("Parameters");
    strategy.parameters:addInteger("pEMA", "param_pEMA_name", "param_pEMA_description", 34);
    strategy.parameters:addInteger("pCCIBig", "param_pCCIBig_name", "param_pCCIBig_description", 50);
    strategy.parameters:addInteger("pCCISmall", "param_pCCISmall_name", "param_pCCISmall_description", 14);
    -- Trading Parameters
    strategy.parameters:addGroup("Trading Parameters");
    strategy.parameters:addBoolean("bClickTrade", "is trading", "true if indicator is trading", false)
    strategy.parameters:addBoolean("AllowTrade", "Can Trade", "", true);
    strategy.parameters:addBoolean("AllowTicks", "Can have Ticks", "", false);
    strategy.parameters:addString("Account", "param Account Trade Name", "", "TESTACCT");
    strategy.parameters:setFlag("Account", core.FLAG_ACCOUNT);
    strategy.parameters:addInteger("tradeSize", "param_tradeSize_name", "", 1, 1, 10000);
    strategy.parameters:addInteger("Limit", "param_LimitOrderPips_name", "", 30, 1, 10000);
    strategy.parameters:addInteger("Stop", "param_StopOrderPips", "", 20, 1, 10000);   
    strategy.parameters:addBoolean("TrailingStop", "Set Trailing Stop Order", "", false);
end


--ABOUT SOURCE--
local pCCIBig;
local pCCISmall;
local pEMA;
local firstCCISmall = 0;
local firstCCIBig   = 0;
local firstEMA      = 0;
local firstASI      = 0;
local cci7 = nil;
local cci50 = nil;
local ema34 = nil;
local asi = nil;
local myCandleSourceBid = nil;
local myCandleSourceAsk = nil;
local bClickTrade;

--ABOUT ASYNC--

cookieLoadHistBid = 1;
cookieEntryOrder = 100;
cookieCancelEntry = 3000;
cookieOrdersTable = 4000;
cookieTradesTable = 1001;

-- ABOUT TRADING PARAMETERS --
local AllowTicks;
local AllowTrade;
local Account;
local BaseSize;
local SetLimit;
local Limit;
local SetStop;
local Stop;
local SetTS;
local Offer;
local CanClose;
local retracePips = 10;
local lastSerial = -1;
local requestId;
local stage;
local orderId;
local tradeSize;
local pipSize;
local nexecuting = 0;


function Prepare(nameOnly)
    pEMA = instance.parameters.pEMA;
    pCCIBig = instance.parameters.pCCIBig;
    pCCISmall = instance.parameters.pCCISmall;
    bClickTrade = instance.parameters.bClickTrade;
    local name = profile:id() .. "(" .. instance.bid:instrument() .. ", " .. tostring(pCCIBig) .. ", " .. tostring(pCCISmall) .. ", " .. tostring(pEMA) .. ")";
    instance:name(name);

    if nameOnly then
        return ;
    end

    AllowTicks = false;
    if (not(AllowTicks)) then
        assert(instance.parameters.TF ~= "t1", "assert_noticks");
    end

    AllowTrade = instance.parameters.AllowTrade;
    if AllowTrade then
        Account = instance.parameters.Account;
        BaseSize = core.host:execute("getTradingProperty", "baseUnitSize", instance.bid:instrument(), Account);
        Offer = core.host:findTable("offers"):find("Instrument", instance.bid:instrument()).OfferID;
        tradeSize = instance.parameters.tradeSize * core.host:execute("getTradingProperty", "baseUnitSize", instance.bid:instrument(), Account);
        SetLimit = true;
        Limit = instance.parameters.Limit * instance.bid:pipSize();
        SetStop = true;
        SetTS = false;
        Stop = instance.parameters.Stop * instance.bid:pipSize();
        pipSize = instance.bid:pipSize();
    end
    local canClose = core.host:execute("getTradingProperty", "canCreateStopLimit", instance.bid:instrument(), instance.parameters.Account);
    local canLimitStop = core.host:execute("getTradingProperty", "canCreateMarketClose", instance.bid:instrument(), Account);

    myCandleSourceBid = ExtSubscribe(cookieLoadHistBid, instance.bid:instrument(), "m5", true, "bar")  --bid
    --myCandleSourceAsk = ExtSubscribe(cookieLoadHistAsk, instance.bid:instrument(), "m5", false, "bar") --ask
 
    core.host:execute("subscribeTradeEvents", cookieTradesTable, "trades");
    core.host:execute("subscribeTradeEvents", cookieOrdersTable, "orders");
    --BID Prices in indicators
    cci7        = core.indicators:create("CCI", myCandleSourceBid, pCCISmall);
    cci50       = core.indicators:create("CCI", myCandleSourceBid, pCCIBig);
    asi         = core.indicators:create("ASI", myCandleSourceBid);
    ema34       = core.indicators:create("EMA", myCandleSourceBid.close, pEMA);

    firstEMA                =   ema34.DATA:first()+1;
    firstCCISmall           =   cci7.DATA:first()+1; 
    firstCCIBig             =   cci50.DATA:first()+1;
    firstASI                =   asi.DATA:first()+1;

   if nameOnly then
        return ;
    end
end


function ExtUpdate(id, source, period)
    if AllowTrade then
        if not(checkReady("trades")) or not(checkReady("orders")) then
            return ;
        end
    end

    if  period < firstEMA or period < firstCCISmall or period < firstCCIBig or period < firstASI then -- bid and ask bar streams
        return;
    end

    ema34:update(core.UpdateLast)
    cci7:update(core.UpdateLast)
    cci50:update(core.UpdateLast)
    asi:update(core.UpdateLast)

    local leave = false;
    local enum = core.host:findTable("orders"):enumerator();
    row = enum:next();
    if row ~= nil then
        if (balkEO(row,period,enum) ~= nil) then
                local vmap = core.valuemap();
                vmap.Command = "DeleteOrder";
                vmap.OrderID = row.OrderID;
                success, msg = terminal:execute(cookieCancelEntry, vmap);
                assert(success, msg);   
                    if not(success) then
                        terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "Failed delete order:" ..
                        msg, myCandleSourceBid:date(period));
                    elseif success then
                        bClickTrade = false;
                    end
                leave = true;
        end
    end
    if not (leave) then
        if canBuy (period) then toBUY(period); end
        if canSell(period) then toSELL(period);end   
    end
end
function balkEO(row,period,enum)
    --offersTime = getOfferTime("OFFER_01");
    offersTime = myCandleSourceBid:date(period);
    --print(core.dateToTable(offersTime).hour..":"..core.dateToTable(offersTime).min..":"..core.dateToTable(offersTime).sec);
    -- Check for Expired Entry Orders ------------------------------------

    while (row ~= nil) do
        if row.FixStatus == "W" then -- this finds all waiting orders
        --    local sDuration = getTimeDiffMin(core.dateToTable(row.Time),core.dateToTable(offersTime));-- get time difference
        sDuration = (offersTime - row.Time)*12*24; -- convert OLE Time to difference in Minutes
            --print(core.dateToTable(row.Time).hour..":"..core.dateToTable(row.Time).min..":"..core.dateToTable(row.Time).sec)
            --print (sDuration);
            if row.OrderID == orderId and sDuration >= 20 then
                return orderId;                                                         
            end
            row = enum:next();
        end
    end   
    return nil;
end
function ExtAsyncOperationFinished(cookie, success, message)
   -- core.host:trace(tostring(cookie) .. " " .. tostring(success) .. " " .. tostring(message));
   if cookie == cookieEntryOrder then -- Entry Order
        if not success then
            stage = 3;          -- failed
            bClickTrade = false;
            orderId = nil;
        else
            stage = 2;          -- executed
            orderId = message;  -- keep id of the created order
            bClickTrade = true; 
        end
    elseif cookie == cookieTradesTable then
        if haveTrades(message) then
            --open event is still bClickTrade
            bClickTrade = true;
        elseif not(haveTrades(message)) then
            --close event
            bClickTrade = false;
            orderId = nil;
        end
    elseif cookie == cookieOrdersTable then
         --   bClickTrade = false;
            local d = 1;
    elseif cookie == cookieCancelEntry then
         --   bClickTrade = false;
            local d = 1;
            --terminal:alertMessage(instance.bid:instrument(), myCandleSourceBid.close[period], "Cancelled Entry Order",     getOfferTime("OFFER_01"))

    end
end

function canBuy(period) -- Check conditions for open trade BUY   
--Buy
    if  (cci7.DATA[period] > 0.0) and
        (cci50.DATA[period] > 0.0) and
        (asi.DATA[period] > 0.0) and
        (myCandleSourceBid.close[period] >= ema34.DATA[period]) and
        not(bClickTrade)
        --instrument.Ema34_5_Minute.EMAV > instrument.Ema200_5_Minute.EMAV &&
        --instrument.asi5Minute.LastSwing == "high" &&
        ----last swing was the highest swing in the period of observation
        --currentASIClose == instrument.ASI5Minute.Fibs.ExtremeASI &&
        --instrument.LSFSwing.Angle > funcs.global.validAngle // &&
    then
        return true;
    else   
        return false;
    end
end

function canSell(period) -- Check conditions for open trade SELL   
--Buy
    if  (cci7.DATA[period] < 0.0) and
        (cci50.DATA[period] < 0.0) and
        (asi.DATA[period] < 0.0) and
        (myCandleSourceBid.close[period] <= ema34.DATA[period])
        and not(bClickTrade)
        --instrument.Ema34_5_Minute.EMAV > instrument.Ema200_5_Minute.EMAV &&
        --instrument.asi5Minute.LastSwing == "high" &&
        ----last swing was the lowest swing in the period of observation
        --currentASIClose == instrument.ASI5Minute.Fibs.ExtremeASI &&
        --instrument.LSFSwing.Angle > funcs.global.validAngle // &&
    then
        return true;
    else   
        return false;
    end
end
function toBUY(period)
    --terminal:alertMessage(instance.bid:instrument(), myCandleSourceBid.close[period], "Going to Buy",     getOfferTime("OFFER_01"))
    trade("B");
end
function toSELL(period)
    --terminal:alertMessage(instance.bid:instrument(), myCandleSourceBid.close[period], "Going to Sell",     getOfferTime("OFFER_01"))
    trade("S");
end
------------------------------------------------ SET UP ORDER ---------------------------------------------------------------------
function trade(sDirection)   
    if sDirection == "B" then
        local valuemap, success, msg;
        valuemap = core.valuemap();
        valuemap.Command = "CreateOrder";   
        valuemap.OrderType = "LE";      -- open market
        valuemap.OfferID = Offer;
        valuemap.AcctID = Account;
        valuemap.Quantity = tradeSize;
        valuemap.BuySell = "B";
        valuemap.Rate = instance.ask[NOW] - (retracePips * pipSize);
        setStopLimits(valuemap,valuemap.BuySell);           -- executing
        success, msg = terminal:execute(cookieEntryOrder, valuemap); 
        assert(success, msg);
            if(success) then
                bClickTrade = true; 
            --    orderId = info;
            end
        requestId = msg;
        stage = 1;
    elseif sDirection == "S" then
        local valuemap, success, msg;
        valuemap = core.valuemap();
        valuemap.Command = "CreateOrder";   
        valuemap.OrderType = "LE";      -- open market
        valuemap.OfferID = Offer;
        valuemap.AcctID = Account;
        valuemap.Quantity = tradeSize;
        valuemap.BuySell = "S";
        valuemap.Rate = instance.bid[NOW] + (retracePips * pipSize);
        setStopLimits(valuemap,valuemap.BuySell);           -- executing
        success, msg = terminal:execute(cookieEntryOrder, valuemap); 
        assert(success, msg);
            if(success) then
                bClickTrade = true; 
          --      orderId = info; 
            end
        requestId = msg;
        stage = 1;
    end
end

function setStopLimits(vm,bs)
    local spread = (instance.ask[NOW] - instance.bid[NOW])/pipSize;
    if SetLimit then
       vm.PegTypeLimit = "M";
       if bs == "B" then
            --vm.Limit = vm.Rate + instance.parameters.Limit*pipSize;
           vm.PegPriceOffsetPipsLimit = instance.parameters.Limit;
       else
            --vm.Limit = vm.Rate - instance.parameters.Limit*pipSize;
          vm.PegPriceOffsetPipsLimit = -instance.parameters.Limit;
       end
    end

    if SetStop then
       vm.PegTypeStop = "M";
       if bs == "B" then
           --vm.Stop = vm.Rate - (instance.parameters.Stop * pipSize) + spread;
           vm.PegPriceOffsetPipsStop = instance.parameters.Stop + spread;
       else
           --vm.Stop = vm.Rate + (instance.parameters.Stop * pipSize) - spread;
           vm.PegPriceOffsetPipsStop = instance.parameters.Stop - spread;
       end

       if SetTS then
           vm.TrailStepStop = 1;
       end
    end
end

-------------------------------------------- UTILITIES ---------------------------------------------------------------------------
function haveTrades(tradeId)
    local enum, row;
    local found = false;
    enum = core.host:findTable("trades"):enumerator();
    row = enum:next();
    while (not found) and (row ~= nil) do
        if row.TradeID == tradeId then
           found = true;
        end
        row = enum:next();
    end
    return found
end
function getOfferTime(offerId)
    local enum, row;
    local found = false;
    enum = core.host:findTable("offers"):enumerator();
    row = enum:next();
    while (not found) and (row ~= nil) do
        if row.OfferID == offerId then
           found = true;
           return row.Time;
        end
        row = enum:next();
    end
    return found
end
function checkReady(table)
    local rc;
    if Account == "TESTACCT" then
        -- run under debugger/simulator
        rc = true;
    else
        rc = core.host:execute("isTableFilled", table);
    end
    return rc;
end
function getTimeDiffMin(i,f)
    -- takes two formated dates and returns the difference in minutes
    local nowSec    = f.day*60*60*24 + f.hour*60*60 + f.min*60 + f.sec;
    local orderSec  = i.day*60*60*24 + i.hour*60*60 + i.min*60 + i.sec;
   return (nowSec - orderSec)/60;
end
---------------------------------------------------------------------------------------------------------------------------------
dofile(core.app_path() .. "\\strategies\\standard\\include\\helper.lua");








































pipReaper
 
Posts: 5
Joined: Tue Nov 27, 2012 9:37 am

Re: function ExtUpdate(id, source, period) does not fire cookie

Postby Victor.Tereschenko » Wed Nov 28, 2012 11:47 pm

pipReaper wrote:I am having some trouble with the attached strategy. I am interested in candle data so I used ExtUpdate and ExtAsyncOperationFinished. Now when I delete an order the cookieCancelEntry does not fire in the ExtAsyncOperationFinished function. However the orders do get deleted as desired but I am unable to say when and so not able to set variables to relay this information.

This is a defect of Backtester (in Marketscope it works well).
pipReaper wrote:I see in the original methodology Update and AsyncOperationFinished there exist two further arguments method1 and method2. These arguments contain information on the FixOrder status = exactly what I need to determine the operation occuring. This happens when core.host:execute("subscribeTradeEvents", cookieOrdersTable, "orders"); is subscribed to.

It's a defect in Marketscope.
Workaround:
Do not include the helper.lua
Replace this string
Code: Select all
dofile(core.app_path() .. "\\strategies\\standard\\include\\helper.lua");

with this code:
Code: Select all
local _gSubscription = {};

-- subscribe for the price data
function ExtSubscribe(id, instrument, period, bid, type)
    local sub = {};
    if instrument == nil and period == "t1" then
        if bid then
            sub.stream = instance.bid;
        else
            sub.stream = instance.ask;
        end
        sub.tick = true;
        sub.loaded = true;
        sub.lastSerial = -1;
        _gSubscription[id] = sub;
    elseif instrument == nil then
        sub.stream = core.host:execute("getHistory", id, instance.bid:instrument(), period, 0, 0, bid);
        sub.tick = false;
        sub.loaded = false;
        sub.lastSerial = -1;
        _gSubscription[id] = sub;
    else
        sub.stream = core.host:execute("getHistory", id, instrument, period, 0, 0, bid);
        sub.tick = (period == "t1");
        sub.loaded = false;
        sub.lastSerial = -1;
        _gSubscription[id] = sub;
    end
    if sub.tick then
        return sub.stream;
    else
        if type == "open" then
            return sub.stream.open;
        elseif type == "high" then
            return sub.stream.high;
        elseif type == "low" then
            return sub.stream.low;
        elseif type == "close" then
            return sub.stream.close;
        elseif type == "bar" then
            return sub.stream;
        else
            assert(false, type .. " is unknown");
        end
    end
end

function AsyncOperationFinished(cookie, success, message, message1, message2)
    local sub;
    sub = _gSubscription[cookie];
    if sub ~= nil then
        sub.loaded = true;
        if sub.stream:size() > 1 then
           sub.lastSerial = sub.stream:serial(sub.stream:size() - 1);
        end
    else
        -- unknown cookie
        if ExtAsyncOperationFinished ~= nil then
            ExtAsyncOperationFinished(cookie, success, message, message1, message2)
        end
    end
end

function Update()
    for k, v in pairs(_gSubscription) do
        if v.loaded and v.stream:size() > 1 then
            local s = v.stream:serial(v.stream:size() - 1);
            local p;
            if s ~= v.lastSerial then
                if v.tick then
                    p = v.stream:size() - 1;    -- the last tick
                else
                    p = v.stream:size() - 2;    -- the previous candle
                end
                ExtUpdate(k, v.stream, p);
                v.lastSerial = s;
            end
        end
    end
end

dofile(core.app_path() .. "\\strategies\\standard\\include\\helperAlert.lua");

It's a code from helper.lua but with a fix. helper.lua defines Update and AsyncOperationFinished (thats why you should use ExtUpdate and ExtAsyncOperationFinished instead). AsyncOperationFinished calls your ExtAsyncOperationFinished but forgets to pass message1 and message2 into it (Marketscope version). The code above has a fix.
“There are only three sports: bullfighting, motor racing, and mountaineering; all the rest are merely games.” (c) Ernest Hemingway
Victor.Tereschenko
FXCodeBase: Confirmed User
 
Posts: 144
Joined: Fri Nov 19, 2010 8:55 am

Re: function ExtUpdate(id, source, period) does not fire cookie

Postby pipReaper » Thu Nov 29, 2012 3:41 am

Many Thanks

The substitution of:
Code: Select all
function ExtAsyncOperationFinished(cookie, success, message)


with

Code: Select all
function ExtAsyncOperationFinished(cookie, success, message,message1,message2)


delivers the FixStatus codes into the ExtAsyncOperationFinished function.

The version of SDK (editors) I have is 2011 November. This is the latest version of SDK I can find. I downloaded this from this site and SDK tab. I assume this is the latest version. So is this documented somewhere or is the way to find this answer to discuss as I have done here?

Again many thanks
pipReaper
 
Posts: 5
Joined: Tue Nov 27, 2012 9:37 am

Re: function ExtUpdate(id, source, period) does not fire cookie

Postby Valeria » Mon Dec 03, 2012 3:14 am

Hi pipReaper,

In this thread you can find all beta versions of SDK and Trading Station. Here is the latest beta version of SDK viewtopic.php?f=30&t=20383#p35748

pipReaper wrote:
The version of SDK (editors) I have is 2011 November. This is the latest version of SDK I can find. I downloaded this from this site and SDK tab. I assume this is the latest version. So is this documented somewhere or is the way to find this answer to discuss as I have done here?

Again many thanks
Valeria
 



Return to Discussions

Who is online

Users browsing this forum: No registered users and 11 guests