Auto Entry Order with Risk Management not working

Moderator: admin

Auto Entry Order with Risk Management not working

Postby Stance » Tue Sep 01, 2015 4:25 pm

Hi,

I'm trying to automate a strategy to put in 2 entry orders and automatically adjust the trading amount depending on the percentage of the account balance you want to risk.

The strategy runs but doesn't trigger and when I change the "amount" to a fixed number, it works.

Any ideas why the strategy won't trigger?

Code: Select all
--+------------------------------------------------------------------+
--|                                         Entry Order Strategy.lua |
--|                               Copyright © 2014, Gehtsoft USA LLC |
--|                                            http://fxcodebase.com |
--|                                       Developed by : Mario Jemic |
--|                                            mario.jemic@gmail.com |
--|                                        Enhanced by : MooMooForex |
--|                                           http://moomooforex.com |
--+------------------------------------------------------------------+
function Init() --The strategy profile initialization
   strategy:name("Advance Entry Order Strategy");
    strategy:description("v4");
    -- NG: optimizer/backtester hint
    strategy:setTag("NonOptimizableParameters", "ShowAlert,PlaySound,SoundFile,RecurrentSound,SendMail,Email");
   strategy:type(core.Both);
   
   strategy.parameters:addGroup("Trading Parameters");
    strategy.parameters:addString("Account", "Account to trade", "", "");
    strategy.parameters:setFlag("Account", core.FLAG_ACCOUNT);
   strategy.parameters:addString("PriceType", "Price Type", "", "Bid");
    strategy.parameters:addStringAlternative("PriceType", "Bid", "", "Bid");
    strategy.parameters:addStringAlternative("PriceType", "Ask", "", "Ask");

   strategy.parameters:addString("TF", "Bar Time frame", "Bar time frame used if Entry Type base is Previous Close.", "D1");
    strategy.parameters:setFlag("TF", core.FLAG_PERIODS);
   strategy.parameters:addString("BuySell", "Buy or Sell?", "", "B");
    strategy.parameters:addStringAlternative("BuySell", "Buy", "", "B");
    strategy.parameters:addStringAlternative("BuySell", "Sell", "", "S");
   strategy.parameters:addInteger("Distance", "Distance to market (in pips)", "", 9, 0, 1000);
   
   strategy.parameters:addBoolean("SetLimit", "Set Limit Orders", "", true);
    strategy.parameters:addBoolean("SetStop", "Set Stop Orders", "", true);
   
   strategy.parameters:addGroup("Risk Management");
   strategy.parameters:addDouble("RiskPercentage", "Risk Percentage", "Risk Percentage ", 2,0,100);
    strategy.parameters:addString("Type", "Balance/Equity", "", "Balance");
    strategy.parameters:addStringAlternative("Type", "Equity", "", "Equity");
    strategy.parameters:addStringAlternative("Type", "Balance", "", "Balance");
   
    CreateTradingParameters();
end

function CreateTradingParameters()


    strategy.parameters:addGroup("Time Parameters");
    strategy.parameters:addString("StartTime", "Start Time for Trading", "", "00:00:00");
    strategy.parameters:addString("StopTime", "Stop Time for Trading", "", "24:00:00");
   strategy.parameters:addBoolean("UseMandatoryClosing", "Scheduled Terminate", "Terminates the strategy at this time.", false);
    strategy.parameters:addString("ExitTime", "Scheduled Termination Time", "", "23:59:00");
    strategy.parameters:addInteger("ValidInterval", "Valid interval for operation in second", "", 60);
   
   strategy.parameters:addGroup("Repeat Parameters");
    strategy.parameters:addBoolean("Repeat", "Repeat", "Should we repeat this operation periodically. If false, strategy terminates after placing trade.", false);
    strategy.parameters:addInteger("RepeatDelay", "Repeat Delay (mins)", "How many minutes should we wait between repeats", 60);
    strategy.parameters:addBoolean("CloseOrdersOnRepeat", "Close Orders On Repeat", "Should we close any pending orders when we repeat?", false);
    strategy.parameters:addBoolean("ClosePositionsOnRepeat", "Close Positions On Repeat", "Should we close any open positions when we repeat?", false);
    strategy.parameters:addString("CustomID", "Identifier", "This identifier is required to identify previously placed orders by this strategy", "EntryOrderStrat");

    strategy.parameters:addGroup("Alerts");
    strategy.parameters:addBoolean("ShowAlert", "ShowAlert", "", false);
    strategy.parameters:addBoolean("PlaySound", "Play Sound", "", false);
    strategy.parameters:addFile("SoundFile", "Sound File", "", "");
    strategy.parameters:setFlag("SoundFile", core.FLAG_SOUND);
    strategy.parameters:addBoolean("RecurrentSound", "Recurrent Sound", "", false);
    strategy.parameters:addBoolean("SendEmail", "Send Email", "", false);
    strategy.parameters:addString("Email", "Email", "", "");
    strategy.parameters:setFlag("Email", core.FLAG_EMAIL);
