Servicios , nueva funcionalidad en la arquitectura de MT5, el funeral de MT4 está a la vuelta de la esquina. - página 8

 

de Eng.

datos

alimentar

datafeed -- fuente de datos (aunque la palabra "fuente" no es del todo correcta)


alimentador -- alimentador, alimentador, alimentador

 

О датафидах. Сколько встречал этот термин, сложилось ощущение, что этим словом обозначают источник данных (котировок). Буквально "заполнитель данных". Когда речь идет о собственных инструментах, понимаю так, что мы сможем вычислять котировки, например, никем не котируемого MXNRUB по известным курсам MXNUSD и USDRUB, выгруженным из терминала в .csv формат, и легализовать для терминала новые котировки, указав файл .csv как новый датафид. Возможно, будет реализовано и более изящное решение, без выгрузки в файлы, путем онлайновых операций */ над тиками (MXNRUB =  MXNUSD * USDRUB). И это будет новый датафид.

¿Han importado ya las cotizaciones .csv en ticks para MT5?
 
Andrey Khatimlianskii:

¿No queda ningún enlace a una discusión, informe de errores o algo parecido? ¿O sólo la sensación de que había uno, pero no lo ha comprobado ahora?

Por lo que recuerdo, los ticks recogidos en OnCalculate coincidían con los solicitados a través de CopyTix.

Ahora lo he comprobado a propósito... como sospechaba, me ha salido una mierda, pero no la que esperaba :)

2017.05.22 12:47:10.591 (RTS-6.17,M1)   OnCalculate: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.591 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.599 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.605 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.617 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.637 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.649 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.683 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.765 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.771 (RTS-6.17,M1)   OnCalculate: 2017.05.22 10:47:11.193 ms v = 1, bid = 108320, ask = 108330, last = 108320, flags = 88
2017.05.22 12:47:10.781 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.193 ms v = 1, bid = 108320, ask = 108330, last = 108320, flags = 88
2017.05.22 12:47:10.843 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.244 ms v = 1, bid = 108320, ask = 108330, last = 108320, flags = 0
2017.05.22 12:47:10.843 (RTS-6.17,M1)   OnBookEvent: Время последнего OnCalculate = 2017.05.22 10:47:11.193 ms (88), время последнего OnBookEvent = 2017.05.22 10:47:11.244 ms (0)
2017.05.22 12:47:10.859 (RTS-6.17,M1)   OnCalculate: 2017.05.22 10:47:11.282 ms v = 1, bid = 108320, ask = 108330, last = 108320, flags = 88
2017.05.22 12:47:10.863 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.282 ms v = 1, bid = 108320, ask = 108330, last = 108320, flags = 88

OnBookEvent() captura los ticks con la bandera 0...

 

Y esto es lo que esperaba ver:

2017.05.22 13:24:38.242 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.689 ms v = 2, bid = 108540, ask = 108560, last = 108550, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.242 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.689 ms v = 2, bid = 108540, ask = 108560, last = 108550, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.242 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.689 ms v = 2, bid = 108540, ask = 108560, last = 108550, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.242 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.689 ms v = 2, bid = 108540, ask = 108560, last = 108550, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.242 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 11:24:38.689 ms v = 2, bid = 108540, ask = 108560, last = 108550, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.253 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.253 (RTS-6.17,M1)   OnCalculate: Время последнего STick = 2017.05.22 11:24:38.704 ms (TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME ), время последнего CopyTicks = 2017.05.22 11:24:38.697 ms (TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME )
2017.05.22 13:24:38.253 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.253 (RTS-6.17,M1)   OnCalculate: Время последнего STick = 2017.05.22 11:24:38.704 ms (TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME ), время последнего CopyTicks = 2017.05.22 11:24:38.697 ms (TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME )
2017.05.22 13:24:38.254 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.255 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.255 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.255 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.261 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.261 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.261 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.262 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.262 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.270 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.280 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.730 ms v = 2, bid = 108550, ask = 108560, last = 108560, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.280 (RTS-6.17,M1)   OnCalculate: Время последнего STick = 2017.05.22 11:24:38.730 ms (TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME ), время последнего CopyTicks = 2017.05.22 11:24:38.719 ms (TICK_FLAG_BID )
2017.05.22 13:24:38.282 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 11:24:38.730 ms v = 2, bid = 108550, ask = 108560, last = 108560, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.283 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.730 ms v = 2, bid = 108550, ask = 108560, last = 108560, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
Como puede ver, al solicitar el último tick en cada llamada a OnCalculate() con SymbolInfoTick() - hay un salto en algunos de los ticks que devuelve CopyTicks().
 

