Selecting Order from 2 same symbols

 

Hi,

I'm trying to select order to get its detail, but currently I have two long trades on USDCAD, and the OrderSelect wont select any.


This is the code:


      for (int i=0; i<all_order;i++) {    

         if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==TRUE) {   


            if(OrderSymbol()==symbol_chart) {      // order selected, and compare if same as current chart symbol

               int ticket = OrderTicket();

//action etc...

   }

          }

}


It works when there's only ONE trade of a symbol. But when TWO exist, the script doesnt run.


Please advise on how to select a trade and get its information (without using Magic number). Thanks.

 
tchandara:

Hi,

I'm trying to select order to get its detail, but currently I have two long trades on USDCAD, and the OrderSelect wont select any.


This is the code:


for (int i=0; i<all_order;i++) {

if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==TRUE) {


if(OrderSymbol()==symbol_chart) { // order selected, and compare if same as current chart symbol

int ticket = OrderTicket();

//action etc...

}

}

}


It works when there's only ONE trade of a symbol. But when TWO exist, the script doesnt run.


Please advise on how to select a trade and get its information (without using Magic number). Thanks.

Try counting down in your loop, like this:

for (int i=all_order-1; i>=0;i--)

 

Hi robofx,

Brilliant! it selects one of them.

Thanks.

 
tchandara:

Hi robofx,

Brilliant! it selects one of them.

For completeness... there's nothing intrinsically wrong with your original code, at least in the form you posted it. However, the fact that things work when you count down from OrdersTotal(), rather than up from zero, almost certainly implies that the part you've marked "// action etc..." is deleting or closing orders.


The problem which is remedied by counting down occurs as follows when counting up: i starts off at zero, and you close the order at position #0. The variable i gets incremented from zero to one. But the open order which was previously at position #1 moves to position #0, because of the deletion, and therefore this second order gets ignored. If you had ten orders, only five would be processed and five would be overlooked.


 
jjc wrote >>

For completeness... there's nothing intrinsically wrong with your original code, at least in the form you posted it. However, the fact that things work when you count down from OrdersTotal(), rather than up from zero, almost certainly implies that the part you've marked "// action etc..." is deleting or closing orders.

The problem which is remedied by counting down occurs as follows when counting up: i starts off at zero, and you close the order at position #0. The variable i gets incremented from zero to one. But the open order which was previously at position #1 moves to position #0, because of the deletion, and therefore this second order gets ignored. If you had ten orders, only five would be processed and five would be overlooked.

jjc /robofx...all What would be the best way to code this to close the OLDEST orders first to comply with the FIFO BS in the US??

The way it's currently coded it closes the newest order first.....

 
n8937g:

jjc /robofx...all What would be the best way to code this to close the OLDEST orders first to comply with the FIFO BS in the US??

If you could rely on MT4's order list being in trade-open order, then the easiest option would be something like this


int i = 0;

while (i < OrdersTotal())

{

OrderSelect(i, SELECT_BY_POS);


// Delete pending orders and close open orders

bool bSuccessfullyClosedOrder;

switch (OrderType())

{

case OP_BUY:

bSuccessfullyClosedOrder = OrderClose(OrderTicket(), OrderLots(), MarketInfo(Symbol(), MODE_BID), 999);

break;


case OP_SELL:

bSuccessfullyClosedOrder = OrderClose(OrderTicket(), OrderLots(), MarketInfo(Symbol(), MODE_ASK), 999);

break;


default:

// Pending order. Could simply do bSuccessfullyClosedOrder = false if you want to ignore pending orders

bSuccessfullyClosedOrder = OrderDelete(OrderTicket());

break;

}


if (bSuccessfullyClosedOrder)

{

// Leave i untouched, because OrdersTotal() decrements

} else {

// Closure/deletion failed. Ignore, and move on to the next order

i++;

}

}


However, I don't think you can rely on the ordering of MT4's list in this way. The list is presumably in trade-placement order, not fill-order. Therefore if orders 1 and 2 start off as pending, and 2 gets filled first, the MT4 list probably isn't reordered to take account of the fact. Therefore, the MT4 order list doesn't necessarily give you the orders on the sort of FIFO basis you're looking for.


The only alternative seems to be to build a list of trades and their fill-times, sort the list by fill-time, and then run through that trade list. Something like the following ought to work. Relies on the relatively obscure fact that ArraySort() works on multi-dimensional arrays.


// Create an array to hold the tickets of open orders. The following code could

// be changed to that it also includes pending orders.

int TradeList[][2];

int ctTrade = 0;


// Loop through the list of open orders, adding orders to TradeList if they are filled rather than pending

for (i = 0; i < OrdersTotal(); i++) {

OrderSelect(i, SELECT_BY_POS);

switch (OrderType()) {

case OP_BUY:

case OP_SELL:

// Resize the array

ctTrade++;

ArrayResize(TradeList, ctTrade);

// Put the open time in [x][0] and the ticket in [x][1]

TradeList[ctTrade - 1][0] = OrderOpenTime();

TradeList[ctTrade - 1][1] = OrderTicket();

break;

default:

// Pending order. Ignore.

break;

}

}


// Sort the array. This sorts on [x][0], therefore ordering the array

// in ascending order of open time. After this [0][0] holds the first open-time,

// and [0][1] holds the corresponding ticket number

ArraySort(TradeList, WHOLE_ARRAY, 0, MODE_ASCEND);