end

local offer;
local account;
local amount;
local pipsize;
local BuySell;
local distance;
local SoundFile = nil;
local RecurrentSound = false;
local SetLimit;
local Limit;
local SetStop;
local Stop;
local TrailingStop;
local ShowAlert;
local Email;
local SendEmail;
local BaseSize;
local ValidInterval;
local UseMandatoryClosing;
local canClose;
local source = nil;
-- Don't need to store hour + minute + second for each time
local OpenTime, CloseTime, ExitTime;

local Repeat;
local RepeatDelay;
local CloseOrdersOnRepeat;
local ClosePositionsOnRepeat;
local instanceName;
local first;

local RiskPercentage;
local Type;
local PipCost;
local RPC;      
local Risk;
local lotSize;

--
function Prepare(nameOnly)
    UseMandatoryClosing = instance.parameters.UseMandatoryClosing;     
    ValidInterval = instance.parameters.ValidInterval;
    Repeat = instance.parameters.Repeat;
    RepeatDelay = instance.parameters.RepeatDelay;
    CloseOrdersOnRepeat = instance.parameters.CloseOrdersOnRepeat;
    ClosePositionsOnRepeat = instance.parameters.ClosePositionsOnRepeat;

    instanceName = profile:id() .. "( " .. instance.bid:name() ..  " )";
    instance:name(instanceName);
    instanceName = instanceName .. " " .. instance.parameters.CustomID;
   
    Type = instance.parameters.Type;
   RiskPercentage = instance.parameters.RiskPercentage;

    -- NG: parsing of the time is moved to separate function
    local valid;
    OpenTime, valid = ParseTime(instance.parameters.StartTime);
    assert(valid, "Time " .. instance.parameters.StartTime .. " is invalid");
    CloseTime, valid = ParseTime(instance.parameters.StopTime);
    assert(valid, "Time " .. instance.parameters.StopTime .. " is invalid");
    ExitTime, valid = ParseTime(instance.parameters.ExitTime);
    assert(valid, "Time " .. instance.parameters.ExitTime .. " is invalid");

    assert(instance.parameters.TF ~= "t1", "The time frame must not be tick");

    if nameOnly then
        return ;
    end

    -- this timer will be used to check our conditions every 5 seconds
    core.host:execute("setTimer", 1111, 5);
   
   source = ExtSubscribe(1, nil, instance.parameters.TF, instance.parameters.PriceType == "Bid", "bar");
   
   first=source:first();
   
   PipCost = core.host:findTable("offers"):find("Instrument", source:instrument()).PipCost;
   
   local name;
    name = profile:id() .. "( " .. instance.bid:name();
    local i;
   
    name = name  ..  " )";
    instance:name(name);
   
    if UseMandatoryClosing then
        core.host:execute("setTimer", 1001, math.max(ValidInterval / 2, 1));
    end
   
   PrepareTrading();
end

