I see in the original methodology Update and AsyncOperationFinished there exist two further arguments method1 and method2. These arguments contain information on the FixOrder status = exactly what I need to determine the operation occuring. This happens when core.host:execute("subscribeTradeEvents", cookieOrdersTable, "orders"); is subscribed to.
So what to do do I
1/. re-engineer this thing away from ExtUpdate and ExtAsyncOperationFinished - which is supposed to be helpful - and back to Update and AsyncOperationFinished?
or
2/. keep a record of the orders and detect when they are no longer in the table?
3/. Hopefully someone has another plan to exact?
Any help / ideas appreciated.
- Code: Select all
function Init()
strategy:name("Candles");
strategy:description("This processes just candle events");
strategy:type(core.Both);
--Price Parameters
strategy.parameters:addGroup("Price Parameters");
--Time Frame
strategy.parameters:addString("TF", "param_TF_name", "param_TF_description", "m5");
strategy.parameters:setFlag("TF", core.FLAG_PERIODS);
-- Indicator Parameters
strategy.parameters:addGroup("Parameters");
strategy.parameters:addInteger("pEMA", "param_pEMA_name", "param_pEMA_description", 34);
strategy.parameters:addInteger("pCCIBig", "param_pCCIBig_name", "param_pCCIBig_description", 50);
strategy.parameters:addInteger("pCCISmall", "param_pCCISmall_name", "param_pCCISmall_description", 14);
-- Trading Parameters
strategy.parameters:addGroup("Trading Parameters");
strategy.parameters:addBoolean("bClickTrade", "is trading", "true if indicator is trading", false)
strategy.parameters:addBoolean("AllowTrade", "Can Trade", "", true);
strategy.parameters:addBoolean("AllowTicks", "Can have Ticks", "", false);
strategy.parameters:addString("Account", "param Account Trade Name", "", "TESTACCT");
strategy.parameters:setFlag("Account", core.FLAG_ACCOUNT);
strategy.parameters:addInteger("tradeSize", "param_tradeSize_name", "", 1, 1, 10000);
strategy.parameters:addInteger("Limit", "param_LimitOrderPips_name", "", 30, 1, 10000);
strategy.parameters:addInteger("Stop", "param_StopOrderPips", "", 20, 1, 10000);
strategy.parameters:addBoolean("TrailingStop", "Set Trailing Stop Order", "", false);
end
--ABOUT SOURCE--
local pCCIBig;
local pCCISmall;
local pEMA;
local firstCCISmall = 0;
local firstCCIBig = 0;
local firstEMA = 0;
local firstASI = 0;
local cci7 = nil;
local cci50 = nil;
local ema34 = nil;
local asi = nil;
local myCandleSourceBid = nil;
local myCandleSourceAsk = nil;
local bClickTrade;
--ABOUT ASYNC--
cookieLoadHistBid = 1;
cookieEntryOrder = 100;
cookieCancelEntry = 3000;
cookieOrdersTable = 4000;
cookieTradesTable = 1001;
-- ABOUT TRADING PARAMETERS --
local AllowTicks;
local AllowTrade;
local Account;
local BaseSize;
local SetLimit;
local Limit;
local SetStop;
local Stop;
local SetTS;
local Offer;
local CanClose;
local retracePips = 10;
local lastSerial = -1;
local requestId;
local stage;
local orderId;
local tradeSize;
local pipSize;
local nexecuting = 0;
function Prepare(nameOnly)
pEMA = instance.parameters.pEMA;
pCCIBig = instance.parameters.pCCIBig;
pCCISmall = instance.parameters.pCCISmall;
bClickTrade = instance.parameters.bClickTrade;
local name = profile:id() .. "(" .. instance.bid:instrument() .. ", " .. tostring(pCCIBig) .. ", " .. tostring(pCCISmall) .. ", " .. tostring(pEMA) .. ")";
instance:name(name);
if nameOnly then
return ;
end
AllowTicks = false;
if (not(AllowTicks)) then
assert(instance.parameters.TF ~= "t1", "assert_noticks");
end
AllowTrade = instance.parameters.AllowTrade;
if AllowTrade then
Account = instance.parameters.Account;
BaseSize = core.host:execute("getTradingProperty", "baseUnitSize", instance.bid:instrument(), Account);
Offer = core.host:findTable("offers"):find("Instrument", instance.bid:instrument()).OfferID;
tradeSize = instance.parameters.tradeSize * core.host:execute("getTradingProperty", "baseUnitSize", instance.bid:instrument(), Account);
SetLimit = true;
Limit = instance.parameters.Limit * instance.bid:pipSize();
SetStop = true;
SetTS = false;
Stop = instance.parameters.Stop * instance.bid:pipSize();
pipSize = instance.bid:pipSize();
end
local canClose = core.host:execute("getTradingProperty", "canCreateStopLimit", instance.bid:instrument(), instance.parameters.Account);
local canLimitStop = core.host:execute("getTradingProperty", "canCreateMarketClose", instance.bid:instrument(), Account);
myCandleSourceBid = ExtSubscribe(cookieLoadHistBid, instance.bid:instrument(), "m5", true, "bar") --bid
--myCandleSourceAsk = ExtSubscribe(cookieLoadHistAsk, instance.bid:instrument(), "m5", false, "bar") --ask
core.host:execute("subscribeTradeEvents", cookieTradesTable, "trades");
core.host:execute("subscribeTradeEvents", cookieOrdersTable, "orders");
--BID Prices in indicators
cci7 = core.indicators:create("CCI", myCandleSourceBid, pCCISmall);
cci50 = core.indicators:create("CCI", myCandleSourceBid, pCCIBig);
asi = core.indicators:create("ASI", myCandleSourceBid);
ema34 = core.indicators:create("EMA", myCandleSourceBid.close, pEMA);
firstEMA = ema34.DATA:first()+1;
firstCCISmall = cci7.DATA:first()+1;
firstCCIBig = cci50.DATA:first()+1;
firstASI = asi.DATA:first()+1;
if nameOnly then
return ;
end
end
function ExtUpdate(id, source, period)
if AllowTrade then
if not(checkReady("trades")) or not(checkReady("orders")) then
return ;
end
end
if period < firstEMA or period < firstCCISmall or period < firstCCIBig or period < firstASI then -- bid and ask bar streams
return;
end
ema34:update(core.UpdateLast)
cci7:update(core.UpdateLast)
cci50:update(core.UpdateLast)
asi:update(core.UpdateLast)
local leave = false;
local enum = core.host:findTable("orders"):enumerator();
row = enum:next();
if row ~= nil then
if (balkEO(row,period,enum) ~= nil) then
local vmap = core.valuemap();
vmap.Command = "DeleteOrder";
vmap.OrderID = row.OrderID;
success, msg = terminal:execute(cookieCancelEntry, vmap);
assert(success, msg);
if not(success) then
terminal:alertMessage(instance.bid:instrument(), instance.bid[NOW], "Failed delete order:" ..
msg, myCandleSourceBid:date(period));
elseif success then
bClickTrade = false;
end
leave = true;
end
end
if not (leave) then
if canBuy (period) then toBUY(period); end
if canSell(period) then toSELL(period);end
end
end
function balkEO(row,period,enum)
--offersTime = getOfferTime("OFFER_01");
offersTime = myCandleSourceBid:date(period);
--print(core.dateToTable(offersTime).hour..":"..core.dateToTable(offersTime).min..":"..core.dateToTable(offersTime).sec);
-- Check for Expired Entry Orders ------------------------------------
while (row ~= nil) do
if row.FixStatus == "W" then -- this finds all waiting orders
-- local sDuration = getTimeDiffMin(core.dateToTable(row.Time),core.dateToTable(offersTime));-- get time difference
sDuration = (offersTime - row.Time)*12*24; -- convert OLE Time to difference in Minutes
--print(core.dateToTable(row.Time).hour..":"..core.dateToTable(row.Time).min..":"..core.dateToTable(row.Time).sec)
--print (sDuration);
if row.OrderID == orderId and sDuration >= 20 then
return orderId;
end
row = enum:next();
end
end
return nil;
end
function ExtAsyncOperationFinished(cookie, success, message)
-- core.host:trace(tostring(cookie) .. " " .. tostring(success) .. " " .. tostring(message));
if cookie == cookieEntryOrder then -- Entry Order
if not success then
stage = 3; -- failed
bClickTrade = false;
orderId = nil;
else
stage = 2; -- executed
orderId = message; -- keep id of the created order
bClickTrade = true;
end
elseif cookie == cookieTradesTable then
if haveTrades(message) then
--open event is still bClickTrade
bClickTrade = true;
elseif not(haveTrades(message)) then
--close event
bClickTrade = false;
orderId = nil;
end
elseif cookie == cookieOrdersTable then
-- bClickTrade = false;
local d = 1;
elseif cookie == cookieCancelEntry then
-- bClickTrade = false;
local d = 1;
--terminal:alertMessage(instance.bid:instrument(), myCandleSourceBid.close[period], "Cancelled Entry Order", getOfferTime("OFFER_01"))
end
end
function canBuy(period) -- Check conditions for open trade BUY
--Buy
if (cci7.DATA[period] > 0.0) and
(cci50.DATA[period] > 0.0) and
(asi.DATA[period] > 0.0) and
(myCandleSourceBid.close[period] >= ema34.DATA[period]) and
not(bClickTrade)
--instrument.Ema34_5_Minute.EMAV > instrument.Ema200_5_Minute.EMAV &&
--instrument.asi5Minute.LastSwing == "high" &&
----last swing was the highest swing in the period of observation
--currentASIClose == instrument.ASI5Minute.Fibs.ExtremeASI &&
--instrument.LSFSwing.Angle > funcs.global.validAngle // &&
then
return true;
else
return false;
end
end
function canSell(period) -- Check conditions for open trade SELL
--Buy
if (cci7.DATA[period] < 0.0) and
(cci50.DATA[period] < 0.0) and
(asi.DATA[period] < 0.0) and
(myCandleSourceBid.close[period] <= ema34.DATA[period])
and not(bClickTrade)
--instrument.Ema34_5_Minute.EMAV > instrument.Ema200_5_Minute.EMAV &&
--instrument.asi5Minute.LastSwing == "high" &&
----last swing was the lowest swing in the period of observation
--currentASIClose == instrument.ASI5Minute.Fibs.ExtremeASI &&
--instrument.LSFSwing.Angle > funcs.global.validAngle // &&
then
return true;
else
return false;
end
end
function toBUY(period)
--terminal:alertMessage(instance.bid:instrument(), myCandleSourceBid.close[period], "Going to Buy", getOfferTime("OFFER_01"))
trade("B");
end
function toSELL(period)
--terminal:alertMessage(instance.bid:instrument(), myCandleSourceBid.close[period], "Going to Sell", getOfferTime("OFFER_01"))
trade("S");
end
------------------------------------------------ SET UP ORDER ---------------------------------------------------------------------
function trade(sDirection)
if sDirection == "B" then
local valuemap, success, msg;
valuemap = core.valuemap();
valuemap.Command = "CreateOrder";
valuemap.OrderType = "LE"; -- open market
valuemap.OfferID = Offer;
valuemap.AcctID = Account;
valuemap.Quantity = tradeSize;
valuemap.BuySell = "B";
valuemap.Rate = instance.ask[NOW] - (retracePips * pipSize);
setStopLimits(valuemap,valuemap.BuySell); -- executing
success, msg = terminal:execute(cookieEntryOrder, valuemap);
assert(success, msg);
if(success) then
bClickTrade = true;
-- orderId = info;
end
requestId = msg;
stage = 1;
elseif sDirection == "S" then
local valuemap, success, msg;
valuemap = core.valuemap();
valuemap.Command = "CreateOrder";
valuemap.OrderType = "LE"; -- open market
valuemap.OfferID = Offer;
valuemap.AcctID = Account;
valuemap.Quantity = tradeSize;
valuemap.BuySell = "S";
valuemap.Rate = instance.bid[NOW] + (retracePips * pipSize);
setStopLimits(valuemap,valuemap.BuySell); -- executing
success, msg = terminal:execute(cookieEntryOrder, valuemap);
assert(success, msg);
if(success) then
bClickTrade = true;
-- orderId = info;
end
requestId = msg;
stage = 1;
end
end
function setStopLimits(vm,bs)
local spread = (instance.ask[NOW] - instance.bid[NOW])/pipSize;
if SetLimit then
vm.PegTypeLimit = "M";
if bs == "B" then
--vm.Limit = vm.Rate + instance.parameters.Limit*pipSize;
vm.PegPriceOffsetPipsLimit = instance.parameters.Limit;
else
--vm.Limit = vm.Rate - instance.parameters.Limit*pipSize;
vm.PegPriceOffsetPipsLimit = -instance.parameters.Limit;
end
end
if SetStop then
vm.PegTypeStop = "M";
if bs == "B" then
--vm.Stop = vm.Rate - (instance.parameters.Stop * pipSize) + spread;
vm.PegPriceOffsetPipsStop = instance.parameters.Stop + spread;
else
--vm.Stop = vm.Rate + (instance.parameters.Stop * pipSize) - spread;
vm.PegPriceOffsetPipsStop = instance.parameters.Stop - spread;
end
if SetTS then
vm.TrailStepStop = 1;
end
end
end
-------------------------------------------- UTILITIES ---------------------------------------------------------------------------
function haveTrades(tradeId)
local enum, row;
local found = false;
enum = core.host:findTable("trades"):enumerator();
row = enum:next();
while (not found) and (row ~= nil) do
if row.TradeID == tradeId then
found = true;
end
row = enum:next();
end
return found
end
function getOfferTime(offerId)
local enum, row;
local found = false;
enum = core.host:findTable("offers"):enumerator();
row = enum:next();
while (not found) and (row ~= nil) do
if row.OfferID == offerId then
found = true;
return row.Time;
end
row = enum:next();
end
return found
end
function checkReady(table)
local rc;
if Account == "TESTACCT" then
-- run under debugger/simulator
rc = true;
else
rc = core.host:execute("isTableFilled", table);
end
return rc;
end
function getTimeDiffMin(i,f)
-- takes two formated dates and returns the difference in minutes
local nowSec = f.day*60*60*24 + f.hour*60*60 + f.min*60 + f.sec;
local orderSec = i.day*60*60*24 + i.hour*60*60 + i.min*60 + i.sec;
return (nowSec - orderSec)/60;
end
---------------------------------------------------------------------------------------------------------------------------------
dofile(core.app_path() .. "\\strategies\\standard\\include\\helper.lua");