// It's now possible to loop through the array doing something with

// the tickets (and without needing to worry about the effect

// on ctTrade of closing orders etc)

for (i = 0; i < ctTrade; i++) {

OrderSelect(TradeList[i][1], SELECT_BY_TICKET);

// Action...

}


 
jjc wrote >>

If you could rely on MT4's order list being in trade-open order, then the easiest option would be something like this

int i = 0;

while (i < OrdersTotal())

{

OrderSelect(i, SELECT_BY_POS);

// Delete pending orders and close open orders

bool bSuccessfullyClosedOrder;

switch (OrderType())

{

case OP_BUY:

bSuccessfullyClosedOrder = OrderClose(OrderTicket(), OrderLots(), MarketInfo(Symbol(), MODE_BID), 999);

break;

case OP_SELL:

bSuccessfullyClosedOrder = OrderClose(OrderTicket(), OrderLots(), MarketInfo(Symbol(), MODE_ASK), 999);

break;

default:

// Pending order. Could simply do bSuccessfullyClosedOrder = false if you want to ignore pending orders

bSuccessfullyClosedOrder = OrderDelete(OrderTicket());

break;

}

if (bSuccessfullyClosedOrder)

{

// Leave i untouched, because OrdersTotal() decrements

} else {

// Closure/deletion failed. Ignore, and move on to the next order

i++;

}

}

However, I don't think you can rely on the ordering of MT4's list in this way. The list is presumably in trade-placement order, not fill-order. Therefore if orders 1 and 2 start off as pending, and 2 gets filled first, the MT4 list probably isn't reordered to take account of the fact. Therefore, the MT4 order list doesn't necessarily give you the orders on the sort of FIFO basis you're looking for.

The only alternative seems to be to build a list of trades and their fill-times, sort the list by fill-time, and then run through that trade list. Something like the following ought to work. Relies on the relatively obscure fact that ArraySort() works on multi-dimensional arrays.

// Create an array to hold the tickets of open orders. The following code could

// be changed to that it also includes pending orders.

int TradeList[][2];

int ctTrade = 0;

// Loop through the list of open orders, adding orders to TradeList if they are filled rather than pending

for (i = 0; i < OrdersTotal(); i++) {

OrderSelect(i, SELECT_BY_POS);

switch (OrderType()) {

case OP_BUY:

case OP_SELL:

// Resize the array

ctTrade++;

ArrayResize(TradeList, ctTrade);

// Put the open time in [x][0] and the ticket in [x][1]

TradeList[ctTrade - 1][0] = OrderOpenTime();

TradeList[ctTrade - 1][1] = OrderTicket();

break;

default:

// Pending order. Ignore.

break;

}

}

// Sort the array. This sorts on [x][0], therefore ordering the array

// in ascending order of open time. After this [0][0] holds the first open-time,

// and [0][1] holds the corresponding ticket number

ArraySort(TradeList, WHOLE_ARRAY, 0, MODE_ASCEND);

// It's now possible to loop through the array doing something with

// the tickets (and without needing to worry about the effect

// on ctTrade of closing orders etc)

for (i = 0; i < ctTrade; i++) {

OrderSelect(TradeList[i][1], SELECT_BY_TICKET);

// Action...

}

Thanks JJC,

Yes...It would be easier if the order list was in the proper order..... I'll test it with both of your suggestions....Thanks again!!

 
n8937g:

Thanks JJC,

Yes...It would be easier if the order list was in the proper order..... I'll test it with both of your suggestions....Thanks again!!

jjc yourcode DOES close the oldest order first...and should work with the new NFA rules...( I have moved all of my accounts out of US except for FXDD) but how could this code be changed to close ONLY the OLDEST order....Just the OLDEST one and not any more until a condition was met again.... if(AccountFreeMargin()<AccountMargin())

I have tried everything I could think of...but can't get it to either just close one....or not end up in a hopeless error loop.....Thanks






if(AccountFreeMargin() <AccountMargin())
int K = OrdersTotal();

while (AccountFreeMargin() <AccountMargin())

{

OrderSelect(K, SELECT_BY_POS);


// Delete pending orders and close open orders

bool bSuccessfullyClosedOrder;

switch (OrderType())

{

case OP_BUY:

bSuccessfullyClosedOrder = OrderClose(OrderTicket(), OrderLots(), MarketInfo(Symbol(), MODE_BID), 999);

break;


case OP_SELL:

bSuccessfullyClosedOrder = OrderClose(OrderTicket(), OrderLots(), MarketInfo(Symbol(), MODE_ASK), 999);

break;


default:

// Pending order. Could simply do bSuccessfullyClosedOrder = false if you want to ignore pending orders

bSuccessfullyClosedOrder = OrderDelete(OrderTicket());

break;

}


if (bSuccessfullyClosedOrder)

{

// Leave i untouched, because OrdersTotal() decrements

} else {

// Closure/deletion failed. Ignore, and move on to the next order

K=0;

}

}
 

Just loop through it all once doing something like this:

datetime oldest = 0;

int oldest_ticket = -1;

//Usual selecting loop and stuff

if(OrderOpenTime() < oldest || oldest == 0){oldest = OrderOpenTime(); oldest_ticket = OrderTicket();}

//Outside the loop

if(oldest_ticket != -1){ OrderClose(...); /* Or whatever else you wanna do to the oldest order*/}

Jon

Reason: