enumerator problem

Moderator: admin

enumerator problem

Postby Newmmy » Fri Sep 10, 2010 6:17 am

Hi,

i would like to discuse one problem, which i figured out and i didnt find thread, where to place my question. So I'm sorry about this. But I really need to fix following problem:

Code: Select all
function CloseTrade(side)

    local enum, row, valuemap;

    enum = core.host:findTable("trades"):enumerator();
   row = enum:next();
    while row ~= nil do

        if row.BS == side then
         valuemap = core.valuemap();

         if CANCLOSE then
            -- non-FIFO account, create a close market order
            valuemap.OrderType = "CM";
            valuemap.Quantity = row.Lot;
            valuemap.TradeID = row.TradeID;
         else
            -- FIFO account, create an opposite market order
            valuemap.OrderType = "OM";
            valuemap.Quantity = AMOUNT;
         end

         valuemap.OfferID = OFFER;
         valuemap.AcctID = ACCOUNT;
         valuemap.CustomID = CID;

         if row.BS == "B" then
            valuemap.BuySell = "S";
         else
            valuemap.BuySell = "B";
         end

         success, msg = terminal:execute(200, valuemap);
         assert(success, msg);
        end

      row = enum:next();
    end
end


thi function should end opened position according to parameter side (sell or buy pos.), but problem is that its not pass all elements. It forget to check last row(trade) and it still open. My question is, if its just me or another guys have same problem?
how to fix this?
I tried recursive calling of this function (looks little bit differently), but the problem is still there even I thought that position will be reseted and its not.

when Im debugging that code. I can see there 2 opened position (both Sell), but closed is just one. During second cycle is row nil and then its of course end of the function.....
As I said, I tried recursive calling of it -> same results. Also I tried somehow to reset enum via function enum:reset() its not help either.

For me It looks like a bug in source code....any advice? Is there any function which has to be presented in strategy or anything else?
Newmmy
 
Posts: 3
Joined: Fri Sep 10, 2010 4:17 am

Re: enumerator problem

Postby Nikolay.Gekht » Fri Sep 10, 2010 11:28 am

Is the last position you mentioned created for the same instrument and account?
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1223
Joined: Wed Dec 16, 2009 6:39 pm
Location: Cary, NC

Re: enumerator problem

Postby Newmmy » Fri Sep 10, 2010 11:34 am

Nikolay.Gekht wrote:Is the last position you mentioned created for the same instrument and account?


yes, everything is created for one pair and on one account
Newmmy
 
Posts: 3
Joined: Fri Sep 10, 2010 4:17 am

Re: enumerator problem

Postby Nikolay.Gekht » Fri Sep 10, 2010 1:00 pm

Oh, I see. Under the debugger, when trade disappears inside the enumeration, it will skip the next value. I'll double-check TS behavior and then decide whatever I can do with that.
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1223
Joined: Wed Dec 16, 2009 6:39 pm
Location: Cary, NC

Re: enumerator problem

Postby Nikolay.Gekht » Fri Sep 10, 2010 1:15 pm

Under TS it's ok. The enumerator above lists all the trades.
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1223
Joined: Wed Dec 16, 2009 6:39 pm
Location: Cary, NC

Re: enumerator problem

Postby Newmmy » Tue Sep 14, 2010 1:34 am

Nikolay.Gekht wrote:Under TS it's ok. The enumerator above lists all the trades.



I'm little bit confused now. Whats TS?
For me its not working even i marketscope. I would like to send here an img for illustration of that problem in marketscope, but i dont know how to do it.
Newmmy
 
Posts: 3
Joined: Fri Sep 10, 2010 4:17 am

Re: enumerator problem

Postby Nikolay.Gekht » Tue Sep 14, 2010 12:11 pm

TS is for "Trading Station", the real trading application which uses these indicators and strategies. Marketscope is a part of this application. Sometimes all the users here uses this abbreviation.

BTW, I updated the SDK, so, now, in debugger, if trade is closed inside the loop, the enumeration is not broken.

Ok. Let's look at the situation a bit carefully. Surely, if you have, for example, a trade with stop attached, the trade can disappear while the strategy enumerates it. Just because stop order is executed. This can affect enumeration. So, any trading application in first is made to provide the most fresh data and will always update it's data in background. all, such as Trading Station, Metatrader, Stategy Trader does it in this way.

Moreover, there is some lag between the order is executed (or trade is closed) on the server side and the information about that fact is delivered to the client. So, the following situation also possible - for example trade is already closed, but at the moment when your strategy decides do close - the trade is still visible in TS. It usually takes about a second to show the trade closed in TS, but strategy is fast enough to run into this situation. In case there is FIFO account (i.e. you use open order to close position), the careless logic can open opposite position instead of closing.

The first example I provided is rather about "how write a simple strategy" rather than "how to use all the available orders properly". This is a big thing to discuss. In short, in the real life, the way to close all chosen positions is strongly not recommended. Trading Station itself uses "netting" orders to close all positions in chosen direction/for chosen instrument and account. This order buys or sells only for the amount the user has at the moment of the order execution, so it's much safer, especially for FIFO accounts.

I'm going to make a number of articles about the proper usage of FXCM's FIX orders.
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1223
Joined: Wed Dec 16, 2009 6:39 pm
Location: Cary, NC

Re: enumerator problem

Postby Nikolay.Gekht » Tue Sep 14, 2010 12:12 pm

Newmmy wrote:For me its not working even i marketscope. I would like to send here an img for illustration of that problem in marketscope, but i dont know how to do it.

BTW, you can contact me directly via email nikolay.gekht(at)gehtsoftusa(dot)com, do discuss the particular problem in details.
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1223
Joined: Wed Dec 16, 2009 6:39 pm
Location: Cary, NC

Re: enumerator problem

Postby Nikolay.Gekht » Tue Sep 14, 2010 12:46 pm

BTW, there is an example of for my further article which shows the whole lifecycle of the trade. The strategy opens specified number of trades, then wait until they appears in the tables, then closes them and then then waits until they disappears from the tables

Code: Select all
-- indicator initialization
function Init()
    strategy:name("Opens and then closes positions");
    strategy:description("");

    strategy.parameters:addString("ACCOUNT", "Choose Account", "", "");
    strategy.parameters:setFlag("ACCOUNT", core.FLAG_ACCOUNT);
    strategy.parameters:addInteger("TRADES", "Number of trades to create", "", 1, 1, 20);
end

-- trade info
local bid, ask;                     -- bid and ask prices
local account;                      -- account id
local offer;                        -- offer id
local amount;                       -- minimal trade amount
local canclose;                     -- flag indicating whether close orders can be used
local trades_num;                   -- number of trades to create

-- state
local INIT = 0;                     -- initial state
local CREATING = 1;                 -- open orders are sent
local CREATED = 2;                  -- open orders are executed
local WAITING_RECEIVE = 3;          -- waiting until trades are received
local RECEIVED = 4;                 -- trades are received
local CLOSING = 5;                  -- close orders are sent
local CLOSED = 6;                   -- close orders are executed
local WAITING_REMOVE = 7;           -- waiting until trades are removed
local FINISH = 8;                   -- finished successful
local FAILED = 9;                   -- failed

local step = INIT;                  -- current state

local open_order_finished = {};     -- flags indicating that open order has been finished
local close_order_finished = {};    -- flags indicating that close order has been finished
local trade_received = {};          -- flags indicating that trade is received
local trade_not_removed = {};       -- flags indicating that trade is removed
local request_ids = {};             -- request identifiers -> to array index map.

local tick_count = 0;

function Prepare()
    -- store parameter data (chosen instrument prices and account)
    bid = instance.bid;
    ask = instance.ask;
    account = instance.parameters.ACCOUNT;
    trades_num = instance.parameters.TRADES;

    -- get additional trading data
    canclose = core.host:execute("getTradingProperty", "canCreateMarketClose", bid:instrument(), account)
    amount = core.host:execute("getTradingProperty", "baseUnitSize", bid:instrument(), account);
    offer = core.host:findTable("offers"):find("Instrument", bid:instrument()).OfferID;
end

-- on tick
function Update()
    local valuemap, enum, row;

    tick_count = tick_count + 1;

    if step == INIT then
        -- create orders
        terminal:alertMessage(bid:instrument(), bid[bid:size() - 1], "Started" .. "(tick:" .. tick_count .. ")", bid:date(bid:size() - 1));
        openall();
        step = CREATING;

    elseif step == CREATING then
        -- trades are being created, do nothing

    elseif step == CREATED then
        -- trades are created... start while they appear inside the trades table
        terminal:alertMessage(bid:instrument(), bid[bid:size() - 1], "Trades Created" .. "(tick:" .. tick_count .. ")", bid:date(bid:size() - 1));
        step = WAITING_RECEIVE;

    elseif step == WAITING_RECEIVE then
        -- trades are being transferred back, check whether all the trades appeared
        enum = core.host:findTable("trades"):enumerator();
        row = enum:next();
        while row ~= nil do
            -- this is request id of the order which were used to create the trade
            local openRequestID = row.OpenOrderReqID;
            local index = request_ids[openRequestID];
            if index ~= nil then
                -- the trade is our trade, mark that trade has been succesfully received
                trade_received[index] = true;
            end
            row = enum:next();
        end

        -- if all the trades are found in the table - go to the next step.
        if all_true(trade_received) then
            step = RECEIVED;
        end

    elseif step == RECEIVED then
        -- trades are received - close them
        terminal:alertMessage(bid:instrument(), bid[bid:size() - 1], "Trades Received" .. "(tick:" .. tick_count .. ")", bid:date(bid:size() - 1));
        closeall();
        step = CLOSING;

    elseif step == CLOSING then
        -- trades are being closed, do nothing

    elseif step == CLOSED then
        terminal:alertMessage(bid:instrument(), bid[bid:size() - 1], "Trades Closed" .. "(tick:" .. tick_count .. ")", bid:date(bid:size() - 1));
        step = WAITING_REMOVE;

    elseif step == WAITING_REMOVE then
        -- trades was closed, check whether all of them succesfully disappered

        for i = 1, trades_num, 1 do
            trade_not_removed[i] = false;
        end

        enum = core.host:findTable("trades"):enumerator();
        row = enum:next();
        while row ~= nil do
            -- this is request id of the order which were used to create the trade
            local openRequestID = row.OpenOrderReqID;
            local index = request_ids[openRequestID];
            if index ~= nil then
                -- the trade is our trade, mark that trade hasn't been removed yet.
                trade_not_removed[index] = true;
            end
            row = enum:next();
        end

        -- if none of the trade appears - finish task
        if all_false(trade_not_removed) then
            step = FINISHED;
            terminal:alertMessage(bid:instrument(), bid[bid:size() - 1], "Task finished" .. "(tick:" .. tick_count .. ")", bid:date(bid:size() - 1));
        end
    end
