Since this is a coding question, I thought it might be fun to evolve a simple OCO EA in the forum. Below is the beginning of code that might one day handle all your OCO needs....gaheitman wrote:I still like an EA for this. Perhaps with a script to enter the orders (assuming you can't program that logic as well) with paired MagicNumbers and the EA would just manage them as they appear.
George
In a nutshell, all it does is this:
- See if there are any open/pending orders for the current chart symbol
- If there is one pending order, delete it
- If there are two orders
- If either is an open order, try to delete the other one
It is, of course, completely untested. I thought we should agree on what it should do before testing.
Code: Select all
//+------------------------------------------------------------------+
//| OCO-Watcher.mq4 |
//| Copyright © 2012, George Heitman |
//| http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2012, George Heitman"
#property link "http://www.stevehopwoodforex.com/phpBB3/viewtopic.php?f=15&t=237"
int init() {
return(0);
}
int deinit() {
return(0);
}
int start() {
//only check once per minute
static int M1BarCount=0;
if (M1BarCount == iBars(Symbol(),PERIOD_M1)) return(0);
M1BarCount=iBars(Symbol(),PERIOD_M1);
//make array of all open/pending tickets
int total=OrdersTotal();
if (total == 0) return(0);
int OpenTickets[]; //array to hold all our ticket numbers
ArrayResize(OpenTickets, total); //make it big enough to hold all of them
ArrayInitialize(OpenTickets, 0);
int i; //i will iterate over all orders
int cnt=0; //cnt will hold the number of trades to manage
for(i = 0; i < total; i++) {
if(OrderSelect(i, SELECT_BY_POS,MODE_TRADES)) {
//skip the ones that don't match our symbol and MN
if(OrderSymbol() != Symbol()) continue;
// if(OrderMagicNumber() != MagicNumber) continue; - gah let's ignore these for now
OpenTickets[cnt] = OrderTicket(); //It's a match, save it to the array
cnt++;
}//if(OrderSelect(i, SELECT_BY_POS))
}//for(i = 0; i < OrdersTotal(); i++)
//first case is easy, we didn't find any so return
if (cnt==0) return;
//second case is a bit of an open question. what if we find just one?
//the code here will delete the order if it is a pending type.
if (cnt==1) {
if(OrderSelect(OpenTickets[0],SELECT_BY_TICKET)) {
switch(OrderType())
{
case OP_SELL:
case OP_BUY: break;
case OP_SELLSTOP:
case OP_BUYSTOP:
case OP_SELLLIMIT:
case OP_BUYLIMIT: OrderDelete(OrderTicket());
}
}
}
//ok, here's the interesting one, we found two. We find out
//the type of each, and if one is open, delete the other one
int type1 = -1;
int type2 = -1;
if (cnt == 2) {
if (OrderSelect(OpenTickets[0],SELECT_BY_TICKET))
type1=OrderType();
if (OrderSelect(OpenTickets[1],SELECT_BY_TICKET))
type2=OrderType();
//this is a test to make sure we set them correctly, if not, exit
if (type1 == -1 || type2 == -1) return;
//we are lazy here and count on OrderDelete failing if the other
//trade is actually open
if (type1 <= OP_SELL) OrderDelete(OpenTickets[1]);
if (type2 <= OP_SELL) OrderDelete(OpenTickets[0]);
}
return(0);
}