Useful features from KimIV - page 12

 

The IndexByTicket() function.

Returns the index (ordinal number in the general list of set orders or open positions) of the order or position on the ticket. If IndexByTicket() cannot find an order or position with the required ticket, it will return -1. We can limit the list of orders or positions to be checked using the function parameters:

  • sy - Name of instrument. If you specify this parameter, the function will only check orders and positions of the specified instrument. NULL means the current instrument, and "" (by default) means any instrument.
  • op - Trade operation, type of pending order or position. Valid values: OP_BUY, OP_BUYLIMIT, OP_BUYSTOP, OP_SELL, OP_SELLLIMIT, OP_SELLSTOP or -1. The default value of -1 indicates any order or position.
  • mn - Identifier of an order or position (MagicNumber). Default value -1 means any MagicNumber.
//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 20.04.2007                                                     |
//|  Описание : Возвращает индекс ордера или позиции по тикету                 |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    ti - тикет ордера, позиции                                              |
//|    sy - наименование инструмента   (""   - любой символ,                   |
//|                                     NULL - текущий символ)                 |
//|    op - операция                   (-1   - любая позиция)                  |
//|    mn - MagicNumber                (-1   - любой магик)                    |
//+----------------------------------------------------------------------------+
int IndexByTicket(int ti, string sy="", int op=-1, int mn=-1) {
  int i, k=OrdersTotal();

  if (sy=="0") sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if ((OrderSymbol()==sy || sy=="") && (op<0 || OrderType()==op)) {
        if ((mn<0 || OrderMagicNumber()==mn) && OrderTicket()==ti) return(i);
      }
    }
  }
  return(-1);
}
 

I wrote the IndexByTicket() function in a custom EA. I remember that I could not do without it, otherwise why would I have written it? But I cannot remember how it was used there or why I practically wrote it :-) Looking for the source code of the advisor is boring. There are hundreds of them.

Anyway, I don't see the point in giving examples like the ones I've already given. If we are smart, we can figure out where to "put" the parameters. And if someone has a good idea of using the IndexByTicket() function, post it here. I will try to realize it.


A short announcement.

Functions SelectByTicket() and SelectByTicketFromHistory() I abolished. I won't use them myself, so I don't see the point in publishing them. Those who wish to discuss on this subject are always welcome. I will show all my delusions AS IS.

 

The NumberOfOrders() function.

This function returns the number of orders and functionally completely overrides ExistOrders(). To replace the ExistOrders() function with the NumberOfOrders() function, it is necessary and sufficient to check the return value so that it is greater than zero. You can limit the list of orders to be checked using the function parameters:

  • sy - Name of instrument. If this parameter is given, the function will only check the orders of the specified instrument. NULL means current instrument, and "" (by default) means any instrument.
  • op - Type of pending order. Valid values: OP_BUYLIMIT, OP_BUYSTOP, OP_SELLLIMIT, OP_SELLSTOP or -1. The default value of -1 means any order.
  • mn - Order identifier (MagicNumber). Default value -1 means any MagicNumber.
//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 28.11.2006                                                     |
//|  Описание : Возвращает количество ордеров.                                 |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    sy - наименование инструмента   (""   - любой символ,                   |
//|                                     NULL - текущий символ)                 |
//|    op - операция                   (-1   - любой ордер)                    |
//|    mn - MagicNumber                (-1   - любой магик)                    |
//+----------------------------------------------------------------------------+
int NumberOfOrders(string sy="", int op=-1, int mn=-1) {
  int i, k=OrdersTotal(), ko=0, ot;

  if (sy=="0") sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      ot=OrderType();
      if (ot>1 && ot<6) {
        if ((OrderSymbol()==sy || sy=="") && (op<0 || ot==op)) {
          if (mn<0 || OrderMagicNumber()==mn) ko++;
        }
      }
    }
  }
  return(ko);
}
 

Examples of how to use the NumberOfOrders() function.

  1. Get the total amount of all orders
    NumberOfOrders();
  2. Get the number of orders placed for the current symbol
    NumberOfOrders(NULL);
  3. Obtain the number of BuyLimit orders for any symbol
    NumberOfOrders("", OP_BUYLIMIT);
  4. Obtain the number of SellStop orders with magic number 123456 for EURUSD
    NumberOfOrders("EURUSD", OP_SELLSTOP, 123456);
  5. Get the number of orders with a magic number 2345 for the current symbol
    NumberOfOrders(NULL, -1, 2345);

Attached here is again a working script with the above examples.

Files:
 
KimIV:

The NumberOfOrders() function.

This function returns the number of orders and functionally completely overrides ExistOrders(). To replace the ExistOrders() function with the NumberOfOrders() function, it is necessary and sufficient to check the return value so that it is greater than zero. You can limit the list of orders to be checked using the function parameters:

  • sy - Name of instrument. If this parameter is given, the function will only check the orders of the specified instrument. NULL means current instrument, and "" (by default) means any instrument.
  • op - Type of pending order. Valid values: OP_BUYLIMIT, OP_BUYSTOP, OP_SELLLIMIT, OP_SELLSTOP or -1. The default value of -1 means any order.
  • mn - Order identifier (MagicNumber). The default value of -1 means any MagicNumber.

I'm a little confused. For some reason, I see some contradiction. Right here:

"...it is necessary and sufficient to check that the return value is greater than zero."

If you check "this and only this", then the function on the number of orders is meaningless!

That's why I started getting into it. I have inserted this function into my Expert Advisor. I set m=1 in parameters and condition to open positions.