function PrepareTrading()
    local PlaySound = instance.parameters.PlaySound;
    if PlaySound then
        SoundFile = instance.parameters.SoundFile;
    else
        SoundFile = nil;
    end
    assert(not(PlaySound) or (PlaySound and SoundFile ~= ""), "Sound file must be chosen");

    ShowAlert = instance.parameters.ShowAlert;
    RecurrentSound = instance.parameters.RecurrentSound;

    SendEmail = instance.parameters.SendEmail;

    if SendEmail then
        Email = instance.parameters.Email;
    else
        Email = nil;
    end
    assert(not(SendEmail) or (SendEmail and Email ~= ""), "E-mail address must be specified");
    account = instance.parameters.Account;
    BuySell = instance.parameters.BuySell;
    distance = instance.parameters.Distance;

    offer = core.host:findTable("offers"):find("Instrument", instance.bid:instrument()).OfferID;
    pipsize = instance.bid:pipSize();
   
    BaseSize = core.host:execute("getTradingProperty", "baseUnitSize", instance.bid:instrument(), account); 
    SetLimit = instance.parameters.SetLimit;
    Limit = instance.parameters.Limit;
    SetStop = instance.parameters.SetStop;
    Stop = instance.parameters.Stop;
    TrailingStop = instance.parameters.TrailingStop;
    canClose = core.host:execute("getTradingProperty", "canCreateMarketClose", instance.bid:instrument(), account);
   
         ----- risk management
   
   lotSize = core.host:execute("getTradingProperty", "baseUnitSize", instance.bid:instrument(), account);

   local accounts = core.host:findTable("accounts");
    local enum = accounts:enumerator();
   local row = enum:next();
   local Balance;
   
   if row ~= nil then
   
         if Type == "Balance" then
         Balance= row.Balance;
         elseif Type == "Equity" then
         Balance= row.Equity;
         else
         Balance= Equity;
         end
    end
   
   Risk = (Balance/100)*RiskPercentage;
   
end

-- NG: create a function to parse time
function ParseTime(time)
    local Pos = string.find(time, ":");
    local h = tonumber(string.sub(time, 1, Pos - 1));
    time = string.sub(time, Pos + 1);
    Pos = string.find(time, ":");
    local m = tonumber(string.sub(time, 1, Pos - 1));
    local s = tonumber(string.sub(time, Pos + 1));
    return (h / 24.0 +  m / 1440.0 + s / 86400.0),                          -- time in ole format
           ((h >= 0 and h < 24 and m >= 0 and m < 60 and s >= 0 and s < 60) or (h == 24 and m == 0 and s == 0)); -- validity flag
end

local create = true;
local nextRepeatTime = nil;
local requestId;

function ExtUpdate(id, source, period)  -- The method called every time when a new bid or ask price appears.
   
end

function CheckConditions()
    if not(checkReady("trades")) or not(checkReady("orders")) then
        return ;
    end

    local now = core.host:execute("getServerTime");
    local time = now - math.floor(now);

    if time >= OpenTime and time <= CloseTime then
        if create then

                -- confirm we have data from our source;
                if not source:hasData(source:size() - 2) then
                    return;
            end

            -- we need to create a new trade, do it.
            Entry();
            nextRepeatTime = now + (RepeatDelay / 1440) - (5 / 86400); -- minus one as it takes a second to come back to this method.
        end
    end

    if not create and Repeat and now >= nextRepeatTime then
        -- we need to repeat now

        -- check if we are supposed to close pending orders first
        if CloseOrdersOnRepeat then
            CloseAllOrders();
        end

        -- check if we are supposed to close open positions first.
        if CloseOrdersOnRepeat then
            exitNet("B");
            exitNet("S");
        end

        -- reset the create flag to create a new trade!
        create = true;
    end
end

function CloseAllOrders()
    local enum, row;
    enum = core.host:findTable("orders"):enumerator();
    row = enum:next();
    while (row ~= nil) do
        if row.AccountID == account and row.OfferID == offer and row.QTXT == instanceName and (row.Type == "LE" or row.Type == "SE") then
            -- we want to close the entry orders, not the stop or limit orders etc otherwise we will get errors as they close each other out.
            local valuemap = core.valuemap();
            valuemap.Command = "DeleteOrder";
            valuemap.OrderID = row.OrderID;
            success, msg = terminal:execute(301, valuemap);
            if not(success) then
                terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "Failed to delete orders for instance: " .. instanceName .. ": " .. msg, instance.bid:date(NOW));
            end
        end

        row = enum:next();
    end
end


function HaveTrades(BuySell)
    local enum, row;
    local found = false;
    enum = core.host:findTable("trades"):enumerator();
    row = enum:next();
    while (not found) and (row ~= nil) do
        if row.AccountID == account and row.OfferID == offer and row.QTXT == instanceName and (row.BS == BuySell or BuySell == nil) then
           found = true;
        end

        row = enum:next();
    end

    return found;
end

