Entry Order Strategy

Strategies are published here.

Moderator: admin

Re: Entry Order Strategy

Postby easytrading » Mon Nov 24, 2014 12:08 am

hello moomoofx ,

yes it is closing now the previous opened position ,but the closing is based on the position opening time till the repeat delay time is met ,that is causing a very big losses when the market reverse in the other direction of the opend position.and becuase of that (to limited those losses to the minimum) i was requesting the close of the opened position based on : when the bar timeframe used in the strategy comes to expire regarardless when it was opened.so if you please could update it to met that .i'll be so greatful to you.thanks for the great job in advance.

below are the parameters i am using:

Entry type :previous close
Bar TF :m5
scheduled terminate :no
repeat :yes
repeat delay(min) :5
close orders on repeat :yes
close positions on repeat :yes
amount in lots to trade :10
distance to market :0
buy or sell :sell
T/P & S/L :no
FXCodeBase: Initiate
Posts: 105
Joined: Thu Sep 11, 2014 5:23 pm

Re: Entry Order Strategy

Postby moomoofx » Mon Nov 24, 2014 1:46 am


If I understand you correctly, you want it to close any open positions when the bar closes.

If you set your repeat timeframe to the same as your bar timeframe, like you have in your example, then it will repeat everytime a new bar is closed/created at pretty much the same time.

Therefore, you should be seeing that behavior already. I tested it, and the screenshot below confirms it.


02:45 Order placed.
02:45 Order Executed, Position Opened.
02:50 5 minutes later Open position closed and new order placed.

Where's the problem?
User avatar
FXCodeBase: Confirmed User
Posts: 193
Joined: Wed Oct 23, 2013 10:26 pm
Location: Okinawa, Japan. http://moomooforex.com

Re: Entry Order Strategy

Postby easytrading » Wed Nov 26, 2014 12:03 am

hello moomoofx,

I re-instal it and now it is closing at the bar closing .thank you
FXCodeBase: Initiate
Posts: 105
Joined: Thu Sep 11, 2014 5:23 pm

Re: Entry Order Strategy

Postby easytrading » Thu Nov 27, 2014 4:31 pm

hello moomoofx,

if you please i need to include another function to the stratrgy as below:
let us assume the trend is Bullish and we set the diraction : buy with TF=5min and amount in lots to trade=10 ,now every time the bar closes in profit (with the trend) it will use the lot=10 . But when the bar closes in loss, the next opened position will use 2 extra lots more than the previous one and keeps on until the trend retuns and the bar closes in profit it will comeback and use the original lot size set before which is 10. the formula used to calculate the new lot size is:
X=10 (original lot size for bars in profit)
Y1=X+2 (lot size for 1st loss bar)
Y2=Y1+2 (lot size for 2nd loss bar)
Y3=Y2+2 (lot size for 3rd loss bar)
.......and so on
your halp is much appreciated and thank you for the excellent job you are doing.
kindest regards.cheers
FXCodeBase: Initiate
Posts: 105
Joined: Thu Sep 11, 2014 5:23 pm

Re: Entry Order Strategy

Postby explorerr » Mon Dec 01, 2014 2:23 am

please help me, where is the post

this page is error
Posts: 2
Joined: Mon Dec 01, 2014 2:16 am

Re: Entry Order Strategy

Postby easytrading » Mon Dec 01, 2014 7:39 pm

hello explorerr,
the post you are looking for and moomoofx is referreing to is my reply in this post dated in:
Re: Entry Order Strategy
by easytrading » Wed Sep 17, 2014 7:08 pm you will find it in page 2 of this post.

hopping this will help...

FXCodeBase: Initiate
Posts: 105
Joined: Thu Sep 11, 2014 5:23 pm

Re: Entry Order Strategy

Postby zoltanh » Fri Apr 03, 2015 2:37 am

Hi MooMoo

Do you think this strategy can be changed from:
"Will generate an Entry order, X pips above or below market.
At future set point in time."

"Will generate an Entry order, X pips above and below market.
If a certain price level is reached."

thanks in advance
Posts: 22
Joined: Tue Aug 26, 2014 2:24 pm

Re: Entry Order Strategy

Postby Stance » Wed Aug 12, 2015 9:17 pm

How does the time parameters work?

I want it to only trade at a particular time and tested it by putting in the start time of 11:30, but it looks like it puts an order in straight away regardless (see blow link), even though current time was 11:26?


How to I set it to put in a trade at the open of the week 10 pips above the closing price of the previous week?