if (NumberOfOrders("", -1, MagicNumber)<m) {//если открытых позиций МЕНЬШЕ m

But it is as if the Expert Advisor does not see this limitation! And it opens orders at every signal.

What can be the problem here?

 
rid писал (а):
I am confused a bit. For some reason, I see a certain contradiction. Right here:
"...it is necessary and sufficient to check the return value to be greater than zero".
If we check "this and only this", then the function for the number of orders is meaningless!

hmm... You don't seem to be paying attention to the amount of information returned by each of the ExistOrders() and NumberOfOrders() functions. The ExistOrders() function only returns information about the existence of orders, and the NumberOfOrders() function returns information about the number of orders. The information about the number of orders contains the information about the existence of orders. When we need to answer the question whether an order exists or not, information about the number of orders is redundant. That is why I said that if we want to replace the ExistOrders() function with the NumberOfOrders() function, we should check the value returned by the NumberOfOrders() function to make sure that it is greater than zero. After all, it is clear that if this value is equal to zero, there are no orders, and if this value is greater than zero, the orders are present. The ExistOrders() function can be used when we do not need information about the order quantity, while NumberOfOrders() function can be used when we don't need information about the order quantity and when we do need it. In this sense, the NumberOfOrders() function completely replaces the ExistOrders() function.

rid:

Here's why I've started to look into it. I have inserted this function into my Expert Advisor. I set m=1 in parameters and condition to open positions.

if (NumberOfOrders("", -1, MagicNumber)<m) {//если открытых позиций МЕНЬШЕ m

But it is as if the Expert Advisor does not see this constraint! And it opens orders at every signal.

What may be the problem here?

So... and here you seem to be confusing positions with warrants. To me they are different things. What are positions? They are OP_BUY and OP_SELL trades, while orders in my understanding are OP_BUYLIMIT, OP_BUYSTOP, OP_SELLLIMIT and OP_SELLSTOP trades. I open positions and I set orders. And what do you open? The NumberOfOrders() function is designed to work with orders.
 

Thank you. Got it all. Both on the first question and on the second.

In other words, the "extended" NumberOfOrders() function essentially already includes the IndexByTicket() function

Yes, indeed. I opened OP_BUY and OP_SELL !

It remains to give an example of your next function which works exactly with positions. (not with orders).

I remember you've already posted it somewhere on this forum. I can't find it.

 
rid писал (а):
It remains to give an example of your next function which works exactly with positions. (not with orders)

I am done with the functions for orders. Next are the functions for positions. There are about 30 of them.


rid wrote (a):
I remember somewhere on the forum you already posted it. I cannot find it.

search

 

Dear Igor, I'm asking for your help! I need to add an EA so that it could take positions on several instruments. There are 2 EAs working, standard MACD and Ema, each with 6 positions, but only one position opens... I read your comments regarding this, but as I'm not good with the language, I can't understand where to add what... If you don't mind, please help... copied Ema adviser... Thank you!



//+------------------------------------------------------------------+
//| Parabolic.mq4 |
//| Vitalik |
//| wwwita@mail.ru |
//+------------------------------------------------------------------+
extern double Lots=0.1;
extern double Pip=5;
extern double MoveBack=3;
extern int chk=0;
extern double SL=20;
//+------------------------------------------------------------------+
//|
//+------------------------------------------------------------------+
int start()
{
double hi=High[1];
double lo=Low[1];
double EMA, EMA1, EMA2, EMA3;
int cnt=0, ticket, total;
EMA=iMA(0,0,5,0,MODE_EMA,PRICE_MEDIAN,1);
EMA1=iMA(0,0,10,0,MODE_EMA,PRICE_MEDIAN,1);
EMA2=iMA(0,0,5,0,MODE_EMA,PRICE_MEDIAN,0);
EMA3=iMA(0,0,10,0,MODE_EMA,PRICE_MEDIAN,0);
total=OrdersTotal();
if(total<1)
{
if(AccountFreeMargin()<(1000*Lots))
{
Print("You have no money. Free funds = ", AccountFreeMargin());
return(0);
}
if(((EMA>EMA1) && (EMA2<EMA3)) || ((EMA<EMA1) && (EMA2>EMA3))
{
chk=1;
Print("Position is possible!");
}
if(chk==1)
{
if(EMA3-EMA2>2*Point && Bid>=(lo+MoveBack*Point))
{
ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,0,
"EMA position:",16385,0,Red);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("SELL order open : ",OrderOpenPrice());
chk=0;
}
else
{
Print("Error opening SELL order : ",GetLastError());
return(0);
}
}
if(EMA2-EMA3>2*Point && Ask<=(hi-MoveBack*Point))
{
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,0,
"EMA position:",16385,0,Green);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("BUY order open : ",OrderOpenPrice());
chk=0;
}
else
{
Print("Order BUY open error : ",GetLastError());
return(0);
}
}
}
return(0);
}
for(cnt=0;cnt<total;cnt++)
{
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(OrderType()<=OP_SELL && // is this an open position? OP_BUY or OP_SELL
OrderSymbol()==Symbol()) // tool match?
{
if(OrderType()==OP_BUY) // long position opened
{
// let's check if it is already time to close?
if(Bid>=(OrderOpenPrice()+Pip*Point))
{
chk=0;
OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position
return(0); // exit
}
if(Bid<=(OrderOpenPrice()-SL*Point))
{
chk=0;
OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position
return(0); // exit
}
}
else // otherwise this is a short position
{
// check if it is already time to close?
if(Ask<=(OrderOpenPrice()-Pip*Point))
{
chk=0;
OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // close position
return(0); // exit
}
if(Ask>=(OrderOpenPrice()+SL*Point))
{
chk=0;
OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // close position
return(0); // exit
}
}
}
}
return(0);
}
//+------------------------------------------------------------------+
 

Igor, I asked you a question in the 'Library of functions for working with INI files.' but there was no answer :(

Reason: