Funciones útiles de KimIV - página 2

 
Qué tal esto:
if (err==146)
{
while (IsTradeContextBusy())
{
if (IsTradeAllowed()) break;
else
Sleep(1000*1,1);
}}
Creo que esta es una solución más rápida. Por favor, comparta sus comentarios.
Gracias.
 
Red.Line писал (а): Gracias por este tema tan útil, aunque yo estoy a punto de quemarme las tartas, pero aun así puede que alguien se haya enfrentado al problema de acumular y tomar muestras de grandes conjuntos de datos en µl. µl y bases de datos? ¿Alguien ha pensado en esa dirección?
Sin duda, una solución sencilla, pero algo. https://forum.mql4.com/ru/9377
 
zhuki:
¿Qué le parece esta variante?
if (err==146)
{
  while (IsTradeContextBusy())
  {
    if (IsTradeAllowed()) break;
    else 
    Sleep(1000*1,1);
  }
}
Esto me parece una solución más rápida.Yo trabajo de esta manera . Comentario.
Gracias.

Me parece bien. Con comprensión. La pausa es menor, funciona más rápido... Pero hay alguna redundancia injustificada en su versión.

La función IsTradeContextBusy devuelve la bandera de ocupación del hilo comercial. No había ninguna función de este tipo antes de la construcción de 195. Así que utilizamos la función IsTradeAllowed que devuelve una señal de que el EA tiene permiso para operar y el flujo de operaciones es libre.

Permitimos que el EA opere marcando la casilla "Permitir que el EA opere" en el cuadro de diálogo de propiedades del EA (tecla F7).

El error 146 (Trade Stream está ocupado) no tiene nada que ver con permitir que el Asesor Experto opere. Por lo tanto, echemos un vistazo a las propiedades de la función IsTradeAllowed en la medida en que se relacionan con el hilo de comercio solamente.

Así, el hilo de comercio está libre y la función IsTradeAllowed devuelve True. El hilo de comercio está ocupado, la función IsTradeAllowed devuelve False. Ahora veamos los valores devueltos por la función IsTradeContextBusy. El hilo comercial está libre, la función IsTradeContextBusy devuelve False. El hilo comercial está ocupado, la función IsTradeContextBusy devuelve True. Podemos ver que para los mismos estados de flujo comercial, los valores de las funciones IsTradeAllowed e IsTradeContextBusy son opuestos. Además, estas funciones se duplican en lugar de complementarse con respecto a los estados de los flujos comerciales. Por lo tanto, se puede excluir uno de ellos. ¿Cuál? La función IsTradeAllowed, como ya he mencionado anteriormente, además de la bandera del estado del flujo de comercio, también devuelve la bandera que permite al EA comerciar, que en esta situación, es decir, cuando se maneja el error 146 (el flujo de comercio está ocupado), no es necesario para nosotros. Por lo tanto, será necesario y suficiente utilizar sólo una función IsTradeContextBusy. Si lleva a cabo las abreviaturas anteriores, su código se reducirá al mío:

if (err==146) while (IsTradeContextBusy()) Sleep(1000*1,1);
con la única diferencia del tamaño de la pausa. Pero esto es una cuestión de gustos, preferencias personales, estilo de negociación, etc. Puedes poner una pausa de 0,1 segundos. No es un gran problema... Sólo prefiero 11 segundos.
 
Pero para mayor precisión sigo prefiriendo hacer una pausa entre todo tipo de operaciones comerciales de 5 segundos hasta la liberación del hilo. Gracias.
 

Se han encontrado dos errores en la función SetOrder:

  1. Uso incorrecto de la función MarketInfo. Debería haberse llamado DESPUÉS de comprobar el parámetro sy, no ANTES.
  2. Corrección de los niveles de ajuste de pedidos que funcionaban incorrectamente. Además, no se corrigieron los niveles de precios de las paradas y las tomas de posesión. Ahora está arreglado y funciona perfectamente. He estado probando esto durante mucho tiempo utilizando el script de prueba que mostraré un poco más adelante.

¡Atención! Se ha corregido el puesto con la función SetOrder para el comercio en línea. La función es un poco más larga. No cabía en todo el puesto, así que hubo que trasladarlo al remolque.

 

En este post he decidido dar los puntos principales explicando cómo funciona la función SetOrder. Yo no trabajo con pedidos, es decir, estoy en territorio ajeno. Tal vez alguien que sepa cómo funciona la función SetOrder sugiera mejoras o encuentre errores.