Código a comprobar:

#property indicator_chart_window
#property indicator_plots 0
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
MqlTick _tick;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Подписываемся на стакан
   MarketBookAdd(_Symbol);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   ResetLastError();
//--- Проверяем получение параметров тика
   if(!SymbolInfoTick(_Symbol,_tick))
      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": параметры тика не получены!");
   else
      Print(__FUNCTION__,": "+GetMsToStringTime(_tick.time_msc)+" v = ",_tick.volume,", bid = "+DoubleToString(_tick.bid,_Digits)+
            ", ask = "+DoubleToString(_tick.ask,_Digits)+", last = "+DoubleToString(_tick.last,_Digits)+", flags = '"+GetStrFlags(_tick.flags)+"'");
//---
   ResetLastError();
//---
   MqlTick t[1];
   if(CopyTicks(_Symbol,t,COPY_TICKS_ALL,0,1)!=1)
      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": Последний тик не получен!");
   else
     {
      if(t[0].time_msc!=_tick.time_msc)
        {
         Print(__FUNCTION__,": Время последнего STick = "+GetMsToStringTime(_tick.time_msc)+" ("+GetStrFlags(_tick.flags)+")"+
               ", время последнего CopyTicks = "+GetMsToStringTime(t[0].time_msc)+" ("+GetStrFlags(t[0].flags)+")");
        }
     }
//---
   return(rates_total);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnBookEvent(const string &symbol)
  {
//---
   if(symbol!=_Symbol)
      return;
//--- Структура - приемник последнего тика
   MqlTick tick;
//---
   ResetLastError();
//--- Проверяем получение параметров тика
   if(!SymbolInfoTick(_Symbol,tick))
      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": параметры тика не получены!");
   else
      Print(__FUNCTION__,": "+GetMsToStringTime(tick.time_msc)+" v = ",tick.volume,", bid = "+DoubleToString(tick.bid,_Digits)+
            ", ask = "+DoubleToString(tick.ask,_Digits)+", last = "+DoubleToString(tick.last,_Digits)+", flags = '"+GetStrFlags(tick.flags)+"'");
//--- Сравниваем последний тик OnCalculate с последним тиком OnBookEvent
   if(tick.time_msc!=_tick.time_msc)
     {
      Print( __FUNCTION__,": Время последнего OnCalculate = "+GetMsToStringTime( _tick.time_msc )+" ("+GetStrFlags( _tick.flags )+")"+
            ", время последнего OnBookEvent = "+GetMsToStringTime( tick.time_msc )+" ("+GetStrFlags( tick.flags )+")" );
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Отписываемся от стакана
   MarketBookRelease(_Symbol);
  }