-- exit from the specified trade using the direction as a key
function exitNet(BS)
    if not HaveTrades(BS) then
        return ;
    end

    local valuemap, success, msg, BuySell;
    valuemap = core.valuemap();

    -- switch the direction since the order must be in oppsite direction
    local BuySell = nil;
    if BS == "B" then
        BuySell = "S";
    else
        BuySell = "B";
    end
    valuemap.Command = "CreateOrder";
    valuemap.OrderType = "CM";
    valuemap.OfferID = offer;
    valuemap.AcctID = account;
    valuemap.NetQtyFlag = "Y"; -- this forces all trades to close in the opposite direction.
    valuemap.BuySell = BuySell;
    valuemap.CustomID = instanceName;
   
    success, msg = terminal:execute(101, valuemap);

    if not(success) then
        terminal:alertMessage(instance.bid:instrument(), instance.bid[instance.bid:size() - 1],
            "Failed net closing of " .. BS .. " trades for instance " .. instanceName .. ": " .. msg, instance.bid:date(instance.bid:size() - 1));
    end
end

function Entry()
    create = false;
   
   -- create order
    local valuemap = core.valuemap();
    valuemap.Command = "CreateOrder";

        -- get the price of the previous close.
        local prevClose = source.close[source:size() - 2];
      local candlesize = math.abs((source.open[source:size() - 2] - source.close[source:size() - 2])/pipsize);
      RPC = PipCost * candlesize;   
      amount = math.floor(Risk/RPC);   
   
        -- adjust the rate from there.
      if BuySell == "B" then
         valuemap.Rate = prevClose + (distance * pipsize);
      else
         valuemap.Rate = prevClose - (distance * pipsize);
      end
      
        -- set the order type
        if BuySell == "B" then
            if instance.ask[NOW] > valuemap.Rate then
                valuemap.OrderType = "LE";
            else
                valuemap.OrderType = "SE";
            end
        elseif BuySell == "S" then
            if instance.bid[NOW] > valuemap.Rate then
                valuemap.OrderType = "SE";
            else
                valuemap.OrderType = "LE";
            end
        end


    if instance.parameters.SetLimit then
        valuemap.PegTypeLimit = "M";
      
        if BuySell == "B" then
            valuemap.PegPriceOffsetPipsLimit = candlesize;
        else
            valuemap.PegPriceOffsetPipsLimit = -candlesize;
        end
    end

    if instance.parameters.SetStop then
        valuemap.PegTypeStop = "M";
        if BuySell == "B" then
            valuemap.PegPriceOffsetPipsStop = -candlesize - distance;
        else
            valuemap.PegPriceOffsetPipsStop = candlesize + distance;
        end

    end

    if not(canClose) and (instance.parameters.SetStop or instance.parameters.SetLimit) then
    -- if regular s/l orders aren't allowed - create ELS order
        valuemap.EntryLimitStop = "Y";
    end

    valuemap.OfferID = offer;
    valuemap.AcctID = account;
    valuemap.Quantity = amount;
    valuemap.BuySell = BuySell;
    valuemap.CustomID = instanceName;
         
      core.host:trace("Previous close is " .. prevClose .. " entry price is " .. valuemap.Rate .. " with " .. amount .. " pips ");
   
    local success, msg = terminal:execute(100, valuemap);
    if not (success) then
        create = true;
    else
        requestId = core.parseCsv(msg, ",")[0];
        Entry2();
    end
end

function Entry2()
    create = false;

    -- create order
    local valuemap = core.valuemap();
    valuemap.Command = "CreateOrder";

        -- get the price of the previous close.
    local prevClose = source.close[source:size() - 2];
   local candlesize = math.abs((source.open[source:size() - 2] - source.close[source:size() - 2])/pipsize);
   RPC = PipCost * candlesize;   
   amount = math.floor(Risk/RPC);   
   
        -- adjust the rate from there.
      if BuySell == "B" then
         valuemap.Rate = prevClose + (distance * pipsize);
      else
         valuemap.Rate = prevClose - (distance * pipsize);
      end

        -- set the order type
        if BuySell == "B" then
            if instance.ask[NOW] > valuemap.Rate then
                valuemap.OrderType = "LE";
            else
                valuemap.OrderType = "SE";
            end
        elseif BuySell == "S" then
            if instance.bid[NOW] > valuemap.Rate then
                valuemap.OrderType = "SE";
            else
                valuemap.OrderType = "LE";
            end
        end


    if instance.parameters.SetStop then
        valuemap.PegTypeStop = "M";
      
        if BuySell == "B" then
            valuemap.PegPriceOffsetPipsStop = -candlesize - distance;
        else
            valuemap.PegPriceOffsetPipsStop = candlesize + distance;
        end
    end

    if not(canClose) and (instance.parameters.SetStop or instance.parameters.SetLimit) then
    -- if regular s/l orders aren't allowed - create ELS order
        valuemap.EntryLimitStop = "Y";
    end

    valuemap.OfferID = offer;
    valuemap.AcctID = account;
    valuemap.Quantity = amount;
    valuemap.BuySell = BuySell;
    valuemap.CustomID = instanceName;
         
        core.host:trace("Previous close is " .. prevClose .. " entry price is " .. valuemap.Rate .. " with " .. amount .. " pips ");
   
    local success, msg = terminal:execute(100, valuemap);
    if not (success) then
        create = true;
    else
        requestId = core.parseCsv(msg, ",")[0];
        TerminateAfterTrade();
    end
