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