1. En las primeras líneas de código se declaran las variables locales y se inicializan algunas de ellas. Por ejemplo, en lsComm se escribe el nombre del EA y el nombre del marco temporal devuelto por la función GetNameTF. Por cierto, no voy a detenerme en funciones como GetNameOP, GetNameTF, Message, etc., sólo si alguien tiene preguntas sobre ellas.

string   lsComm=WindowExpertName()+" "+GetNameTF(Period());

2. Comprobación de los parámetros recibidos. Si sy está vacío, se inicializa con el nombre de la herramienta actual. La variable del color del icono en el gráfico se inicializa con el tipo de operación. Si el tiempo de expiración de la orden que no es cero es menor que el tiempo actual, se pone a cero.

if (sy=="" || sy=="0") sy=Symbol();
msl=MarketInfo(sy, MODE_STOPLEVEL);
if (op==OP_BUYLIMIT || op==OP_BUYSTOP) clOpen=clOpenBuy; else clOpen=clOpenSell;
if (ex>0 && ex<TimeCurrent()) ex=0;

3. el cuerpo del ciclo de intentos de negociación, cuyo número está limitado por el valor de la variable global NumberOfTry. A continuación, las operaciones realizadas dentro del bucle principal de la función SetOrder.

for (it=1; it<=NumberOfTry; it++)

4. Si la función SetOrder no se ejecuta en el probador, tenemos la oportunidad de terminar su operación. Aquí se realiza la espera del ciclo de liberación del flujo comercial. Se actualizan las variables del entorno del mercado y se registra la hora actual.

if (!IsTesting() && (!IsExpertEnabled() || IsStopped())) {
  Print("SetOrder(): Остановка работы функции");
  break;
}
while (!IsTradeAllowed()) Sleep(5000);
RefreshRates();
ot=TimeCurrent();

5. Envío de una solicitud a un servidor de comercio. Si la entrada es positiva, la función SetOrder se termina.

ticket=OrderSend(sy, op, ll, pp, Slippage, sl, tp, lsComm, mn, ex, clOpen);
if (ticket>0) {
  if (UseSound) PlaySound(NameFileSound); break;
 

6. Si el ticket es negativo, se realiza el tratamiento de los errores de ejecución.
7. En el caso de los errores 128 (El tiempo de espera ha expirado para la ejecución de la operación), 142 (La orden se ha puesto en cola) y 143 (La orden ha sido aceptada por el distribuidor para su ejecución) hacemos una pausa de 66 segundos. Después de la pausa, mediante la función ExistOrders (que describiremos más adelante) comprobamos si el pedido ya ha sido establecido en el intervalo de tiempo entre la petición del servidor y el momento actual. Si la orden se ha establecido, salga de la función.

err=GetLastError();
if (err==128 || err==142 || err==143) {
  Sleep(1000*66);
  if (ExistOrders(sy, op, mn, ot)) {
    if (UseSound) PlaySound(NameFileSound); break;
  }
  Print("Error(",err,") set order: ",ErrorDescription(err),", try ",it);
  continue;
}

8. El tamaño del artículo y los precios de compra y venta se almacenan en las variables locales.

mp=MarketInfo(sy, MODE_POINT);
pa=MarketInfo(sy, MODE_ASK);
pb=MarketInfo(sy, MODE_BID);

9. En el caso del error 130 (paradas incorrectas) los niveles de precio de la orden, la parada y la retirada se corrigen si es posible.

// Неправильные стопы
if (err==130) {
  switch (op) {
    case OP_BUYLIMIT:
      if (pp>pa-msl*mp) pp=pa-msl*mp;
      if (sl>pp-(msl+1)*mp) sl=pp-(msl+1)*mp;
      if (tp>0 && tp<pp+(msl+1)*mp) tp=pp+(msl+1)*mp;
      break;
    case OP_BUYSTOP:
      if (pp<pa+(msl+1)*mp) pp=pa+(msl+1)*mp;
      if (sl>pp-(msl+1)*mp) sl=pp-(msl+1)*mp;
      if (tp>0 && tp<pp+(msl+1)*mp) tp=pp+(msl+1)*mp;
      break;
    case OP_SELLLIMIT:
      if (pp<pb+msl*mp) pp=pb+msl*mp;
      if (sl>0 && sl<pp+(msl+1)*mp) sl=pp+(msl+1)*mp;
      if (tp>pp-(msl+1)*mp) tp=pp-(msl+1)*mp;
      break;
    case OP_SELLSTOP:
      if (pp>pb-msl*mp) pp=pb-msl*mp;
      if (sl>0 && sl<pp+(msl+1)*mp) sl=pp+(msl+1)*mp;
      if (tp>pp-(msl+1)*mp) tp=pp-(msl+1)*mp;
      break;
  }
  Print("SetOrder(): Скорректированы ценовые уровни");
}

10. La información, que puede ayudar a resolver el problema o encontrar el error más tarde, se muestra en el informe.

Print("Error(",err,") set order: ",ErrorDescription(err),", try ",it);
Print("Ask=",pa,"  Bid=",pb,"  sy=",sy,"  ll=",ll,"  op=",GetNameOP(op),
      "  pp=",pp,"  sl=",sl,"  tp=",tp,"  mn=",mn);
if (pa==0 && pb==0) Message("SetOrder(): Проверьте в обзоре рынка наличие символа "+sy);

Al final procesamos otros errores. Algunos muestran una larga pausa (5 minutos), otros bloquean el Asesor Experto, otros permiten nuevos intentos de operar, etc.

¡Eso es! Fin de la descripción

 

La función ExistOrders().

Devuelve un indicador de la existencia de una orden. Responde a la pregunta de si la orden está fijada o no. Puede utilizar esta función para solicitar cualquier pedido, así como otros más específicos. El filtro de peticiones se configura mediante los parámetros de la función:

  • sy - Impone una restricción al nombre del instrumento. El parámetro por defecto es "" - sin restricción, es decir, cualquier instrumento. Si pasa NULL, la selección de la orden estará limitada por el símbolo actual.
  • op - pone una restricción en el tipo de orden. Ninguna restricción por defecto, es decir, se comprueba cualquier tipo de orden. Los valores válidos del parámetro son -1, OP_BUYLIMIT, OP_BUYSTOP, OP_SELLLIMIT y OP_SELLSTOP.
  • mn - pone un límite al número de identificación ("mágico") de la orden. Sin restricción por defecto, es decir, se comprueba la orden con cualquier número mágico.
  • ot - pone un límite al tiempo de establecimiento de la orden. Se comprueba que la orden se ha establecido con posterioridad al valor de este parámetro. Por defecto no hay límite, es decir, se comprueba una orden con cualquier tiempo de ajuste.
//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 12.03.2008                                                     |
//|  Описание : Возвращает флаг существования ордеров.                         |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    sy - наименование инструмента   (""   - любой символ,                   |
//|                                     NULL - текущий символ)                 |
//|    op - операция                   (-1   - любой ордер)                    |
//|    mn - MagicNumber                (-1   - любой магик)                    |
//|    ot - время открытия             ( 0   - любое время установки)          |
//+----------------------------------------------------------------------------+
bool ExistOrders(string sy="", int op=-1, int mn=-1, datetime ot=0) {
  int i, k=OrdersTotal(), ty;
 
  if (sy=="0") sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      ty=OrderType();
      if (ty>1 && ty<6) {
        if ((OrderSymbol()==sy || sy=="") && (op<0 || ty==op)) {
          if (mn<0 || OrderMagicNumber()==mn) {
            if (ot<=OrderOpenTime()) return(True);
          }
        }
      }
    }
  }
  return(False);
}
 

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

1. Comprobar la disponibilidad de cualquier pedido

ExistOrders();

2. Comprobar la disponibilidad de cualquier orden para cualquier instrumento en el gráfico actual

ExistOrders(NULL);

3. Comprobar la presencia de la orden BuyLimit en cualquier instrumento

ExistOrders("", OP_BUYLIMIT);

4. Comprueba si hay una orden SellStop con el número mágico 123456 en el EURUSD

ExistOrders("EURUSD", OP_SELLSTOP, 123456);

5. Compruebe la disponibilidad de cualquier pedido con un tiempo de preparación de 2 horas o menos

ExistOrders("", -1, -1, TimeCurrent()-2*60*60);
En el trailer hay un script para probar la función ExistOrders. Los primeros 4 ejemplos del script están comentados.

Archivos adjuntos:
 

¡Atención! En el post del 12.03.2008 07:24 he sustituido el archivo adjunto SetOrder.mq4