end

function TerminateAfterTrade()
    if Repeat then
        -- don't abort.
        return;
    end

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

-- NG: Introduce async function for timer/monitoring for the order results
function ExtAsyncOperationFinished(cookie, success, message)
    if cookie == 1001 then
        -- timer
        if UseMandatoryClosing  then
            now = core.host:execute("getServerTime");
            -- get only time
            now = now - math.floor(now);

            -- check whether the time is in the exit time period
            if now >= ExitTime and now < ExitTime + ValidInterval then
                core.host:execute ("stop");
            end
        end
    elseif cookie == 1111 then
        CheckConditions();
    elseif cookie== 100 then
        if not(success) then
            Signal("create order failed: " .. message);
        else
            Signal("order sent: " .. message);
            TerminateAfterTrade();
        end
    elseif cookie== 101 then
        if not(success) then
            Signal("close position failed: " .. message);
        end   
    elseif cookie== 301 then
        if not(success) then
            Signal("delete order failed: " .. message);
        end           
    end
end

--===========================================================================--
--                    TRADING UTILITY FUNCTIONS                              --
--============================================================================--
function Signal(Label)
    if ShowAlert then
        terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW],  Label, instance.bid:date(NOW));
    end

    if SoundFile ~= nil then
        terminal:alertSound(SoundFile, RecurrentSound);
    end

    if Email ~= nil then
        terminal:alertEmail(Email, Label, profile:id() .. "(" .. instance.bid:instrument() .. ")" .. instance.bid[NOW]..", " .. Label..", " .. instance.bid:date(NOW));
    end
end

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

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

Stance
FXCodeBase: Initiate
 
Posts: 141
Joined: Mon Jun 01, 2015 4:34 pm

Re: Auto Entry Order with Risk Management not working

Postby Stance » Wed Sep 02, 2015 7:34 am

I've figured it out, here is the working code if anybody wants to use it.

Code: Select all
function Init() --The strategy profile initialization
   strategy:name("Advance Entry Order Strategy");
    strategy:description("v6");
    -- NG: optimizer/backtester hint
    strategy:setTag("NonOptimizableParameters", "ShowAlert,PlaySound,SoundFile,RecurrentSound,SendMail,Email");
   strategy:type(core.Both);
   
   strategy.parameters:addGroup("Trading Parameters");
    strategy.parameters:addString("Account", "Account to trade", "", "");
    strategy.parameters:setFlag("Account", core.FLAG_ACCOUNT);
   strategy.parameters:addString("PriceType", "Price Type", "", "Bid");
    strategy.parameters:addStringAlternative("PriceType", "Bid", "", "Bid");
    strategy.parameters:addStringAlternative("PriceType", "Ask", "", "Ask");

   strategy.parameters:addString("TF", "Bar Time frame", "Bar time frame used if Entry Type base is Previous Close.", "D1");
    strategy.parameters:setFlag("TF", core.FLAG_PERIODS);
   strategy.parameters:addString("BuySell", "Buy or Sell?", "", "B");
    strategy.parameters:addStringAlternative("BuySell", "Buy", "", "B");
    strategy.parameters:addStringAlternative("BuySell", "Sell", "", "S");
   strategy.parameters:addInteger("Distance", "Distance to market (in pips)", "", 9, 0, 1000);
   
   strategy.parameters:addBoolean("SetLimit", "Set Limit Orders", "", true);
    strategy.parameters:addBoolean("SetStop", "Set Stop Orders", "", true);
   
   strategy.parameters:addGroup("Risk Management");
   strategy.parameters:addDouble("RiskPercentage", "Risk Percentage", "Risk Percentage ", 2,0,100);
    strategy.parameters:addString("Type", "Balance/Equity", "", "Balance");
    strategy.parameters:addStringAlternative("Type", "Equity", "", "Equity");
    strategy.parameters:addStringAlternative("Type", "Balance", "", "Balance");
   
    CreateTradingParameters();