//+------------------------------------------------------------------+
//| Получаем строку времени из миллисекунд                                                                      |
//+------------------------------------------------------------------+
string GetMsToStringTime(const ulong ms)
  {
   const int MS_KOEF=1000;               // Коэффициент перевода секунд в миллисекунды
   return( TimeToString( ms/MS_KOEF, TIME_DATE|TIME_SECONDS )+"."+string( ms%MS_KOEF )+" ms" );
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string GetStrFlags(const uint flags)
  {
   string s="";
//---
   if(( flags&TICK_FLAG_ASK)==TICK_FLAG_ASK)
      s+="TICK_FLAG_ASK ";
   if(( flags&TICK_FLAG_BID)==TICK_FLAG_BID)
      s+="TICK_FLAG_BID ";
   if(( flags&TICK_FLAG_BUY)==TICK_FLAG_BUY)
      s+="TICK_FLAG_BUY ";
   if(( flags&TICK_FLAG_SELL)==TICK_FLAG_SELL)
      s+="TICK_FLAG_SELL ";
   if(( flags&TICK_FLAG_LAST)==TICK_FLAG_LAST)
      s+="TICK_FLAG_LAST ";
   if(( flags&TICK_FLAG_VOLUME)==TICK_FLAG_VOLUME)
      s+="TICK_FLAG_VOLUME ";
//---
   return( s );
  }
//+------------------------------------------------------------------+
 
Alexey Kozitsyn:

Código para probar:

Yo dejaría sólo la escritura de ticks al archivo cuando se llama a OnCalculate, para estar seguro (no para probar OnBookEvent y CopyTicks, sinoOnCalculate, como se pretende).

Y luego por script habría generado el mismo archivo, obteniendo los ticks a través de CopyTicks. La diferencia sería más obvia, e indicaría que se han perdido ticks en OnCalculate o que el funcionamiento de CopyTicks es incorrecto.

 
Andrey Khatimlianskii:

Para estar seguro (no para probar OnBookEvent y CopyTicks, sino OnCalculate, como se pretende), yo dejaría sólo los ticks escribiendo en el archivo cuando se llama a OnCalculate.

Y luego por script habría generado el mismo archivo, obteniendo los ticks a través de CopyTicks. La diferencia sería más clara, e indicaría la omisión de ticks en OnCalculate o el trabajo incorrecto de CopyTicks.

Con un cálculo tan sencillo no veo el sentido de molestarse. Hay una comparación específica de dos llamadas: SymbolInfoTick() y CopyTicks(). Y todas las llamadas de SymbolInfoTick() se muestran claramente. Y se puede ver claramente que CopyTicks() devolvió el tick, que no fue recibido en la llamada SymbolInfoTick() de OnCalculate(). Y aquí puede haber dos razones para el error: 1. O bien OnCalculate() se salta un tic, o bien 2. SymbolInfoTick() devuelve algo erróneo en alguna parte.

Sí, esto es parte del registro, que ha estado construyendo como 30 segundos... así que imagina el número de garrapatas que faltan.

 
Alexey Kozitsyn:

Nuestro diálogo con el servicio de atención al cliente:

Salto de tic en OnCalculate
Abierto, Iniciado: 2017.05.22 14:52, #1751442

Mira para no perderte:https://www.mql5.com/ru/forum/190129/page8#comment_5081300 y los 2 siguientes puestos.

CopyTicks del indicador da un tick que el indicador no obtiene en OnCalculate (ni antes ni después).

Equipo de apoyo2017.05.23 09:44
Estado:Sin procesarAbierto
Su solicitud ha sido aceptada para su revisión.
Equipo de apoyo2017.05.23 09:46

OnCalculate es llamado en cada tick.

Las garrapatas se añaden a la base de datos en un hilo separado. Es decir, de forma asíncrona. No es un hecho que con CopyTicks obtendrá el mismo tick que llamó OnCalculate.

Andrey Khatimlianskii 2017.05.23 14:08

No se trata de eso.

Con CopyTicks es posible obtener un tick, que no estaba en OnCalculate (nos enteramos en OnCalculate en un tick, cuyo tiempo es más largo que el perdido).

Echa un vistazo a los registros.

Equipo de apoyo2017.05.23 14:13

Esto es exactamente de lo que estamos hablando.

Llegó un lote de garrapatas. Dos hilos comienzan a procesar este paquete - un hilo en el bucle ejecuta OnCalculate en cada tic del paquete; otro hilo pone todo el paquete en una base de datos de tic. Estos dos hilos no están sincronizados entre sí de ninguna manera y se desconoce qué hilo procesará un paquete de ticks más rápido

Andrey Khatimlianskii 2017.05.23 14:26

Pero cada tick del paquete debe ser procesado por OnCalculate. Y esto no está ocurriendo.

No hay ninguna garrapata con ese tiempo. Hay un tic con menos tiempo, y un tic con más tiempo. Y no hay ninguna llamada OnCalculate en medio.

Equipo de apoyo2017.05.23 14:33

komposter

Pero cada tic en el paquete tiene que ser manejado por OnCalculate. Y esto no está ocurriendo.

No hay ninguna garrapata con ese tiempo. Hay un tic con menos tiempo, y un tic con más tiempo. Y no hay ninguna llamada de OnCalculate entre ellos.

Cada tilde del paquete se procesa en OnCalculate. Allí no hay saltos. El bucle se escribe así.

Para saber qué tick se procesa en OnCalculate, utiliceSymbolInfoTick- aquí todo está claro. El tick se aplica a la información del símbolo y luego se llaman todos los indicadores de este símbolo, todo en un hilo

Andrey Khatimlianskii 2017.05.23 14:36

Por favor, eche un vistazo al registro en el enlace.

SymbolInfoTick de OnCalculate no ve el tick, que se puede obtener de CopyTicks.

Por eso escribí

Equipo de apoyo2017.05.23 14:40

Tenemos que hacer exactamente lo que sugieres enhttps://www.mql5.com/ru/forum/190129/page8#comment_5082755

Yo, para estar seguro (para probar OnCalculate en lugar de OnBookEvent y CopyTicks, como se pretende), dejaría sólo la escritura de ticks al archivo cuando se llama a OnCalculate.

Y luego por script habría generado el mismo archivo, obteniendo los ticks a través de CopyTicks. La diferencia sería mucho más clara, e indicaría la omisión de ticks en OnCalculate o el trabajo incorrecto de CopyTicks.

Y exactamente de esta manera en un momento comprobamos la corrección de CopyTicks. Quedan los scripts de prueba y los indicadores, lo comprobaremos de nuevo.

 

Foro sobre trading, sistemas de trading automatizados y pruebas de estrategias de trading

Bichos, errores, preguntas

fxsaber, 2017.02.07 13:41

SymbolInfoTick en los indicadores funciona de manera muy diferente que en los EAs.

En un indicador siempre devuelve el tick que fue el iniciador de la llamada OnCalculate. Y estos ticks de iniciación en el indicador no deben ser omitidos - esta es la ideología de los desarrolladores. El problema está en la formación de la cola de estas garrapatas.

En el Asesor Experto, el SymbolInfoTick en OnTick no devuelve el tick que inició la llamada de OnTick, sino que hace una petición completa del estado actual.

Foro sobre comercio, sistemas de comercio automatizados y pruebas de estrategias

Características del lenguaje mql5, sutilezas y trucos

fxsaber, 2017.03.29 22:32

El evento de cálculo se genera en CADA tick. Así que hay una cola de ticks para los indicadores. Si llega a un número determinado, aparece un aviso en el registro de que el indicador es demasiado lento.

Las barras en sí mismas son indicadores por naturaleza y son generadas por Calculate-events. Por lo tanto, si TF M1 y es 10:15:00.020 y viene un paquete de 50ms, la primera garrapata en él todavía tiene tiempo 10:14:59.970. Y todos los indicadores son llamados primero en este evento Calculate - primero el indicador de series de tiempo y luego los indicadores personalizados con estas series de tiempo. Es decir, en esta disposición, la barra de las 10:15 aún no se ha formado como la barra de cero. Y la barra de cero es de 10:14.


Entonces, cuando el paquete empiece a desenrollarse a través de los eventos de Cálculo, también aparecerá la barra de las 10:15. Creo que lo he descrito con detalle.

Foro sobre comercio, sistemas de comercio automatizados y pruebas de estrategias

Características del lenguaje mql5, sutilezas y trucos

fxsaber, 2017.03.29 22:41

En consecuencia, es bastante normal que un EA obtenga un tick de una barra que aún no se ha formado. Pero este es un punto tan sutil que requiere un esfuerzo incluso para reproducirlo a propósito. En general, es más teórico que práctico.


Si somos paranoicos con la velocidad, el uso de indicadores (y barras, por supuesto) no es una opción. Todo está en el EA.

 
Andrey Khatimlianskii:

Nuestro diálogo con el Service Desk:

El Service Desk está, por desgracia, en su repertorio. No es necesario que lancen un enlace cuando se trata de una discusión. Pero para dar un ejemplo concreto, en sus dedos. No se trata de eso. A saber, dicen, que SymbolInfoTick() devuelve el tick actual a comprobar, y como OnCalculate() maneja cada tick - resulta que, esa salida debería ser de cada tick. Y CopyTicks() nos dice lo contrario. Bueno... Y dicen que no hay que mirar CopyTicks() :). Sobre dos hilos me explicaron también, cuando estaban arreglando CopyTicks() a finales de año. Sólo que no es el tema aquí (aunque, tal vez en él también, no lo sé).

¿No les preguntó sobre los ticks con bandera 0 cuando se reciben de OnBookEvent()?