Why is row.Limit returns 0 ?

If you need an Indicator or Signal developed or translated from other language, please post all Indicator development REQUESTS to this section here.

Moderator: admin

Why is row.Limit returns 0 ?

Postby conjure » Tue May 07, 2019 12:21 pm

I m trying to get the limit from an opened position but it keeps returning zero.
Any ideas why?
Code: Select all
createTrueMarketOrder("B", Amount, symbol, 100, false, 100);

   local enum, row
enum = core.host:findTable("Orders"):enumerator()
row = enum:next()
while row ~= nil do
if row.Instrument == symbol
then
lim=row.Limit
end
row = enum:next()
end
            
   
   terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], lim, instance.bid:date(NOW));

         core.host:execute ("stop");
conjure
FXCodeBase: Initiate
 
Posts: 135
Joined: Sat Jul 22, 2017 7:27 am

Re: Why is row.Limit returns 0 ?

Postby Apprentice » Thu May 09, 2019 1:02 pm

You can use something like this.

Code: Select all
function IsLimitOrderType(order_type) return order_type == "L" or order_type == "LE" or order_type == "LT" or order_type == "LTE"; end

function FindLimitOrder(trade) local can_close = core.host:execute("getTradingProperty", "canCreateMarketClose", trade.Instrument, trade.AccountID); if can_close then local order_id; if trade.LimitOrderID ~= nil and trade.LimitOrderID ~= "" then order_id = trade.LimitOrderID; end if order_id ~= nil then return core.host:findTable("orders"):find("OrderID", order_id); end else local enum = core.host:findTable("orders"):enumerator(); local row = enum:next(); while (row ~= nil) do if row.ContingencyType == 3 and IsLimitOrderType(row.Type) then return row; end row = enum:next(); end end return nil; end
User avatar
Apprentice
FXCodeBase: Confirmed User
 
Posts: 36341
Joined: Thu Dec 31, 2009 11:59 am
Location: Zagreb, Croatia

Re: Why is row.Limit returns 0 ?

Postby conjure » Mon May 13, 2019 7:55 am

Hi Apprentice..

I tried to understand how to use these functions , but i m getting errors all the time.
Is it possible to give me a working example.lua so i can understand how to use the code?
Thank you!
conjure
FXCodeBase: Initiate
 
Posts: 135
Joined: Sat Jul 22, 2017 7:27 am


Re: Why is row.Limit returns 0 ?

Postby conjure » Tue May 14, 2019 8:50 am

Sure..This is the code where i am trying to get Limit and Stop from an opened position and both values return zero.

Code: Select all


-----------------------------------------------------------
-- Standard strategy init handler for marketscope strategy
-----------------------------------------------------------
function Init()
    strategy:name("giannis");

   
    strategy:type(core.Both);
   

   
   
   
   
   strategy.parameters:addGroup("------------------------------General parameters------------------------------");

   
   
    strategy.parameters:addString("Account", "Account", "", "");
    strategy.parameters:setFlag("Account", core.FLAG_ACCOUNT);
       strategy.parameters:addInteger("Amount", "Trade Amount in Lots", "", 1, 1, 10000);

    strategy.parameters:addBoolean("AllowTrade", "Allow trade", "", true);
    strategy.parameters:setFlag("AllowTrade", core.FLAG_ALLOW_TRADE);
    strategy.parameters:addString("AllowedSide", "Allowed side", "Allowed side for trading or signaling, can be Sell, Buy or Both", "Both");
    strategy.parameters:addStringAlternative("AllowedSide", "Both", "", "Both");
    strategy.parameters:addStringAlternative("AllowedSide", "Buy", "", "Buy");
    strategy.parameters:addStringAlternative("AllowedSide", "Sell", "", "Sell");
   
    strategy.parameters:addBoolean("AllowMultiplePositions", "Allow multiple positions", "", true);

    strategy.parameters:addString("tf", "tf_for_HH_LL", "The used timeframe", "m30");
    strategy.parameters:setFlag("tf", core.FLAG_PERIODS);

end



local mCID= "FXSW_STRATEGY";
local mAccount;
local mLotSize;
local mAllowTrade = false;
local Amount;



local mAllowedSide = "Both";
local mPlaySound = false;
local mReccurentSound = false;
local mSendEmail = true;
local mShowAlert = false;

local mEmail;
local mAllowMultiplePositions = true;

local tf;



local symbol;


local source;
local id_source = 101;




-----------------------------------------------------------
-- Standard prepare handler for marketscope strategy
-----------------------------------------------------------
function Prepare(onlyName)
    assert(instance.parameters.tf ~= "t1", "Tick is not allowed for tf parameter");
       
   

    -- collect parameters
   symbol = instance.bid:instrument();
    mAccount = instance.parameters.Account;
    mLotSize = core.host:execute("getTradingProperty", "baseUnitSize", instance.bid:instrument(), mAccount);
    mAllowTrade = instance.parameters.AllowTrade;
    mAllowedSide = instance.parameters.AllowedSide;
   Amount = instance.parameters.Amount;
   mSendEmail = instance.parameters.SENDEMAIL;
    mEmail = instance.parameters.EMAIL;
    mAllowMultiplePositions = instance.parameters.AllowMultiplePositions;
   mShowAlert = instance.parameters.SHOWALERT;

   
   
    tf = instance.parameters.tf;

   


   
   
    --set name
    instance:name(profile:id() .. "(" .. instance.bid:instrument()  .. "(" .. tf  .. "))");
 
    if onlyName then
        return;
    end

    source = ExtSubscribe(id_source, symbol, tf, true, "bar");


   

end

-----------------------------------------------------------
-- 'Event handler' that is called when a datasource is updated
-----------------------------------------------------------


function ExtUpdate(id, updatedSource, period)
    if not checkReady("trades") or not checkReady("summary") then
        return;
    end
   



    -- update expressions
    -- processing of Activation points

    if id==id_source then --Updates handler of 'source' datasource ('tf'  timeframe)
         


createTrueMarketOrder("B", Amount, symbol, 100, false, 200);


   local enum, row
enum = core.host:findTable("Orders"):enumerator()
row = enum:next()
while row ~= nil do
if row.Instrument == symbol
then
limit=row.Limit
stop=row.Stop

end
row = enum:next()
end
           
   
   terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], limit, instance.bid:date(NOW));
   terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], stop, instance.bid:date(NOW));

         core.host:execute ("stop");
            
            end

            
         
         

end   
   
   


function IsLimitOrderType(order_type)
return order_type == "L" or order_type == "LE" or order_type == "LT" or order_type == "LTE";
 end


function FindLimitOrder(trade)
local can_close = core.host:execute("getTradingProperty", "canCreateMarketClose", trade.Instrument, trade.AccountID);
if can_close then
local order_id;
if trade.LimitOrderID ~= nil and trade.LimitOrderID ~= ""
then order_id = trade.LimitOrderID;
 end
 
 if order_id ~= nil
 then return
 core.host:findTable("orders"):find("OrderID", order_id);
 end
 
 else
 
 local enum = core.host:findTable("orders"):enumerator();
 local row = enum:next();
 while (row ~= nil) do
 if row.ContingencyType == 3 and IsLimitOrderType(row.Type)
 then return row;
 end
 row = enum:next(); end
 end
 return nil;
 end












function checkReady(tableName)
    return core.host:execute("isTableFilled", tableName);
end

