checking status of limit orders

Questions about MultiCharts and user contributed studies.
janus
Posts: 838
Joined: 25 May 2009
Has thanked: 64 times
Been thanked: 105 times

checking status of limit orders

Postby janus » 27 Jan 2011

Apart from checking the position count, is there a more reliable and accurate way of determining if and when a limit order is filled from within a study?

User avatar
Dave Masalov
Posts: 1712
Joined: 16 Apr 2010
Has thanked: 51 times
Been thanked: 489 times

Re: checking status of limit orders

Postby Dave Masalov » 28 Jan 2011

Dear janus,

It is the only way to check if the limit order was filled from the code.

janus
Posts: 838
Joined: 25 May 2009
Has thanked: 64 times
Been thanked: 105 times

Re: checking status of limit orders

Postby janus » 29 Jan 2011

Not the news I was hoping for. I find it impossible to be sure in a study all the time that a limit order is completely filled when cover orders are also submitted in the same direction as the limit order. Oh well, can't have everything.

User avatar
Dave Masalov
Posts: 1712
Joined: 16 Apr 2010
Has thanked: 51 times
Been thanked: 489 times

Re: checking status of limit orders

Postby Dave Masalov » 04 Feb 2011

Dear janus,

If you have a suggestion on how it can be realized, please post a feature request in Project Management.

Rommi
Posts: 9
Joined: 15 Sep 2010

Re: checking status of limit orders

Postby Rommi » 04 Feb 2011

Dear janus,

If you have a suggestion on how it can be realized, please post a feature request in Project Management.
It is allready there, posted by me (MC-99 " Order execution control").
I think it is minimal that traders need. Of cource it will be better to have orderstatus function
like OrderStatus(OrderName) and it returns string -filled,placed,paritally filled,canceled,pending or if no such order returns 0).

janus
Posts: 838
Joined: 25 May 2009
Has thanked: 64 times
Been thanked: 105 times

Re: checking status of limit orders

Postby janus » 05 Feb 2011

Of cource it will be better to have orderstatus function
like OrderStatus(OrderName) and it returns string -filled,placed,paritally filled,canceled,pending or if no such order returns 0).
Yes, something like that would be ideal, if not essential for any serious trader.

janus
Posts: 838
Joined: 25 May 2009
Has thanked: 64 times
Been thanked: 105 times

Re: checking status of limit orders

Postby janus » 06 Feb 2011

Meanwhile I've stitched up this code to workaround the issue. I haven't tested it enough to be confident it works all the time - so far it's good. I'm going to test it with a pyramid strategy. I would be surprised if it does work all the time. Of course, more work has to be programmed when this workaround is to be used in a strategy. The more complex the strategy the harder it will be. Clearly, the only real solution is for MC to add the feature discussed earlier.

Code: Select all

[IntrabarOrderGeneration = True]

// Note: In Format Signal -> Intra-Bar Order Generation - set to "Allow unlimited entries and exits per bar", and
// Strategy Properties -> Properties - Allow up to a sufficiently large number of entry orders in the same
// direction as the currently held position, regardless of the entry that generated the order,
// with a suitable maximum shares/contracts per position

variables:
n(0), n1(0), n2(0), profit(0), max.lots(10), num.covered(0),
intrabarpersist posi(0), intrabarpersist qty(0), intrabarpersist num.to.fill(0),
intrabarpersist nlot(0), intrabarpersist delay(-1), intrabarpersist init.posi(0),
num.total(10), num.inc(2), intrabarpersist num.left(0), intrabarpersist exec.order(0),
intrabarpersist prev.posi(0);

arrays:
intrabarpersist entry.price[10](0), intrabarpersist entry.num[10](0), intrabarpersist sell.limit[10](False),
intrabarpersist sell.limit.sent[10](False), intrabarpersist exit.price[10](0), intrabarpersist buy.limit[10](False),
intrabarpersist buy.limit.sent[10](False);


once begin
cleardebug;
print ("Started simulation");
profit = 5; // number of points profit for each entry
num.left = 5; // number of contracts total to process
exec.order = 1; // test buy order(s) with corresponding sell limit order(s)
end;


if LastBarOnChart_s and getappinfo(aiStrategyAuto) = 1 and GetAppInfo(airealtimecalc) = 1 then begin // last bar and real-time

posi = MarketPosition_at_Broker; // current position

if ((posi >= 0 and prev.posi > 0) or (posi <= 0 and prev.posi < 0))
and absvalue(posi) < absvalue(prev.posi) then begin // contracts were reduced so a limit order must have been hit
num.covered = absvalue(prev.posi)-absvalue(posi); // number covered
print (num.covered:0:0, " contracts covered");

// look for the most likely limit order(s) that was(were) filled - lowest entry price for sell limits, highest for buy limits
while num.covered > 0 begin // loop until exact number covered are accounted for
n1 = 0;
n2 = 0;
for n = 1 to max.lots begin
if entry.num[n] > 0 then begin
if n1 = 0 or (prev.posi > 0 and entry.price[n] < n1) or (prev.posi < 0 and entry.price[n] > n1) then begin
n1 = entry.price[n];
n2 = n;
end;
end;
end;
if entry.num[n2] >= num.covered then begin // sufficient number in lot #n2 so terminate loop
entry.num[n2] = entry.num[n2] - num.covered; // reduce number for this lot
num.covered = 0; // terminate loop since all are now accounted for
end else begin // insufficient in lot #n2 so keep looping
num.covered = num.covered - entry.num[n2]; // adjust for remaining number covered
entry.num[n2] = 0; // clear this lot
end;
end;
end;

if nlot > 0 and num.to.fill > 0 and absvalue(posi) - absvalue(init.posi) >= num.to.fill then begin // requested number of contracts are filled
print ("Order filled for lot #",nlot:0:0);
if nlot = 1 then begin // 1st lot so store entry price
entry.price[1] = avgentryprice;
end else begin // 2nd or more lot so compute entry price of additional entries
n1 = 0;
n2 = 0;
for n = 1 to nlot-1 begin
n1 = n1 + entry.num[n] * entry.price[n];
n2 = n2 + entry.num[n];
end;
n2 = n2 + num.to.fill;
entry.price[nlot] = (avgentryprice*n2 - n1)/num.to.fill;
end;
entry.num[nlot] = num.to.fill; // number of contracts filled for this lot
if posi > 0 then exit.price[nlot] = entry.price[nlot] + profit; // sell limit to take profit on longs
if posi < 0 then exit.price[nlot] = entry.price[nlot] - profit; // buy limit to take profit on shorts
num.to.fill = 0; // all entries filled for this lot - prepare for the next lot to fill, if any
if posi > 0 then sell.limit[nlot] = True; // now long so set flag to send sell limit order for this lot
if posi < 0 then buy.limit[nlot] = True; // now short so set flag to send buy limit order for this lot
end;


if posi > 0 then begin // currently long so set or continue any sell limit order(s)
if sell.limit[1] then sell ("CL#1") from entry ("BL#1") next bar at exit.price[1] limit;
if sell.limit[2] then sell ("CL#2") from entry ("BL#2") next bar at exit.price[2] limit;
if sell.limit[3] then sell ("CL#3") from entry ("BL#3") next bar at exit.price[3] limit;
if sell.limit[4] then sell ("CL#4") from entry ("BL#4") next bar at exit.price[4] limit;
if sell.limit[5] then sell ("CL#5") from entry ("BL#5") next bar at exit.price[5] limit;
if sell.limit[6] then sell ("CL#6") from entry ("BL#6") next bar at exit.price[6] limit;
if sell.limit[7] then sell ("CL#7") from entry ("BL#7") next bar at exit.price[7] limit;
if sell.limit[8] then sell ("CL#8") from entry ("BL#8") next bar at exit.price[8] limit;
if sell.limit[9] then sell ("CL#9") from entry ("BL#9") next bar at exit.price[9] limit;
if sell.limit[10] then sell ("CL#10") from entry ("BL#10") next bar at exit.price[10] limit;

end else if posi < 0 then begin// currently short so set or continue any buy limit order(s)
if buy.limit[1] then buytocover ("CS#1") from entry ("SS#1") next bar at exit.price[1] limit;
if buy.limit[2] then buytocover ("CS#2") from entry ("SS#2") next bar at exit.price[2] limit;
if buy.limit[3] then buytocover ("CS#3") from entry ("SS#3") next bar at exit.price[3] limit;
if buy.limit[4] then buytocover ("CS#4") from entry ("SS#4") next bar at exit.price[4] limit;
if buy.limit[5] then buytocover ("CS#5") from entry ("SS#5") next bar at exit.price[5] limit;
if buy.limit[6] then buytocover ("CS#6") from entry ("SS#6") next bar at exit.price[6] limit;
if buy.limit[7] then buytocover ("CS#7") from entry ("SS#7") next bar at exit.price[7] limit;
if buy.limit[8] then buytocover ("CS#8") from entry ("SS#8") next bar at exit.price[8] limit;
if buy.limit[9] then buytocover ("CS#9") from entry ("SS#9") next bar at exit.price[9] limit;
if buy.limit[10] then buytocover ("CS#10") from entry ("SS#10") next bar at exit.price[10] limit;

end;

// check status of limit orders
for n = 1 to max.lots begin
// ?? if posi = 0 then sell.limit[n] = False; // reset if flat
// ?? if posi = 0 then sell.limit.sent[n] = False; // as above
if sell.limit[n] and not sell.limit.sent[n] then begin
print ("Sent new sell limit for lot #",n:0:0, " with price limit = ",exit.price[n]);
sell.limit.sent[n] = True; // avoids repeating the message
end;
end;


// start with one buy order, wait for it to be filled then send a sell limit order attached to it,
// then send another buy order, and again wait for it to be filled and also send another sell limit order attached to it. Keep doing this until all
// required contracts are bought.
qty = 0;
if num.to.fill = 0 and num.left > 0 and delay <= 0 then begin // outstanding contracts to process
if delay = 0 and delay[1] > 0 then print ("delay has expired");
nlot = nlot + 1; // lot number
if nlot > max.lots then begin // too many lots
print ("WARMING: reached maximum number of allowed lots; ",num.left:0:0, " contracts remaining - ignored");
num.left = 0; // ignore the remaining contracts
end else begin
print ("buying lot #", nlot:0:0);
if num.left >= num.inc then begin
qty = num.inc; // qty to process for this lot
num.left = num.left - num.inc; // reduce the number of contracts left to process; could be the last
end else begin // less than a lot size left to process so adjust
qty = num.left; // qty to process for this lot
num.left = 0; // this is the last lot; no more left to process after this one
end;
if exec.order = 1 then begin // buy long order
if nlot = 1 then buy ("BL#1") qty contracts next bar at market;
if nlot = 2 then buy ("BL#2") qty contracts next bar at market;
if nlot = 3 then buy ("BL#3") qty contracts next bar at market;
if nlot = 4 then buy ("BL#4") qty contracts next bar at market;
if nlot = 5 then buy ("BL#5") qty contracts next bar at market;
if nlot = 6 then buy ("BL#6") qty contracts next bar at market;
if nlot = 7 then buy ("BL#7") qty contracts next bar at market;
if nlot = 8 then buy ("BL#8") qty contracts next bar at market;
if nlot = 9 then buy ("BL#9") qty contracts next bar at market;
if nlot = 10 then buy ("BL#10") qty contracts next bar at market;
sell.limit[nlot] = False; // reset flag
sell.limit.sent[nlot] = False; // reset flag
end else if exec.order = 2 then begin // sell short order
if nlot = 1 then sellshort ("SS#1") qty contracts next bar at market;
if nlot = 2 then sellshort ("SS#2") qty contracts next bar at market;
if nlot = 3 then sellshort ("SS#3") qty contracts next bar at market;
if nlot = 4 then sellshort ("SS#4") qty contracts next bar at market;
if nlot = 5 then sellshort ("SS#5") qty contracts next bar at market;
if nlot = 6 then sellshort ("SS#6") qty contracts next bar at market;
if nlot = 7 then sellshort ("SS#7") qty contracts next bar at market;
if nlot = 8 then sellshort ("SS#8") qty contracts next bar at market;
if nlot = 9 then sellshort ("SS#9") qty contracts next bar at market;
if nlot = 10 then sellshort ("SS#10") qty contracts next bar at market;
buy.limit[nlot] = False; // reset flag
buy.limit.sent[nlot] = False; // reset flag
end;
num.to.fill = qty; // number of contracts expecting to be filled for this lot
init.posi = posi; // current position size; will wait when position size >= this + number to fill for this lot
end;
delay = 0; // introduce a delay (# ticks) between successive lots; 0 = no delay
end;
if delay > 0 then delay = delay - 1;
prev.posi = posi;
end;


Return to “MultiCharts”