Funciones útiles de KimIV - página 12

 

La función IndexByTicket().

Devuelve el índice (número ordinal en la lista general de órdenes establecidas o posiciones abiertas) de la orden o posición en el ticket. Si IndexByTicket() no encuentra una orden o posición con el ticket requerido, devolverá -1. Podemos limitar la lista de órdenes o posiciones a comprobar mediante los parámetros de la función:

  • sy - Nombre del instrumento. Si especifica este parámetro, la función sólo comprobará las órdenes y posiciones del instrumento especificado. NULL significa el instrumento actual, y "" (por defecto) significa cualquier instrumento.
  • op - Operación comercial, tipo de orden pendiente o posición. Valores válidos: OP_BUY, OP_BUYLIMIT, OP_BUYSTOP, OP_SELL, OP_SELLLIMIT, OP_SELLSTOP o -1. El valor por defecto de -1 indica cualquier orden o posición.
  • mn - Identificador de una orden o posición (MagicNumber). El valor por defecto -1 significa cualquier 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);
}
 

Escribí la función IndexByTicket() en un EA personalizado. Recuerdo que no podía prescindir de él, si no, ¿por qué lo habría escrito? Pero no recuerdo cómo se usaba allí ni por qué lo escribí prácticamente :-) Buscar el código fuente del asesor es aburrido. Hay cientos de ellos.

De todas formas, no veo el sentido de poner ejemplos como los que ya he puesto. Si somos inteligentes, podemos averiguar dónde "poner" los parámetros. Y si alguien tiene una buena idea para utilizar la función IndexByTicket(), que la publique aquí. Intentaré realizarlo.


Un breve anuncio.

Funciones SelectByTicket() y SelectByTicketFromHistory() suprimidas. Yo no los utilizaré, así que no veo el sentido de publicarlos. Quienes deseen debatir sobre este tema son siempre bienvenidos. Mostraré todos mis delirios TAL CUAL.

 

La función NumberOfOrders().

Esta función devuelve el número de pedidos y anula completamente ExistOrders(). Para sustituir la función ExistOrders() por la función NumberOfOrders(), es necesario y suficiente comprobar el valor de retorno para que sea mayor que cero. Puede limitar la lista de órdenes a comprobar mediante los parámetros de la función:

  • sy - Nombre del instrumento. Si se da este parámetro, la función sólo comprobará las órdenes del instrumento especificado. NULL significa instrumento actual, y "" (por defecto) significa cualquier instrumento.
  • op - Tipo de orden pendiente. Valores válidos: OP_BUYLIMIT, OP_BUYSTOP, OP_SELLLIMIT, OP_SELLSTOP o -1. El valor por defecto de -1 indica cualquier orden.
  • mn - Identificador del pedido (MagicNumber). El valor por defecto -1 significa cualquier 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);
}
 

Ejemplos de cómo utilizar la función NumberOfOrders().

  1. Obtener el importe total de todos los pedidos
    NumberOfOrders();
  2. Obtiene el número de órdenes realizadas para el símbolo actual
    NumberOfOrders(NULL);
  3. Obtener el número de órdenes BuyLimit para cualquier símbolo
    NumberOfOrders("", OP_BUYLIMIT);
  4. Obtener el número de órdenes SellStop con el número mágico 123456 para EURUSD
    NumberOfOrders("EURUSD", OP_SELLSTOP, 123456);
  5. Obtener el número de órdenes con número mágico 2345 para el símbolo actual
    NumberOfOrders(NULL, -1, 2345);

Adjuntamos de nuevo un script de trabajo con los ejemplos anteriores.

Archivos adjuntos:
 
KimIV:

La función NumberOfOrders().

Esta función devuelve el número de pedidos y anula completamente ExistOrders(). Para sustituir la función ExistOrders() por la función NumberOfOrders(), es necesario y suficiente comprobar el valor de retorno para que sea mayor que cero. Puede limitar la lista de órdenes a comprobar mediante los parámetros de la función:

  • sy - Nombre del instrumento. Si se da este parámetro, la función sólo comprobará las órdenes del instrumento especificado. NULL significa instrumento actual, y "" (por defecto) significa cualquier instrumento.
  • op - Tipo de orden pendiente. Valores válidos: OP_BUYLIMIT, OP_BUYSTOP, OP_SELLLIMIT, OP_SELLSTOP o -1. El valor por defecto de -1 significa cualquier orden.
  • mn - Identificador del pedido (MagicNumber). El valor por defecto de -1 significa cualquier MagicNumber.

Estoy un poco confundido. Por alguna razón, veo alguna contradicción. Aquí mismo:

"...es necesario y suficiente comprobar que el valor de retorno es mayor que cero".

Si marca "esto y sólo esto", la función sobre el número de pedidos no tiene sentido.

Por eso empecé a meterme en esto. He insertado esta función en mi Asesor Experto. Pongo m=1 en los parámetros y la condición de abrir posiciones.

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

Pero es como si el Asesor Experto no viera esta limitación. Y abre órdenes en cada señal.

¿Cuál puede ser el problema aquí?

 
rid писал (а):
Estoy un poco confundido. Por alguna razón, veo una cierta contradicción. Aquí mismo:
"...es necesario y suficiente comprobar que el valor de retorno es mayor que cero".
Si marcamos "esto y sólo esto", entonces la función para el número de pedidos no tiene sentido.