-----------------------------------------------------------
--Enters to the market
--   side: B - BUY or S - SELL
--   amount: order amount
--   instrumentName: instrument of order
--   stop:  0, 1 or greater value
--   isTrailingStop: true/false
--   limit: 0, 1 or greater value
-----------------------------------------------------------
function createTrueMarketOrder(side, amount, instrumentName, stop, isTrailingStop, limit)
    if not mAllowTrade then
        return;
    end
   
    local offerId = core.host:findTable("offers"):find("Instrument", instrumentName).OfferID;     
   
    if not (mAllowedSide == "Both" or (mAllowedSide == "Buy" and side == "B") or (mAllowedSide == "Sell" and side == "S")) then
        return;
    end
   
    if not mAllowMultiplePositions then
       if (side == 'B' and countLongPositions(instrumentName) > 0) then
           return;
       elseif (side == 'S' and countShortPositions(instrumentName) > 0) then
           return;
       end
    end
   
   

   
    local valuemap;
   

amount=getBalance()/2000
amount=math.floor(amount)
if amount<1 then amount=1 end


    valuemap = core.valuemap();
    valuemap.Command = "CreateOrder";
    valuemap.OrderType = "OM";
    valuemap.OfferID = offerId;
    valuemap.AcctID = mAccount;
    valuemap.GTC = "FOK"; --Fill or Kill order to avoid partial execution
    valuemap.Quantity = amount * mLotSize;
    valuemap.BuySell = side;
    valuemap.CustomID = mCID;
    if stop >= 1 then
        valuemap.PegTypeStop = "M";
        if side == "B" then
            valuemap.PegPriceOffsetPipsStop = - stop;
        else
            valuemap.PegPriceOffsetPipsStop = stop;
        end
        if isTrailingStop then
           valuemap.TrailStepStop = 1;
        end
    end
    if limit >= 1 then
        valuemap.PegTypeLimit = "M";
        if side == "B" then
            valuemap.PegPriceOffsetPipsLimit = limit;
        else
            valuemap.PegPriceOffsetPipsLimit = -limit;
        end
    end

    if (not canClose(instrumentName)) and (stop >= 1 or limit >= 1) then
        valuemap.EntryLimitStop = 'Y'
    end
   
    success, msg = terminal:execute(200, valuemap);
    assert(success, msg);
end



-----------------------------------------------------------
-- closes all positions of the specified direction (B for buy, S for sell)
-----------------------------------------------------------
function canClose(instrumentName)
    return core.host:execute("getTradingProperty", "canCreateMarketClose", instrumentName, mAccount);
end

function close(side, offer)
    local enum, row, valuemap;

    enum = core.host:findTable("trades"):enumerator();
    while true do
        row = enum:next();
        if row == nil then
            break;
        end
        if row.AccountID == mAccount and
           row.OfferID == offer and
           row.BS == side and
           row.QTXT == mCID then
            -- if trade has to be closed

            if canClose(row.Instrument) then
                -- create a close market order when hedging is allowed
                valuemap = core.valuemap();
                valuemap.OrderType = "CM";
                valuemap.OfferID = offer;
                valuemap.AcctID = mAccount;
                valuemap.Quantity = row.Lot;
                valuemap.TradeID = row.TradeID;
                valuemap.CustomID = mCID;
                if row.BS == "B" then
                    valuemap.BuySell = "S";
                else
                    valuemap.BuySell = "B";
                end
                success, msg = terminal:execute(200, valuemap);
                assert(success, msg);
            else               
                -- create an opposite market order when FIFO
                valuemap = core.valuemap();
                valuemap.OrderType = "OM";
                valuemap.OfferID = offer;
                valuemap.AcctID = mAccount;
                valuemap.Quantity = row.Lot;
                valuemap.CustomID = mCID;
                if row.BS == "B" then
                    valuemap.BuySell = "S";
                else
                    valuemap.BuySell = "B";
                end
                success, msg = terminal:execute(200, valuemap);
                assert(success, msg);
            end
        end
    end
end

-----------------------------------------------------------
--Handle command execution result
-----------------------------------------------------------
function ExtAsyncOperationFinished(cookie, success, message)
    if cookie == 1 then
        loaded = true;
    elseif cookie == 200 then
        assert(success, message);
    end
   
end

-----------------------------------------------------------
-- Helper functions
-----------------------------------------------------------
function getOppositeSide(side)
    if(side == "B") then
        return "S";
    else
        return "B";
    end