end

-- notification that asynchronous operation has been finished
-- sending of the trade order is asynchrnous, i.e. you just
-- requests for the operation, but the actual result will be
-- passed later to this (AsyncOperationFinished) function.
function AsyncOperationFinished(id, success, msg)
    if id >= 101 and id <= 100 + trades_num then
        -- it's a response for open trade request
        if not(success) then
            -- open order failed
            terminal:alertMessage(bid:instrument(), bid[bid:size() - 1], "Open order failed" .. msg, bid:date(bid:size() - 1));
            step = FAILED;
        else
            -- open order executed - mark that order has been executed
            open_order_finished[id - 100] = true;
            if all_true(open_order_finished) then
                step = CREATED;
            end
        end
    elseif id >= 201 and id <= 200 + trades_num then
        if not(success) then
            -- close order failed
            terminal:alertMessage(bid:instrument(), bid[bid:size() - 1], "Close order failed" .. msg, bid:date(bid:size() - 1));
            step = FAILED;
        else
            -- close order executed - mark that order has been executed
            close_order_finished[id - 200] = true;
            if all_true(close_order_finished) then
                step = CLOSED;
            end
        end
    end
end

-- open all orders
function openall()
    local i;
    local request_id
    for i = 1, trades_num, 1 do
        -- open trade
        request_id = openone(100 + i);          -- operation id
        if request_id == nil then
            return ;
        end
        -- keep index in the open_order_finished, close_order_finished, trade_received and trade_not_removed
        -- for the returned request id
        request_ids[request_id] = i;

        -- prepare watching tables
        open_order_finished[i] = false;
        close_order_finished[i] = false;
        trade_received[i] = false;
    end
end

-- open one trade
function openone(operation_id)
    local valuemap, success, msg;
    valuemap = core.valuemap();

    valuemap.OrderType = "OM";
    valuemap.OfferID = offer;
    valuemap.AcctID = account;
    valuemap.Quantity = amount;
    valuemap.BuySell = "B";
    success, msg = terminal:execute(operation_id, valuemap);
    if success then
        return msg;         -- request_id
    else
        terminal:alertMessage(bid:instrument(), bid[bid:size() - 1], "Open order failed" .. msg, bid:date(bid:size() - 1));
        step = FAILED;
        return nil;
    end
end

-- close all previously opended positions
function closeall()
    local enum, row, valuemap, success, msg;

    enum = core.host:findTable("trades"):enumerator();
    row = enum:next();
    while row ~= nil do
        -- this is request id of the order which were used to create the trade
        local openRequestID = row.OpenOrderReqID;
        local index = request_ids[openRequestID];
        if index ~= nil then
            -- the trade is our trade, remove it!
            valuemap = core.valuemap();
            if canclose then
                valuemap.OrderType = "CM";
                valuemap.TradeID = row.TradeID;
            else
                valuemap.OrderType = "OM";
            end
            valuemap.Quantity = row.Lot;
            valuemap.OfferID = offer;
            valuemap.AcctID = account;
            if row.BS == "B" then
                valuemap.BuySell = "S";
            else
                valuemap.BuySell = "B";
            end
            success, msg = terminal:execute(200 + index, valuemap);
            if not(success) then
                terminal:alertMessage(bid:instrument(), bid[bid:size() - 1], "Close order failed" .. msg, bid:date(bid:size() - 1));
                step = FAILED;
                return ;
            end
        end
        row = enum:next();
    end

end

-- checks whether all flags are true in the specified array
function all_true(array)
    local ret_code = true;
    local i;

    for i = 1, trades_num, 1 do
        ret_code = (ret_code and array[i]);
    end
    return ret_code;
end

-- checks whether all flags are true in the specified array
function all_false(array)
    local ret_code = false;
    local i;

    for i = 1, trades_num, 1 do
        ret_code = (ret_code or array[i]);
    end
    return not(ret_code);
end


shot.png
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1223
Joined: Wed Dec 16, 2009 6:39 pm
Location: Cary, NC

Re: enumerator problem

Postby Nikolay.Gekht » Wed Sep 15, 2010 9:49 am

Please also read this article about using netting close orders viewtopic.php?f=28&t=2177
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1223
Joined: Wed Dec 16, 2009 6:39 pm
Location: Cary, NC


Return to Indicator Development

Who is online

Users browsing this forum: No registered users and 2 guests