Multiple updates running in strategies

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

Moderator: admin

Multiple updates running in strategies

Postby tllewell » Tue Nov 06, 2012 3:16 pm

Another multiple time frame question. When I have two time frames built into a strategy, the ExtUpdate gets called each time a bar closes, and the update runs twice sometimes. The update seems to produce the same output each time, including opening a position twice when opening only one position was desired.

I have a core.trace producing output to track variables, and you can see two examples of duplicated output:

Code: Select all
EUR/USD   PIVOTAVERAGE(EUR/USD, 13, 13)   STFprice:1.28154, Prev. LTFprice:1.28149, DOAV=0.00047, pivot=1.28182, date:11/6/2012, time:150   11/06/2012 15:00:00
EUR/USD   PIVOTAVERAGE(EUR/USD, 13, 13)   STFprice:1.28154, Prev. LTFprice:1.28149, DOAV=0.00047, pivot=1.28182, date:11/6/2012, time:150   11/06/2012 15:00:00

EUR/USD   PIVOTAVERAGE(EUR/USD, 13, 13)   STFprice:1.28207, Prev. LTFprice:1.28205, DOAV=0.00108, pivot=1.28197, date:11/6/2012, time:1445   11/06/2012 14:45:02
EUR/USD   PIVOTAVERAGE(EUR/USD, 13, 13)   STFprice:1.28240, Prev. LTFprice:1.28205, DOAV=0.00139, pivot=1.28197, date:11/6/2012, time:1430   11/06/2012 14:30:02
EUR/USD   PIVOTAVERAGE(EUR/USD, 13, 13)   STFprice:1.28224, Prev. LTFprice:1.28205, DOAV=0.00130, pivot=1.28197, date:11/6/2012, time:1415   11/06/2012 14:15:02

EUR/USD   PIVOTAVERAGE(EUR/USD, 13, 13)   STFprice:1.28204, Prev. LTFprice:1.28205, DOAV=0.00120, pivot=1.28197, date:11/6/2012, time:140   11/06/2012 14:00:01
EUR/USD   PIVOTAVERAGE(EUR/USD, 13, 13)   STFprice:1.28204, Prev. LTFprice:1.28205, DOAV=0.00120, pivot=1.28197, date:11/6/2012, time:140   11/06/2012 14:00:01

EUR/USD   PIVOTAVERAGE(EUR/USD, 13, 13)   STFprice:1.28241, Prev. LTFprice:1.28136, DOAV=0.00171, pivot=1.28151, date:11/6/2012, time:1345   11/06/2012 13:45:00
EUR/USD   PIVOTAVERAGE(EUR/USD, 13, 13)   PIVOTAVERAGE(EUR/USD, 13, 13) is started.   11/06/2012 13:17:23
EUR/USD   MARGINALERT(All accounts)   MARGINALERT(All accounts) is started.   11/06/2012 13:15:52


You can see that all of the output is the same for the entries at 1400 and 1500. That's OK, but if a trade is signaled it opens the trade twice. I tried to stop the second update by keeping the time in a variable and returning if it hadn't changed, to no avail. Perhaps the updates run in different threads?

How do I compensate for this? Is this a program structure problem; maybe I should move some of the logic out of the update function? (Not sure I know how to do that; you kind of have to update your signals.) Is there some way for the program to know the update is running more than once and do some things only on one of the passes?
tllewell
 
Posts: 76
Joined: Thu Mar 01, 2012 4:06 pm

Re: Multiple updates running in strategies

Postby Apprentice » Tue Nov 06, 2012 3:21 pm

Unfortunately, without your code, i can not help you.
Here you can see an example of MTF Strategy.
viewtopic.php?f=28&t=2712#p6290
User avatar
Apprentice
FXCodeBase: Confirmed User
 
Posts: 36341
Joined: Thu Dec 31, 2009 11:59 am
Location: Zagreb, Croatia

Re: Multiple updates running in strategies

Postby tllewell » Tue Nov 06, 2012 5:15 pm

Thanks for the response, but the MTF strategy you point to is an indicator, so it doesn't have to deal with placing trades.

My strategy is based on the code in http://fxcodebase.com/wiki/index.php/Simple_Strategy_-_Moving_Average_Cross.

If you ran this strategy, wouldn't it place two trades when both time frames updated?
tllewell
 
Posts: 76
Joined: Thu Mar 01, 2012 4:06 pm