end

function CreateTradingParameters()

    strategy.parameters:addString("CustomID", "Identifier", "This identifier is required to identify previously placed orders by this strategy", "EntryOrderStrat");
    strategy.parameters:addGroup("Alerts");
    strategy.parameters:addBoolean("ShowAlert", "ShowAlert", "", false);
    strategy.parameters:addBoolean("PlaySound", "Play Sound", "", false);
    strategy.parameters:addFile("SoundFile", "Sound File", "", "");
    strategy.parameters:setFlag("SoundFile", core.FLAG_SOUND);
    strategy.parameters:addBoolean("RecurrentSound", "Recurrent Sound", "", false);
    strategy.parameters:addBoolean("SendEmail", "Send Email", "", false);
    strategy.parameters:addString("Email", "Email", "", "");
    strategy.parameters:setFlag("Email", core.FLAG_EMAIL);
end

local offer;
local account;
local amount;
local pipsize;
local BuySell;
local distance;
local SoundFile = nil;
local RecurrentSound = false;
local SetLimit;
local Limit;
local SetStop;
local Stop;
local TrailingStop;
local ShowAlert;
local Email;
local SendEmail;
local BaseSize;
local canClose;
local source = nil;
local instanceName;
local first;

local RiskPercentage;
local Type;
local PipCost;
local RPC;      
local Risk;
local lotSize;

--
function Prepare(nameOnly)

    instanceName = profile:id() .. "( " .. instance.bid:name() ..  " )";
    instance:name(instanceName);
    instanceName = instanceName .. " " .. instance.parameters.CustomID;
   
    Type = instance.parameters.Type;
   RiskPercentage = instance.parameters.RiskPercentage;

    assert(instance.parameters.TF ~= "t1", "The time frame must not be tick");

    if nameOnly then
        return ;
    end

    -- this timer will be used to check our conditions every 5 seconds
    core.host:execute("setTimer", 1111, 5);
   
   source = ExtSubscribe(1, nil, instance.parameters.TF, instance.parameters.PriceType == "Bid", "bar");
   
   first=source:first();
   
   PipCost = core.host:findTable("offers"):find("Instrument", source:instrument()).PipCost;
   
   local name;
    name = profile:id() .. "( " .. instance.bid:name();
    local i;
   
    name = name  ..  " )";
    instance:name(name);
      
   PrepareTrading();
end

function PrepareTrading()
    local PlaySound = instance.parameters.PlaySound;
    if PlaySound then
        SoundFile = instance.parameters.SoundFile;
    else
        SoundFile = nil;
    end
    assert(not(PlaySound) or (PlaySound and SoundFile ~= ""), "Sound file must be chosen");

    ShowAlert = instance.parameters.ShowAlert;
    RecurrentSound = instance.parameters.RecurrentSound;

    SendEmail = instance.parameters.SendEmail;

    if SendEmail then
        Email = instance.parameters.Email;
    else
        Email = nil;
    end
    assert(not(SendEmail) or (SendEmail and Email ~= ""), "E-mail address must be specified");
    account = instance.parameters.Account;
    BuySell = instance.parameters.BuySell;
    distance = instance.parameters.Distance;

    offer = core.host:findTable("offers"):find("Instrument", instance.bid:instrument()).OfferID;
    pipsize = instance.bid:pipSize();
   
    BaseSize = core.host:execute("getTradingProperty", "baseUnitSize", instance.bid:instrument(), account); 
    SetLimit = instance.parameters.SetLimit;
    Limit = instance.parameters.Limit;
    SetStop = instance.parameters.SetStop;
    Stop = instance.parameters.Stop;
    TrailingStop = instance.parameters.TrailingStop;
    canClose = core.host:execute("getTradingProperty", "canCreateMarketClose", instance.bid:instrument(), account);
   
         ----- risk management

   local accounts = core.host:findTable("accounts");
    local enum = accounts:enumerator();
   local row = enum:next();
   local Balance;
   
   if row ~= nil then
   
         if Type == "Balance" then
         Balance= row.Balance;
         elseif Type == "Equity" then
         Balance= row.Equity;
         else
         Balance= Equity;
         end
    end
   
   Risk = (Balance/100)*RiskPercentage;
   