Is this correct?

Start Time for Trading: ???
Srop Time for Trading: 24:00:00
Entry Type: Previous Close
Bar Time Frame: W1
Distance to market (in pips): 10
FXCodeBase: Initiate
Posts: 141
Joined: Mon Jun 01, 2015 4:34 pm

Re: Entry Order Strategy

Postby Stance » Fri Aug 28, 2015 2:10 am

Hi would it be possible to have an option to place 2 or orders simultaneously? Ie when triggered 2 buy orders for the same market is put in.
FXCodeBase: Initiate
Posts: 141
Joined: Mon Jun 01, 2015 4:34 pm

Re: Entry Order Strategy

Postby Stance » Thu Oct 01, 2015 4:07 am

lucypip wrote:Hi Apprentice! can you make this available on OCO (one cancels other), Market Order, and Market Range please. Thanks!!!

I've managed to modify the code to support OCO.

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("Entry OCO Strategy");
    -- NG: optimizer/backtester hint
    strategy:setTag("NonOptimizableParameters", "ShowAlert,PlaySound,SoundFile,RecurrentSound,SendMail,Email");
    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:addGroup("Strategy Parameters");
      strategy.parameters:addString("PriceType", "Price Type", "", "Bid");
    strategy.parameters:addStringAlternative("PriceType", "Bid", "", "Bid");
    strategy.parameters:addStringAlternative("PriceType", "Ask", "", "Ask");
    strategy.parameters:addString("EntryType", "Entry Type", "When the time to place the order comes, should the order price be determined from the current price or previous close?", "PreviousClose");
    strategy.parameters:addStringAlternative("EntryType", "Current Price", "", "CurrentPrice");
    strategy.parameters:addStringAlternative("EntryType", "Previous Close", "", "PreviousClose");
   strategy.parameters:addString("TF", "Bar Time frame", "Bar time frame used if Entry Type base is Previous Close.", "m5");
    strategy.parameters:setFlag("TF", core.FLAG_PERIODS);
    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.", true);
    strategy.parameters:addInteger("RepeatDelay", "Repeat Delay (mins)", "How many minutes should we wait between repeats", 5);
    strategy.parameters:addBoolean("CloseOrdersOnRepeatCloseOrdersOnRepeat", "Close Orders On Repeat", "Should we close any pending orders when we repeat?", true);
    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");


function CreateTradingParameters()
    strategy.parameters:addGroup("Trading Parameters");

    strategy.parameters:addString("Account", "Account to trade", "", "");
    strategy.parameters:setFlag("Account", core.FLAG_ACCOUNT);
    strategy.parameters:addInteger("Amount", "Amount in lots to trade", "", 10, 1, 1000);
    strategy.parameters:addInteger("Distance", "Distance to market (in pips)", "", 5, -1000, 1000);
    strategy.parameters:addString("BuySell", "Buy or Sell?", "", "B");
    strategy.parameters:addStringAlternative("BuySell", "Buy", "", "B");
    strategy.parameters:addStringAlternative("BuySell", "Sell", "", "S");

    strategy.parameters:addBoolean("SetLimit", "Set Limit Orders", "", false);
    strategy.parameters:addInteger("Limit", "Limit Order in pips", "", 5, 1, 10000);
    strategy.parameters:addBoolean("SetStop", "Set Stop Orders", "", true);
    strategy.parameters:addInteger("Stop", "Stop Order in pips", "", 5, 1, 10000);
   strategy.parameters:addInteger("TrailingStop", "Trailing stop order", "Use 0 for none or 1 for dynamic and great than 1 for fixed trailing", 1, 0, 10000);

    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);

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;
-- Don't need to store hour + minute + second for each time
local OpenTime, CloseTime, ExitTime;

local source = nil;
local EntryType;
local Repeat;
local RepeatDelay;
local CloseOrdersOnRepeat;
local ClosePositionsOnRepeat;
local instanceName;

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

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

    -- 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 ;

    -- this timer will be used to check our conditions every 5 seconds
    core.host:execute("setTimer", 1111, 5);

    if (EntryType == "PreviousClose") then
        -- price bid/ask depends on if we are selling or buying.
        source = ExtSubscribe(1, nil, instance.parameters.TF, instance.parameters.PriceType == "Bid", "bar");

    if UseMandatoryClosing then
        core.host:execute("setTimer", 1001, math.max(ValidInterval / 2, 1));

function PrepareTrading()
    local PlaySound = instance.parameters.PlaySound;
    if PlaySound then
        SoundFile = instance.parameters.SoundFile;
        SoundFile = nil;
    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;
        Email = nil;
    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;

    local lotSize = core.host:execute("getTradingProperty", "baseUnitSize", instance.bid:instrument(), account);
    amount = lotSize * instance.parameters.Amount;
    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);


-- 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

local create = true;
local nextRepeatTime = nil;
local requestId;
local trade = false;
local requestId1;
local requestId2;

function ExtUpdate(id, source, period)  -- The method called every time when a new bid or ask price appears.
    -- we don't need to do anything here.

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

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

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

            if (EntryType == "PreviousClose") then
                -- confirm we have data from our source;
                if not source:hasData(source:size() - 2) then

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

    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

        -- check if we are supposed to close open positions first.
        if ClosePositionsOnRepeat then

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

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));

        row = enum:next();

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;

        row = enum:next();

    return found;

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

    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";
        BuySell = "B";
    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));

function Entry()
 if create then
           create = false;
           -- create order
           local valuemap = core.valuemap();
           valuemap.Command = "CreateOCO";
           valuemap:append(CreateOrder("B", distance));
           valuemap:append(CreateOrder("S", -distance));
           local success, msg = terminal:execute(100, valuemap);
           if not (success) then
               terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "create order failed:" .. msg, instance.bid:date(NOW));
               local t = core.parseCsv(msg, ",");
               requestId1 = t[0];
               local second = 1;
               if instance.parameters.SetStop and not(canClose) then
                   second = second + 1;
               if instance.parameters.SetLimit and not(canClose) then
                   second = second + 1;
               requestId2 = t[second];
       elseif not(trade) then
           -- check whether trade has been created
           local row;
           row = core.host:findTable("trades"):find("OpenOrderReqID", requestId1);
           if row ~= nil then
               terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "trade created by first order:" .. row.TradeID, instance.bid:date(NOW));
               trade = true;
           local row;
           row = core.host:findTable("trades"):find("OpenOrderReqID", requestId2);
           if row ~= nil then
               terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "trade created by second order:" .. row.TradeID, instance.bid:date(NOW));
               trade = true;

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

    core.host:execute ("stop");

function CreateOrder(aBuySell, adistance)
       local valuemap = core.valuemap();
       -- get the order type
       if aBuySell == "B" and adistance < 0 then
           valuemap.OrderType = "LE";
       elseif aBuySell == "B" and adistance > 0 then
           valuemap.OrderType = "SE";
       elseif aBuySell == "S" and adistance < 0 then
           valuemap.OrderType = "SE";
       elseif aBuySell == "S" and adistance > 0 then
           valuemap.OrderType = "LE";
       if adistance > 0 then
           valuemap.Rate = instance.ask[NOW] + adistance * pipsize;
           valuemap.Rate = instance.bid[NOW] + adistance * pipsize;
       valuemap.OfferID = offer;
       valuemap.AcctID = account;
       valuemap.Quantity = amount;
       valuemap.BuySell = aBuySell;
      valuemap.CustomID = instanceName;
       if instance.parameters.SetLimit then
           valuemap.PegTypeLimit = "M";
           if aBuySell == "B" then
               valuemap.PegPriceOffsetPipsLimit = instance.parameters.Limit;
               valuemap.PegPriceOffsetPipsLimit = -instance.parameters.Limit;
       if instance.parameters.SetStop then
           valuemap.PegTypeStop = "M";
           if aBuySell == "B" then
               valuemap.PegPriceOffsetPipsStop = -instance.parameters.Stop;
               valuemap.PegPriceOffsetPipsStop = instance.parameters.Stop;
               valuemap.TrailStepStop = TrailingStop;

       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";
       return valuemap;

-- 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");
    elseif cookie == 1111 then
    elseif cookie== 100 then
        if not(success) then
            Signal("create order failed: " .. message);
            Signal("order sent: " .. message);
    elseif cookie== 101 then
        if not(success) then
            Signal("close position failed: " .. message);
    elseif cookie== 301 then
        if not(success) then
            Signal("delete order failed: " .. message);

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

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

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

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

dofile(core.app_path() .. "\\strategies\\standard\\include\\helper.lua");
FXCodeBase: Initiate
Posts: 141
Joined: Mon Jun 01, 2015 4:34 pm


Return to Custom Strategies

Who is online

Users browsing this forum: No registered users and 4 guests