Safer way to close all trades for the chosen offer/account

Moderator: admin

Safer way to close all trades for the chosen offer/account

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

The first indicator development article describes the following way to close all trades on chosen instrument and account via enumerator.

Code: Select all
function closeall(account, instrument, sell)
    local enum, row, valuemap, side, closed;
    local offer;
    local valuemap;
    local CanClose;

    -- get offer id and check whether close order can be used for the specified instrument and account.
    offer = core.host:findTable("offers"):find("Instrument", instrument).OfferID;
    CanClose = core.host:execute("getTradingProperty", "canCreateMarketClose", instrument, account);

    -- just prepare the name of the direction ("S" for sell and "B" for buy).
    if sell then
        side = "S";
    else
        side = "B";
    end

    -- the flag indicating whether at least one position is closed.
    closed = false;

    -- get a enumerator for the "open trades" trading table
    enum = core.host:findTable("trades"):enumerator();

    -- and scan trough all table rows. one row is one trade.
    while true do
        row = enum:next();
        if row == nil then
            break;
        end

        -- if trade was placed for chosen account and instrument
        -- and the trade is in the requested side - close it
        if row.AccountID == account and
           row.OfferID == offer and
           row.BS == side then
            -- use different close models depending on the account type
            if CanClose then
                -- non-NFA accounts, can use Market Close order
                valuemap = core.valuemap();
                valuemap.Command = "CreateOrder";
                valuemap.OrderType = "CM";      -- close market order
                valuemap.OfferID = OfferID;
                valuemap.AcctID = Account;
                valuemap.Quantity = row.Lot;    -- the size is required because we can close the position partially
                valuemap.TradeID = row.TradeID; -- the trade must be referenced int he close order
                -- the side of the close order must be opposite to the side of the trade.
                if row.BS == "B" then
                    valuemap.BuySell = "S";
                else
                    valuemap.BuySell = "B";
                end
                -- and execute
                local success, msg;
                success, msg = terminal:execute(200, valuemap);
                assert(success, msg);
            else
                -- NFA accounts. We cannot call close orders but can
                -- execute an opposite open order. Since NFA accounts can
                -- never be hedging accounts, the opposite open order
                -- closes the existing positions first.
                valuemap = core.valuemap();
                valuemap.OrderType = "OM";
                valuemap.Command = "CreateOrder";
                valuemap.OfferID = OfferID;
                valuemap.AcctID = Account;
                valuemap.Quantity = row.Lot;
                if row.BS == "B" then
                    valuemap.BuySell = "S";
                else
                    valuemap.BuySell = "B";
                end
                local success, msg;
                success, msg = terminal:execute(200, valuemap);
                assert(success, msg);
            end
            -- we closed the position, so we should not open anything.
            closed = true;
        end
    end
    return closed;
end


The function enumerates all the trades and closes those of them which are opened in the specified direction for the specified account and the specified side (buy or sell).

This function has a number of lacks in case many trades must be closed:

a) In fact, the trades table is not refreshed exactly in the same moment when the trade is closed on the server. The update takes 250ms-1sec. Therefore, there is a chance that the function will try to close a trade which is already closed on the server. In case the close orders are prohibited, and, therefore, opposite order is used, this method will open an opposite position instead of closing.

b) The trades table changes dynamically, every time when new information is received from the server, so, it can skip some trades, for example, in case some trades appears or disappears during the enumeration loop is being executed.

To avoid this feature I recommend to use netting close orders which are available on any account, including FIFO accounts. These orders closes all existing trades for the specified account and specified instrument opened in the direction opposite to the order direction.

Here is an example of using of the netting order:

Code: Select all
function closeall(account, instrument, sell)
    local enum, row, valuemap, side, closed;
    local offer;
    local valuemap;
    local CanClose;

    -- get offer id and check whether close order can be used for the specified instrument and account.
    offer = core.host:findTable("offers"):find("Instrument", instrument).OfferID;

    valuemap = core.valuemap();
    valuemap.OrderType = "CM";
    valuemap.AcctID = account;
    valuemap.OfferID = offer;
    valuemap.TradeID = "all";
    -- set an opposite direction
    if sell then
        side = "B";
    else
        side = "S";
    end
    valuemap.NetQtyFlag = "Y";
    success, msg = terminal:execute(300, valuemap);
    if not(success) then
        assert(success, msg);
    end
end
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1234
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 1 guest