Create OCO orders

You can create two or more entry orders and then join them into OCO using just one call.

To create OCO order group:

1) Create a valuemap and fill only one field:

Valuemap field

Datatype

Description

Command

string

The command. Must be CreateOCO.

The field is obligatory.

2) Create a valuemap for each entry order you want to create and fill it as for the regular entry order.

3) Append each entry order valuemap to the main valuemap using valuemap.append() method.

4) Pass main valuemap table to terminal:execute() method.

Limitations:

1) Only entry orders can be joined into OCO. However, Entry orders with attached stop limits, either regular or ELS can be joined into OCO.

2) All entry orders must be create for the same account.

Returns:

The terminal:execute() method will return the list of request id for each entry order created. So, if 3 entry order is created - 3 request id separated by commas (,) will be returned. Moreover, if any of the orders is ELS order, 3 request id will be returned per each ELS order inside the OCO.

Example: Create a pair of entry order on the specified distance from the market and wait for the result [hide]

   function Init()
       strategy:name("Sample");
       strategy:description("");
 
       strategy.parameters:addString("Account", "Account to trade", "", "");
       strategy.parameters:setFlag("Account", core.FLAG_ACCOUNT);
       strategy.parameters:addInteger("Amount", "Amount in lots to trade", "", 1, 1, 100);
       strategy.parameters:addInteger("Distance", "Distance to market", "", 100, 1, 1000);
       strategy.parameters:addString("BuySell", "Buy or Sell?", "", "B");
       strategy.parameters:addStringAlternative("BuySell", "Buy", "", "B");
       strategy.parameters:addStringAlternative("BuySell", "Sell", "", "S");
   end
 
   local offer;
   local account;
   local amount;
   local pipsize;
   local BuySell;
   local distance;
 
   function Prepare()
       instance:name(profile:id() .. "(" .. instance.bid:instrument() .. ")");
 
       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();
 
   end
 
   local create = true;
   local trade = false;
   local requestId1;
   local requestId2;
 
   function Update()
       if create then
           create = false;
 
           -- create order
           local valuemap = core.valuemap();
           valuemap.Command = "CreateOCO";
 
           valuemap:append(CreateOrder(BuySell, distance));
           valuemap:append(CreateOrder(BuySell, -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));
           else
               local t = core.parseCsv(msg, ",");
               requestId1 = t[0];
               requestId2 = t[1];
               terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "orders sent:" .. requestId1 .. "," .. requestId2, instance.bid:date(NOW));
           end
       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;
           end
           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;
           end
       end
   end
 
   function CreateOrder(aBuySell, adistance)
       local valuemap = core.valuemap();
 
       --valuemap.Command = "CreateOrder";
 
       -- 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";
       end
 
       if adistance > 0 then
           valuemap.Rate = instance.ask[NOW] + adistance * pipsize;
       else
           valuemap.Rate = instance.bid[NOW] + adistance * pipsize;
       end
 
       valuemap.OfferID = offer;
       valuemap.AcctID = account;
       valuemap.Quantity = amount;
       valuemap.BuySell = aBuySell;
 
       return valuemap;
   end
 
   function AsyncOperationFinished(cookie, success, msg)
       if cookie == 100 then
           if not(success) then
               terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "create order failed:" .. msg, instance.bid:date(NOW));
           else
               terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "order created:" .. msg, instance.bid:date(NOW));
           end
       end
   end

Example: Create an OCO of Two Entry Orders with Stops and Limits Attached [hide]

   function Init()
       strategy:name("Sample");
       strategy:description("");
 
       strategy.parameters:addString("Account", "Account to trade", "", "");
       strategy.parameters:setFlag("Account", core.FLAG_ACCOUNT);
       strategy.parameters:addInteger("Amount", "Amount in lots to trade", "", 1, 1, 100);
       strategy.parameters:addInteger("Distance", "Distance to market", "", 20, 20, 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 Order", "", true);
       strategy.parameters:addInteger("Limit", "Set Limit Distance in pips", "", 30, 1, 10000);
       strategy.parameters:addBoolean("SetStop", "Set Stop Order", "", true);
       strategy.parameters:addInteger("Stop", "Set Stop Distance in pips", "", 30, 1, 10000);
       strategy.parameters:addBoolean("TrailingStop", "Set Trailing Stop Order", "", true);
 
   end
 
   local offer;
   local account;
   local amount;
   local pipsize;
   local BuySell;
   local distance;
   local canClose;
 
   function Prepare()
       instance:name(profile:id() .. "(" .. instance.bid:instrument() .. ")");
 
       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();
       canClose = core.host:execute("getTradingProperty", "canCreateMarketClose", instance.bid:instrument(), account);
 
 
   end
 
   local create = true;
   local trade = false;
   local requestId1;
   local requestId2;
 
   function Update()
       if create then
           create = false;
 
           -- create order
           local valuemap = core.valuemap();
           valuemap.Command = "CreateOCO";
 
           valuemap:append(CreateOrder(BuySell, distance));
           valuemap:append(CreateOrder(BuySell, -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));
           else
               local t = core.parseCsv(msg, ",");
               requestId1 = t[0];
               local second = 1;
               if instance.parameters.SetStop and not(canClose) then
                   second = second + 1;
               end
               if instance.parameters.SetLimit and not(canClose) then
                   second = second + 1;
               end
               requestId2 = t[second];
               terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "orders sent:" .. requestId1 .. "," .. requestId2, instance.bid:date(NOW));
           end
 
       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;
           end
           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;
           end
       end
   end
 
   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";
       end
 
       if adistance > 0 then
           valuemap.Rate = instance.ask[NOW] + adistance * pipsize;
       else
           valuemap.Rate = instance.bid[NOW] + adistance * pipsize;
       end
 
       valuemap.OfferID = offer;
       valuemap.AcctID = account;
       valuemap.Quantity = amount;
       valuemap.BuySell = aBuySell;
 
       if instance.parameters.SetLimit then
           valuemap.PegTypeLimit = "M";
           if aBuySell == "B" then
               valuemap.PegPriceOffsetPipsLimit = instance.parameters.Limit;
           else
               valuemap.PegPriceOffsetPipsLimit = -instance.parameters.Limit;
           end
       end
 
       if instance.parameters.SetStop then
           valuemap.PegTypeStop = "M";
           if aBuySell == "B" then
               valuemap.PegPriceOffsetPipsStop = -instance.parameters.Stop;
           else
               valuemap.PegPriceOffsetPipsStop = instance.parameters.Stop;
           end
 
           if instance.parameters.TrailingStop then
               valuemap.TrailStepStop = 1;
           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
 
       return valuemap;
   end
 
   function AsyncOperationFinished(cookie, success, msg)
       if cookie == 100 then
           if not(success) then
               terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "create order failed:" .. msg, instance.bid:date(NOW));
           else
               terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "order created:" .. msg, instance.bid:date(NOW));
           end
       end
   end

back