end

-- NG: create a function to parse time
function ParseTime(time)
    local Pos = string.find(time, ":");
    local h = tonumber(string.sub(time, 1, Pos - 1));
    time = string.sub(time, Pos + 1);
    Pos = string.find(time, ":");
    local m = tonumber(string.sub(time, 1, Pos - 1));
    local s = tonumber(string.sub(time, Pos + 1));
    return (h / 24.0 +  m / 1440.0 + s / 86400.0),                          -- time in ole format
           ((h >= 0 and h < 24 and m >= 0 and m < 60 and s >= 0 and s < 60) or (h == 24 and m == 0 and s == 0)); -- validity flag
end

local create = true;
local nextRepeatTime = nil;
local requestId;

function ExtUpdate(id, source, period)  -- The method called every time when a new bid or ask price appears.
   
end

function CheckConditions()
    if not(checkReady("trades")) or not(checkReady("orders")) then
        return ;
    end

    local now = core.host:execute("getServerTime");
    local time = now - math.floor(now);

        if create then
                -- confirm we have data from our source;
                if not source:hasData(source:size() - 2) then
                    return;
            end

            -- we need to create a new trade, do it.
            Entry();
        end
end


function HaveTrades(BuySell)
    local enum, row;
    local found = false;
    enum = core.host:findTable("trades"):enumerator();
    row = enum:next();
    while (not found) and (row ~= nil) do
        if row.AccountID == account and row.OfferID == offer and row.QTXT == instanceName and (row.BS == BuySell or BuySell == nil) then
           found = true;
        end

        row = enum:next();
    end

    return found;
end

function Entry()
    create = false;
   
   -- create order
    local valuemap = core.valuemap();
    valuemap.Command = "CreateOrder";

        -- get the price of the previous close.
        local prevClose = source.close[source:size() - 2];
      local candlesize = math.abs((source.open[source:size() - 2] - source.close[source:size() - 2])/pipsize);
      RPC = PipCost * candlesize;   
      amount = math.floor(Risk/RPC);   
   
        -- adjust the rate from there.
      if BuySell == "B" then
         valuemap.Rate = prevClose + (distance * pipsize);
      else
         valuemap.Rate = prevClose - (distance * pipsize);
      end
      
        -- set the order type
        if BuySell == "B" then
            if instance.ask[NOW] > valuemap.Rate then
                valuemap.OrderType = "LE";
            else
                valuemap.OrderType = "SE";
            end
        elseif BuySell == "S" then
            if instance.bid[NOW] > valuemap.Rate then
                valuemap.OrderType = "SE";
            else
                valuemap.OrderType = "LE";
            end
        end


    if instance.parameters.SetLimit then
        valuemap.PegTypeLimit = "M";
      
        if BuySell == "B" then
            valuemap.PegPriceOffsetPipsLimit = candlesize;
        else
            valuemap.PegPriceOffsetPipsLimit = -candlesize;
        end
    end

    if instance.parameters.SetStop then
        valuemap.PegTypeStop = "M";
        if BuySell == "B" then
            valuemap.PegPriceOffsetPipsStop = -candlesize - distance;
        else
            valuemap.PegPriceOffsetPipsStop = candlesize + distance;
        end

    end

    if not(canClose) and (instance.parameters.SetStop or instance.parameters.SetLimit) then
    -- if regular s/l orders aren't allowed - create ELS order
        valuemap.EntryLimitStop = "Y";
    end

    valuemap.OfferID = offer;
    valuemap.AcctID = account;
    valuemap.Quantity = amount * BaseSize;
    valuemap.BuySell = BuySell;
    valuemap.CustomID = instanceName;
         
      core.host:trace("Previous close is " .. prevClose .. " entry price is " .. valuemap.Rate .. " with " .. amount .. " pips ");
   
    local success, msg = terminal:execute(100, valuemap);
    if not (success) then
        create = true;
    else
        requestId = core.parseCsv(msg, ",")[0];
        Entry2();
    end
end

function Entry2()
    create = false;

    -- create order
    local valuemap = core.valuemap();
    valuemap.Command = "CreateOrder";

        -- get the price of the previous close.
    local prevClose = source.close[source:size() - 2];
   local candlesize = math.abs((source.open[source:size() - 2] - source.close[source:size() - 2])/pipsize);
   RPC = PipCost * candlesize;   
   amount = math.floor(Risk/RPC);   
   
        -- adjust the rate from there.
      if BuySell == "B" then
         valuemap.Rate = prevClose + (distance * pipsize);
      else
         valuemap.Rate = prevClose - (distance * pipsize);
      end

        -- set the order type
        if BuySell == "B" then
            if instance.ask[NOW] > valuemap.Rate then
                valuemap.OrderType = "LE";
            else
                valuemap.OrderType = "SE";
            end
        elseif BuySell == "S" then
            if instance.bid[NOW] > valuemap.Rate then
                valuemap.OrderType = "SE";
            else
                valuemap.OrderType = "LE";
            end
        end


    if instance.parameters.SetStop then
        valuemap.PegTypeStop = "M";
      
        if BuySell == "B" then
            valuemap.PegPriceOffsetPipsStop = -candlesize - distance;
        else
            valuemap.PegPriceOffsetPipsStop = candlesize + distance;
        end
    end

    if not(canClose) and (instance.parameters.SetStop or instance.parameters.SetLimit) then
    -- if regular s/l orders aren't allowed - create ELS order
        valuemap.EntryLimitStop = "Y";
    end

    valuemap.OfferID = offer;
    valuemap.AcctID = account;
    valuemap.Quantity = amount * BaseSize;
    valuemap.BuySell = BuySell;
    valuemap.CustomID = instanceName;
         
        core.host:trace("Previous close is " .. prevClose .. " entry price is " .. valuemap.Rate .. " with " .. amount .. " pips ");
   
    local success, msg = terminal:execute(100, valuemap);
    if not (success) then
        create = true;
    else
        requestId = core.parseCsv(msg, ",")[0];
        TerminateAfterTrade();
    end
end

function TerminateAfterTrade()

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

-- NG: Introduce async function for timer/monitoring for the order results
function ExtAsyncOperationFinished(cookie, success, message)
  if cookie == 1111 then
        CheckConditions();
    elseif cookie== 100 then
        if not(success) then
            Signal("create order failed: " .. message);
        else
            Signal("order sent: " .. message);
            TerminateAfterTrade();
        end
    elseif cookie== 101 then
        if not(success) then
            Signal("close position failed: " .. message);
        end   
    elseif cookie== 301 then
        if not(success) then
            Signal("delete order failed: " .. message);
        end           
    end
end

--===========================================================================--
--                    TRADING UTILITY FUNCTIONS                              --
--============================================================================--
function Signal(Label)
    if ShowAlert then
        terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW],  Label, instance.bid:date(NOW));
    end

    if SoundFile ~= nil then
        terminal:alertSound(SoundFile, RecurrentSound);
    end

    if Email ~= nil then
        terminal:alertEmail(Email, Label, profile:id() .. "(" .. instance.bid:instrument() .. ")" .. instance.bid[NOW]..", " .. Label..", " .. instance.bid:date(NOW));
    end
end

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

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

Stance
FXCodeBase: Initiate
 
Posts: 141
Joined: Mon Jun 01, 2015 4:34 pm

Re: Auto Entry Order with Risk Management not working

Postby CABS73 » Wed Oct 11, 2017 12:16 pm

Hi.
I tried to use it but there is an error message. Unexpected symbol near ' '

I don't know what the problem is. Do you know if there is another similar indicator.

Thank you.
CABS73
 
Posts: 2
Joined: Wed Oct 11, 2017 12:11 pm

Re: Auto Entry Order with Risk Management not working

Postby Apprentice » Thu Oct 19, 2017 3:31 am

Your request is added to the development list under Id Number 3925
User avatar
Apprentice
FXCodeBase: Confirmed User
 
Posts: 36341
Joined: Thu Dec 31, 2009 11:59 am
Location: Zagreb, Croatia


Return to Indicator Development

Who is online

Users browsing this forum: No registered users and 9 guests