end

function getDSPeriod(ds, updatedSource, period)
    local p;
    if ds:isBar() then
        p = core.findDate(ds.open, updatedSource:date(period), false);
    else
        p = core.findDate(ds, updatedSource:date(period), false);
    end
    if (p > ds:size() - 1) then
        p = ds:size() - 1;
    elseif (p < ds:first()) then
        p = ds:first();
    end
    return p;
end


-----------------------------------------------------------
-- Allow to calculate last closed bar period for ds datasource
-- which has not tick frequency updates
-----------------------------------------------------------
function getClosedPeriod(ds, supposedPeriod)
    --Check if datasource lastdate is closed on updatePeriod or shift supposedPeriod to -1
    if _gUpdatePeriods[ds] == 't1' or _gUpdatePeriods[ds] == nil then
        return supposedPeriod;
    else
        return supposedPeriod - 1;
    end
end

-----------------------------------------------------------
--Helper functions to wrap the table's method call into the simple function call
-----------------------------------------------------------
function streamSize(stream)
    return stream:size();
end

function streamHasData(stream, period)
    return stream:hasData(period);
end

function canCalculate(stream, period)
    return (period >= 0) and (period > stream:first()) and streamHasData(stream, period);
end

-----------------------------------------------------------
-- Helper functions to be sure that you work with a tick stream
-----------------------------------------------------------
function getTickStreamOfPriceType(stream, priceType)
    if stream:isBar() then
        if priceType == "open" then
            return stream.open;
        elseif priceType == "high" then
            return stream.high;   
        elseif priceType == "low" then
            return stream.low;
        elseif priceType == "close" then
            return stream.close;
        elseif priceType == "typical" then
            return stream.typical;
        elseif priceType == "weighted" then
            return stream.weighted;
        elseif priceType == "volume" then
            return stream.volume;
        else
            return stream.close;
        end
    else
       return stream;
    end
end

function selectStream(safeStream, subStream)
    if safeStream:isBar() then
       return subStream;
    else
       return safeStream;
    end
end

---------------------------------------------------------
-- Subscription for updates by datasource timeframe
---------------------------------------------------------

-- 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
    _gUpdatePeriods[sub.stream] = period;
    if sub.tick then
        return sub.stream;
    else
        if type == "open" then
            _gUpdatePeriods[sub.stream.open] = period;
            return sub.stream.open;
        elseif type == "high" then
            _gUpdatePeriods[sub.stream.high] = period;
            return sub.stream.high;
        elseif type == "low" then
            _gUpdatePeriods[sub.stream.low] = period;
            return sub.stream.low;
        elseif type == "close" then
            _gUpdatePeriods[sub.stream.close] = period;
            return sub.stream.close;
        elseif type == "bar" then
            _gUpdatePeriods[sub.stream.open] = period;
            _gUpdatePeriods[sub.stream.high] = period;
            _gUpdatePeriods[sub.stream.low] = period;
            _gUpdatePeriods[sub.stream.close] = period;
            _gUpdatePeriods[sub.stream.median] = period;
            _gUpdatePeriods[sub.stream.typical] = period;
            _gUpdatePeriods[sub.stream.volume] = period;
            _gUpdatePeriods[sub.stream.weighted] = period;
            return sub.stream;
        else
            assert(false, type .. " is unknown");
        end
    end
end

function AsyncOperationFinished(cookie, success, message)
    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)
        end
    end
end

function Update()
    if instance.bid:size() > 0 then
        _gLastTime = instance.bid:date(instance.bid:size() - 1);
    end
    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

---------------------------------------------------------
-- Additional functions
---------------------------------------------------------
local mAccountRow = nil;
local mSummaries = {};

function checkAccountRow()
    if mAccountRow == nil then
        mAccountRow = core.host:findTable("accounts"):find("AccountID", mAccount);
    else
        mAccountRow:refresh();
    end
end

function checkSummaryRow(sInstrument)
    local sOfferID, summaryIter, summaryRow;
   
    if mSummaries[sInstrument] ~= nil then
        --try refresh
        if not (mSummaries[sInstrument]:refresh()) then
            mSummaries[sInstrument] = nil;
        end
    end
   
    --re-read all cache
    if mSummaries[sInstrument] == nil then
        sOfferID = core.host:findTable("offers"):find("Instrument", sInstrument).OfferID;
        summaryIter = core.host:findTable("summary"):enumerator();
        summaryRow = summaryIter:next();
        while summaryRow ~= nil do
            if summaryRow.OfferID == sOfferID then
                mSummaries[sInstrument] = summaryRow;
                break;
            end
            summaryRow = summaryIter:next();
        end
    end
end


function getUsableMarginPercent()
    checkAccountRow()
    return (mAccountRow.UsableMargin / mAccountRow.Equity) * 100
end

function getUsableMargin()
    checkAccountRow()
    return mAccountRow.UsableMargin
end


function getEquity()
   
    checkAccountRow();
    return mAccountRow.Equity;
end

function getBalance()
    checkAccountRow();
    return mAccountRow.Balance;
end

function getProfit()
    checkAccountRow();
    return mAccountRow.Equity - mAccountRow.Balance;
end

function getAmountK(sInstrument)
    local res;
    checkSummaryRow(sInstrument);
    res = mSummaries[sInstrument];
    if res == nil then
        return 0;
    else
        return res.AmountK;
    end
end

function getGrossPL(sInstrument)
    local res;
    checkSummaryRow(sInstrument);
    res = mSummaries[sInstrument];
    if res == nil then
        return 0;
    else
        return res.GrossPL;
    end
end

function getNetPL(sInstrument)
    local res;
    checkSummaryRow(sInstrument);
    res = mSummaries[sInstrument];
    if res == nil then
        return 0;
    else
        return res.NetPL;
    end
end

function getSellAmountK(sInstrument)
    local res;
    checkSummaryRow(sInstrument);
    res = mSummaries[sInstrument];
    if res == nil then
        return 0;
    else
        return res.SellAmountK;
    end
end

function getBuyAmountK(sInstrument)
    local res;
    checkSummaryRow(sInstrument);
    res = mSummaries[sInstrument];
    if res == nil then
        return 0;
    else
        return res.BuyAmountK;
    end
end

function getBuyNetPLPip(sInstrument)
    local res;
    checkSummaryRow(sInstrument);
    res = mSummaries[sInstrument];
    if res == nil then
        return 0;
    else
        return res.BuyNetPLPip;
    end
end

function getSellNetPLPip(sInstrument)
    local res;
    checkSummaryRow(sInstrument);
    res = mSummaries[sInstrument];
    if res == nil then
        return 0;
    else
        return res.SellNetPLPip;
    end
end

function getBuyNetPL(sInstrument)
    local res;
    checkSummaryRow(sInstrument);
    res = mSummaries[sInstrument];
    if res == nil then
        return 0;
    else
        return res.BuyNetPL;
    end
end

function getSellNetPL(sInstrument)
    local res;
    checkSummaryRow(sInstrument);
    res = mSummaries[sInstrument];
    if res == nil then
        return 0;
    else
        return res.SellNetPL;
    end
end


function countPositions(sInstrument)
    local tradesIter, tradeRow, count, sOfferID;
    count = 0;
    if sInstrument ~= nil then
        sOfferID = core.host:findTable("offers"):find("Instrument", sInstrument).OfferID;
    end
    tradesIter = core.host:findTable("trades"):enumerator();
    tradeRow = tradesIter:next();
    while tradeRow ~= nil do
        if (sInstrument == nil or tradeRow.OfferID == sOfferID) then
            count = count + 1;
        end
        tradeRow = tradesIter:next();
    end
    return count;
end

function countLongPositions(sInstrument)
    local tradesIter, tradeRow, count, sOfferID;
    count = 0;
    if sInstrument ~= nil then
        sOfferID = core.host:findTable("offers"):find("Instrument", sInstrument).OfferID;
    end
    tradesIter = core.host:findTable("trades"):enumerator();
    tradeRow = tradesIter:next();
    while tradeRow ~= nil do
        if ((sInstrument==nil or tradeRow.OfferID == sOfferID) and tradeRow.BS == "B") then
            count = count + 1;
        end
        tradeRow = tradesIter:next();
    end
    return count;
end

function countShortPositions(sInstrument)
    local tradesIter, tradeRow, count, sOfferID;
    count = 0;
    if sInstrument ~= nil then
        sOfferID = core.host:findTable("offers"):find("Instrument", sInstrument).OfferID;
    end
    tradesIter = core.host:findTable("trades"):enumerator();
    tradeRow = tradesIter:next();
    while tradeRow ~= nil do
        if ((sInstrument == nil or tradeRow.OfferID == sOfferID) and tradeRow.BS == "S") then
            count = count + 1;
        end
        tradeRow = tradesIter:next();
    end
    return count;
end

function getLastUpdateTime()
    if (_gLastTime == nil) then
        return 0;
    else
        return _gLastTime;
    end
end

function time(hours, minutes, seconds)
    local dtLast;
    dtLast = core.dateToTable(_gLastTime);
    if seconds == nil then
        seconds = 0;
    end
    return core.datetime(dtLast.year, dtLast.month, dtLast.day, hours, minutes, seconds);
end

function isValidDate(checkDate)
   if (checkDate < 1) then
       return false;
   else
       return true;
   end
end

function parseTime(sTime)
    local iDelimHMPos = string.find(sTime, ":");
    local h = tonumber(string.sub(sTime, 1, iDelimHMPos - 1));
    local sTimeTile = string.sub(sTime, iDelimHMPos + 1);
    local iDelimMSPos = string.find(sTimeTile, ":");
    local m, s;
    s = 0;
    if iDelimMSPos == nil then
        m = tonumber(sTimeTile);
    else
        m = tonumber(string.sub(sTimeTile, 1, iDelimMSPos - 1));
        s = tonumber(string.sub(sTimeTile, iDelimMSPos + 1));
    end
    return time(h, m, s);
end

function getPipSize(sInstrument)
    return core.host:findTable("offers"):find("Instrument", sInstrument).PointSize;
end
dofile(core.app_path() .. "\\strategies\\standard\\include\\helper.lua");


conjure
FXCodeBase: Initiate
 
Posts: 135
Joined: Sat Jul 22, 2017 7:27 am

Re: Why is row.Limit returns 0 ?

Postby conjure » Fri May 17, 2019 8:16 am

Apprentice can you help me on how to use the functions?
conjure
FXCodeBase: Initiate
 
Posts: 135
Joined: Sat Jul 22, 2017 7:27 am

Re: Why is row.Limit returns 0 ?

Postby Apprentice » Tue May 21, 2019 4:40 am

You scanned the orders table instead of trades. Also, you scan it
right after the order creation. There will be no trade yet. The trades
table will be updated later on.

You can use this:
Prepare()
...
core.host:execute("subscribeTradeEvents", 42, "trades");
...

ExtAsyncOperationFinished
...
if cookie == 42 then
terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW],
"New trade appeared in the table", instance.bid:date(NOW))
end
...

test.lua
(23.76 KiB) Downloaded 326 times

(it is already inserted into the code)
User avatar
Apprentice
FXCodeBase: Confirmed User
 
Posts: 36341
Joined: Thu Dec 31, 2009 11:59 am
Location: Zagreb, Croatia

Re: Why is row.Limit returns 0 ?

Postby conjure » Tue May 21, 2019 9:04 am

Thank you so much for your help ;)
conjure
FXCodeBase: Initiate
 
Posts: 135
Joined: Sat Jul 22, 2017 7:27 am


Return to Indicator and Signal Requests

Who is online

Users browsing this forum: No registered users and 11 guests