Re: Multiple updates running in strategies

Postby tllewell » Tue Nov 06, 2012 6:01 pm

Oh, I think I see what's going on here. Looking at some of your MTF strategies, you have the MTF stuff built into an indicator. I'm doing too much in the strategy.

So, is there going to be an update to the SDK where we can access other time frame price streams like the Data Source Period menu in Marketscope?
tllewell
 
Posts: 76
Joined: Thu Mar 01, 2012 4:06 pm

Re: Multiple updates running in strategies

Postby Apprentice » Wed Nov 07, 2012 5:34 am

As you can see from the template, other time frame source data is already available within the Strategy. My suggestion for you to contacting me privately.
Or and post your code here so i can help you.
User avatar
Apprentice
FXCodeBase: Confirmed User
 
Posts: 36341
Joined: Thu Dec 31, 2009 11:59 am
Location: Zagreb, Croatia

Re: Multiple updates running in strategies

Postby tllewell » Wed Nov 07, 2012 10:33 am

Here is the code that produces the problem.

Code: Select all
function Init()
    strategy:name("MTFPivot");
    strategy:description("Price crossing pivot point strategy.");
    strategy:type(core.Both);
    strategy:setTag("group", "Support/Resistance");
    strategy:setTag("NonOptimizableParameters", "Email,SendEmail,SoundFile,RecurrentSound,PlaySound,ShowAlert");

    strategy.parameters:addGroup("Time Frame");

    strategy.parameters:addString("ShortTF", "Price Time Frame", "", "m15");
    strategy.parameters:setFlag( "ShortTF", core.FLAG_PERIODS);
    strategy.parameters:addString("LongTF", "Pivot Time Frame", "", "H1");
    strategy.parameters:setFlag( "LongTF", core.FLAG_PERIODS);
    strategy.parameters:addString("Type", "Price Type", "", "Bid");
    strategy.parameters:addStringAlternative("Type", "Bid", "", "Bid");
    strategy.parameters:addStringAlternative("Type", "Ask", "", "Ask");

    strategy.parameters:addGroup("Alerts");

    strategy.parameters:addBoolean("ShowAlert", "Show Alert", "", true);
    strategy.parameters:addBoolean("PlaySound", "Play Sound", "", false);
    strategy.parameters:addBoolean("RecurrentSound", "Recurrent Sound", "", false);
    strategy.parameters:addFile("SoundFile", "Sound File", "", "");
    strategy.parameters:setFlag("SoundFile", core.FLAG_SOUND);
    strategy.parameters:addBoolean("SendEmail", "Send Email", "", false);
    strategy.parameters:addString("Email", "Email address", "Note that to recieve e-mails, SMTP settings must be defined (see Signals Options).", "");
    strategy.parameters:setFlag("Email", core.FLAG_EMAIL);
    strategy.parameters:addColor("clr", "Label Color", "", core.COLOR_LABEL);

    strategy.parameters:addGroup("Trading");
    strategy.parameters:addBoolean("AllowTrade", "Allow strategy to trade?", "If trading is not allowed, the strategy works just as a signal", false);
    strategy.parameters:addBoolean("EuroAm", "Trade European and US hours?", "", false);
    strategy.parameters:addString("Account", "Account", "", "");
    strategy.parameters:setFlag("Account", core.FLAG_ACCOUNT);
    strategy.parameters:addInteger("Amount", "Amount to Trade", "Specify the amount to trade in lots", 1, 1, 1000);
end

local allow;
local offer;
local account;
local amount;
local SoundFile;
local RecurrentSound;
local SendEmail, Email;
local STF;
local LTF;
local priceType;
local requestId;

function Prepare()
    local priceType = true;

    if instance.parameters.Type == "Ask" then
       priceType = false;
    end

    STF = ExtSubscribe(20, nil, instance.parameters.ShortTF, priceType, "bar");
    LTF = ExtSubscribe(30, nil, instance.parameters.LongTF, priceType, "bar");

    pivot = core.indicators:create("PIVOT", LTF, instance.parameters.LongTF, "Pivot", "HIST");

    local name = profile:id();
    instance:name(name);

    allow = instance.parameters.AllowTrade;
    if allow then
        account = instance.parameters.Account;
        offer = core.host:findTable("offers"):find("Instrument", instance.bid:instrument()).OfferID;
        amount = core.host:execute("getTradingProperty", "baseUnitSize", instance.bid:instrument(), account);
   canclose = core.host:execute("getTradingProperty", "canCreateMarketClose", instance.bid:instrument(), account);
    end

end

function Enter(side)
   valuemap = core.valuemap();
   valuemap.OrderType = "OM";
   valuemap.OfferID = offer;
   valuemap.AcctID = account;
   valuemap.Quantity = amount;
   valuemap.BuySell = side;
   success, msg = terminal:execute(100, valuemap);
   if not success then
      terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "open trade failed: " .. msg, instance.bid:date(NOW));
   else
      requestId = msg;
   end
end

function Exit(side)
   local enum, row, valuemap, hasTrades;
   if canclose then
      if requestId ~= nil then
         row = core.host:findTable("trades"):find("OpenOrderReqID", requestId);
         if row ~= nil then
            valuemap = core.valuemap();
            valuemap.OrderType = "CM";
            valuemap.OfferID = offer;
            valuemap.AcctID = account;
            valuemap.Quantity = row.Lot;
            valuemap.TradeID = row.TradeID;
            if row.BS == "B" then
               valuemap.BuySell = "S";
            else
            valuemap.BuySell = "B";
            end
         success, msg = terminal:execute(101, valuemap);
            if not success then
               terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "close trade failed: " .. msg, instance.bid:date(NOW));
            end
         end
      end
   else
      enum = core.host:findTable("trades"):enumerator();
      hasTrades = false;
      while not hasTrades do
         row = enum:next();
         if row == nil then
            break;
         end
         if row.AccountID == account and
         row.OfferID == offer and
         row.BS == side then
            hasTrades = true;
         end
      end
      if hasTrades then
         valuemap = core.valuemap();
         valuemap.OrderType = "CM";
         valuemap.OfferID = offer;
         valuemap.AcctID = account;
         valuemap.NetQtyFlag = "y";
         if side == "B" then
            valuemap.BuySell = "S";
         else
            valuemap.BuySell = "B";
         end
         success, msg = terminal:execute(101, valuemap);
         if not success then
            terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "close trade failed: " .. msg, instance.bid:date(NOW));
         end
      end

        end
end

function AsyncOperationFinished(cookie, success, msg)
    if cookie == 100 then
      if not success then
         terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "open trade failed: " .. msg, instance.bid:date(NOW));
   elseif cookie == 101 then
      if not success then
         terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "close trade failed: " .. msg, instance.bid:date(NOW));
      end
   end
    end
end

function ExtUpdate(id, source, period)


pivot:update(core.UpdateLast);


if pivot.DATA[pivot.DATA:size() -1] == 0 then
       return;
   end

   if STF.low[STF.low:size() - 2] > pivot.DATA[pivot.DATA:size() - 1] and
      allow then
         Enter("B");
         Exit("S");
   end

   if STF.high[STF.high:size() - 2] < pivot.DATA[pivot.DATA:size() - 1] and
      allow then
         Enter("S");
         Exit("B");
   end

   
   


core.host:trace(string.format("STFprice:%.5f, Prev. LTFprice:%.5f, pivot=%.5f", STF.close[STF.close:size() - 1], LTF.close[LTF.close:size() - 2], pivot.DATA[pivot.DATA:size() - 1]));
end

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


I ran it with a five minute price time frame and a 15 minute pivot time frame, and it updates twice on the quarter hour:

Code: Select all
EUR/USD   MTFPIVOT   STFprice:1.27547, Prev. LTFprice:1.27548, pivot=1.27527   11/07/2012 10:30:00
EUR/USD   MTFPIVOT   STFprice:1.27547, Prev. LTFprice:1.27548, pivot=1.27527   11/07/2012 10:30:00
EUR/USD   MTFPIVOT   MTFPIVOT is started.   11/07/2012 10:23:49
EUR/USD   MARGINALERT(All accounts)   MARGINALERT(All accounts) is started.   11/07/2012 10:23:03
tllewell
 
Posts: 76
Joined: Thu Mar 01, 2012 4:06 pm

Re: Multiple updates running in strategies

Postby tllewell » Wed Nov 07, 2012 7:45 pm

Well, this is not what I would call a proper fix, but I have a workaround for the problem. Create a global variable and save the OLE datetime to it. So, I create

local noRepeat = 0;

I create this with the assignment so it passes the first test of the variable. I assign the OLE value of the short time frame's last candle to this variable. Then test it to see if the current value is already stored, and return if it is:

if STF:date(NOW) == noRepeat then
return;
end

Here is the full code with the change.

Code: Select all
function Init()
    strategy:name("MTFPivot");
    strategy:description("Price crossing pivot point strategy.");
    strategy:type(core.Both);
    strategy:setTag("group", "Support/Resistance");
    strategy:setTag("NonOptimizableParameters", "Email,SendEmail,SoundFile,RecurrentSound,PlaySound,ShowAlert");

    strategy.parameters:addGroup("Time Frame");

    strategy.parameters:addString("ShortTF", "Price Time Frame", "", "m15");
    strategy.parameters:setFlag( "ShortTF", core.FLAG_PERIODS);
    strategy.parameters:addString("LongTF", "Pivot Time Frame", "", "H1");
    strategy.parameters:setFlag( "LongTF", core.FLAG_PERIODS);
    strategy.parameters:addString("Type", "Price Type", "", "Bid");
    strategy.parameters:addStringAlternative("Type", "Bid", "", "Bid");
    strategy.parameters:addStringAlternative("Type", "Ask", "", "Ask");

    strategy.parameters:addGroup("Alerts");

    strategy.parameters:addBoolean("ShowAlert", "Show Alert", "", true);
    strategy.parameters:addBoolean("PlaySound", "Play Sound", "", false);
    strategy.parameters:addBoolean("RecurrentSound", "Recurrent Sound", "", false);
    strategy.parameters:addFile("SoundFile", "Sound File", "", "");
    strategy.parameters:setFlag("SoundFile", core.FLAG_SOUND);
    strategy.parameters:addBoolean("SendEmail", "Send Email", "", false);
    strategy.parameters:addString("Email", "Email address", "Note that to recieve e-mails, SMTP settings must be defined (see Signals Options).", "");
    strategy.parameters:setFlag("Email", core.FLAG_EMAIL);
    strategy.parameters:addColor("clr", "Label Color", "", core.COLOR_LABEL);

    strategy.parameters:addGroup("Trading");
    strategy.parameters:addBoolean("AllowTrade", "Allow strategy to trade?", "If trading is not allowed, the strategy works just as a signal", false);
    strategy.parameters:addBoolean("EuroAm", "Trade European and US hours?", "", false);
    strategy.parameters:addString("Account", "Account", "", "");
    strategy.parameters:setFlag("Account", core.FLAG_ACCOUNT);
    strategy.parameters:addInteger("Amount", "Amount to Trade", "Specify the amount to trade in lots", 1, 1, 1000);
end

local allow;
local offer;
local account;
local amount;
local SoundFile;
local RecurrentSound;
local SendEmail, Email;
local STF;
local LTF;
local priceType;
local requestId;
local noRepeat = 0;

function Prepare()
    local priceType = true;

    if instance.parameters.Type == "Ask" then
       priceType = false;
    end

    STF = ExtSubscribe(20, nil, instance.parameters.ShortTF, priceType, "bar");
    LTF = ExtSubscribe(30, nil, instance.parameters.LongTF, priceType, "bar");

    pivot = core.indicators:create("PIVOT", LTF, instance.parameters.LongTF, "Pivot", "HIST");

    local name = profile:id();
    instance:name(name);

    allow = instance.parameters.AllowTrade;
    if allow then
        account = instance.parameters.Account;
        offer = core.host:findTable("offers"):find("Instrument", instance.bid:instrument()).OfferID;
        amount = core.host:execute("getTradingProperty", "baseUnitSize", instance.bid:instrument(), account);
   canclose = core.host:execute("getTradingProperty", "canCreateMarketClose", instance.bid:instrument(), account);
    end

end

function Enter(side)
   valuemap = core.valuemap();
   valuemap.OrderType = "OM";
   valuemap.OfferID = offer;
   valuemap.AcctID = account;
   valuemap.Quantity = amount;
   valuemap.BuySell = side;
   success, msg = terminal:execute(100, valuemap);
   if not success then
      terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "open trade failed: " .. msg, instance.bid:date(NOW));
   else
      requestId = msg;
   end
end

function Exit(side)
   local enum, row, valuemap, hasTrades;
   if canclose then
      if requestId ~= nil then
         row = core.host:findTable("trades"):find("OpenOrderReqID", requestId);
         if row ~= nil then
            valuemap = core.valuemap();
            valuemap.OrderType = "CM";
            valuemap.OfferID = offer;
            valuemap.AcctID = account;
            valuemap.Quantity = row.Lot;
            valuemap.TradeID = row.TradeID;
            if row.BS == "B" then
               valuemap.BuySell = "S";
            else
            valuemap.BuySell = "B";
            end
         success, msg = terminal:execute(101, valuemap);
            if not success then
               terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "close trade failed: " .. msg, instance.bid:date(NOW));
            end
         end
      end
   else
      enum = core.host:findTable("trades"):enumerator();
      hasTrades = false;
      while not hasTrades do
         row = enum:next();
         if row == nil then
            break;
         end
         if row.AccountID == account and
         row.OfferID == offer and
         row.BS == side then
            hasTrades = true;
         end
      end
      if hasTrades then
         valuemap = core.valuemap();
         valuemap.OrderType = "CM";
         valuemap.OfferID = offer;
         valuemap.AcctID = account;
         valuemap.NetQtyFlag = "y";
         if side == "B" then
            valuemap.BuySell = "S";
         else
            valuemap.BuySell = "B";
         end
         success, msg = terminal:execute(101, valuemap);
         if not success then
            terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "close trade failed: " .. msg, instance.bid:date(NOW));
         end
      end

        end
end

function AsyncOperationFinished(cookie, success, msg)
    if cookie == 100 then
      if not success then
         terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "open trade failed: " .. msg, instance.bid:date(NOW));
   elseif cookie == 101 then
      if not success then
         terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "close trade failed: " .. msg, instance.bid:date(NOW));
      end
   end
    end
end

function ExtUpdate(id, source, period)


pivot:update(core.UpdateLast);

if STF:date(NOW) == noRepeat then
   return;
end

if pivot.DATA[pivot.DATA:size() -1] == 0 then
       return;
   end

   if STF.low[STF.low:size() - 2] > pivot.DATA[pivot.DATA:size() - 1] and
      allow then
         Enter("B");
         Exit("S");
   end

   if STF.high[STF.high:size() - 2] < pivot.DATA[pivot.DATA:size() - 1] and
      allow then
         Enter("S");
         Exit("B");
   end

   
   noRepeat = STF:date(NOW);


core.host:trace(string.format("STFprice:%.5f, Prev. LTFprice:%.5f, datetime=%f", STF.close[STF.close:size() - 1], LTF.close[LTF.close:size() - 2], noRepeat));
end

dofile(core.app_path() .. "\\strategies\\standard\\include\\helper.lua");
tllewell
 
Posts: 76
Joined: Thu Mar 01, 2012 4:06 pm

Re: Multiple updates running in strategies

Postby Apprentice » Mon Nov 12, 2012 5:05 am

Try this code.

function ExtUpdate(id, source, period)
if id ~= 20 then
return;
end


...
end

This will ensure, that you have only one update
Just for lower time frame.
User avatar
Apprentice
FXCodeBase: Confirmed User
 
Posts: 36341
Joined: Thu Dec 31, 2009 11:59 am
Location: Zagreb, Croatia

Re: Multiple updates running in strategies

Postby tllewell » Mon Nov 12, 2012 10:14 pm

Yes, that works fine, and much more elegant that my little kludge. :D
tllewell
 
Posts: 76
Joined: Thu Mar 01, 2012 4:06 pm

Re: Multiple updates running in strategies

Postby boss_hogg » Thu Jan 31, 2013 3:42 pm

I have a similar problem only slightly more complicated.

I'm working on a strategy using two time frames: the trading tf (eg 1H) and a larger one , the major tf (eg 4H)

The strategy takes into account the last closed candle of both time frames. I use ExtSubscribe to create two sources in the two time frames and extUpdate(id, source, period) like this:

if id==1 then update trading tf indicators...
if id==2 then update major tf indicators...
if all indicators are up to date, continue with strategy logic...

My problem is this: when the trading tf candle and the major tf candle close at the same time, I want to be sure that both trading and major tf indicators have been updated before proceeding to the strategy logic. Since there is not knowing which tf is updated first, when the trading tf updates I cannot know if the major was also updated.

If I could know whether the current period is applicable to both time frames, I could solve this...

Any ideas are welcome!
boss_hogg
FXCodeBase: Confirmed User
 
Posts: 48
Joined: Fri Oct 26, 2012 3:03 am

Next

Return to Discussions

Who is online

Users browsing this forum: No registered users and 11 guests