hmm... Parece que no está prestando atención a la cantidad de información devuelta por cada una de las funciones ExistOrders() y NumberOfOrders(). La función ExistOrders( ) sólo devuelve información sobre la existencia de órdenes, y la función NumberOfOrders() devuelve información sobre el número de órdenes. La información sobre el número de pedidos contiene la información sobre la existencia de pedidos. Cuando necesitamos responder a la pregunta de si un pedido existe o no, la información sobre el número de pedidos es redundante. Por eso he dicho que si queremos sustituir la función ExistOrders() por la función NumberOfOrders(), debemos comprobar el valor devuelto por la función NumberOfOrders() para asegurarnos de que es mayor que cero. Al fin y al cabo, está claro que si este valor es igual a cero, no hay pedidos, y si este valor es mayor que cero, los pedidos están presentes. La función ExistOrders( ) se puede utilizar cuando no necesitamos información sobre la cantidad de pedidos, mientras que la función NumberOfOrders() se puede utilizar cuando no necesitamos información sobre la cantidad de pedidos y cuando sí la necesitamos. En este sentido, la función NumberOfOrders( ) sustituye completamente a la función ExistOrders().

rid:

Esto es lo que he empezado a investigar. He insertado esta función en mi Asesor Experto. Pongo m=1 en los parámetros y la condición de abrir posiciones.

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

Pero es como si el Asesor Experto no viera esta limitación. Y abre órdenes en cada señal.

¿Cuál puede ser el problema aquí?

Así que... y aquí parece que se confunden las posiciones con las garantías. Para mí son cosas diferentes. ¿Qué son las posiciones? Son operaciones OP_BUY y OP_SELL, mientras que las órdenes a mi entender son operaciones OP_BUYLIMIT, OP_BUYSTOP, OP_SELLLIMIT y OP_SELLSTOP. Abro posiciones y pongo órdenes. ¿Y qué abres? La función NumberOfOrders() está diseñada para trabajar con pedidos.
 

Gracias. Lo tengo todo. Tanto en la primera pregunta como en la segunda.

En otras palabras, la función "ampliada" NumberOfOrders() ya incluye esencialmente la función IndexByTicket()

Sí, en efecto. ¡Abrí OP_BUY y OP_SELL !

Todavía tengo que darle un ejemplo de su siguiente función que funciona exactamente con las posiciones. (no con órdenes).

Recuerdo que ya lo has publicado en algún lugar de este foro. No lo encuentro.

 
rid писал (а):
Queda por dar un ejemplo de su siguiente función que funciona exactamente con las posiciones. (no con pedidos)

He terminado con las funciones para los pedidos. A continuación, las funciones de los puestos. Hay unos 30.


rid escribió (a):
Recuerdo que en algún lugar del foro ya lo publicaste. No lo encuentro.

busque en

 

Querido Igor, ¡te pido ayuda! Necesito añadir un EA para que pueda tomar posiciones en varios instrumentos. Hay 2 EAs trabajando, MACD estándar y Ema, cada uno con 6 posiciones, pero sólo una posición se abre... He leído sus comentarios al respecto, pero como no soy bueno con el idioma, no puedo entender dónde añadir qué... Si no te importa, por favor, ayuda... copiado asesor de Ema... Gracias.



//+------------------------------------------------------------------+
//| 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("No tienes dinero. Fondos libres = ", AccountFreeMargin());
return(0);
}
if(((EMA>EMA1) && (EMA2<EMA3)) || ((EMA<EMA1) && (EMA2>EMA3))
{
chk=1;
Print("¡La posición es posible!");
}
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("Orden de venta abierta : ",OrderOpenPrice());
chk=0;
}
else
{
Print("Error al abrir la orden de VENTA : ",GetLastError());
return(0);
}
}
if(EMA2-EMA3>2*Punto && Ask<=(hi-MoveBack*Punto))
{
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("Orden de compra abierta : ",OrderOpenPrice());
chk=0;
}
else
{
Print("Error de apertura de la orden BUY : ",GetLastError());
return(0);
}
}
}
return(0);
}
for(cnt=0;cnt<total;cnt++)
{
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(OrderType()<=OP_SELL && // ¿es una posición abierta? OP_BUY o OP_SELL
OrderSymbol()==Symbol()) // ¿coincidencia de herramientas?
{
if(OrderType()==OP_BUY) // posición larga abierta
{
// ¿comprobamos si ya es hora de cerrar?
if(Bid>=(OrderOpenPrice()+Pip*Point))
{
chk=0;
OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // cerrar posición
return(0); // salir
}
if(Bid<=(OrderOpenPrice()-SL*Point))
{
chk=0;
OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // cerrar la posición
return(0); // salir
}
}
else // en caso contrario se trata de una posición corta
{
// ¿comprobar si ya es hora de cerrar?
if(Ask<=(OrderOpenPrice()-Pip*Point))
{
chk=0;
OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // cerrar posición
return(0); // salir
}
if(Ask>=(OrderOpenPrice()+SL*Point))
{
chk=0;
OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // cerrar posición
return(0); // salir
}
}
}
}
return(0);
}
//+------------------------------------------------------------------+
 

Igor, te hice una pregunta en la 'Biblioteca de funciones para trabajar con archivos INI', pero no hubo respuesta :(

Razón de la queja: