Discusión sobre el artículo "Desarrollo de un sistema de repetición — Simulación de mercado (Parte 10): Sólo datos reales para la repetición"

 

Artículo publicado Desarrollo de un sistema de repetición — Simulación de mercado (Parte 10): Sólo datos reales para la repetición:

Aquí veremos cómo se pueden utilizar datos más fiables (ticks negociados) en el sistema de repetición, sin tener que preocuparnos necesariamente de si están ajustados o no.

En el vídeo que se muestra a continuación se puede ver el resultado del trabajo presentado en este artículo. Aunque algunas cosas no se aprecian visualmente, viendo el vídeo te harás una idea clara del progreso del sistema de repetición/simulador a lo largo de estos artículos. Sólo tienes que ver los vídeos y comparar los cambios desde el principio hasta ahora.


En el próximo artículo, continuaremos con el desarrollo de este sistema, ya que aún quedan por implementar algunas características que son realmente necesarias.


Autor: Daniel Jose

 

Hola Daniel, ¡buenas tardes!

Daniel, tengo la siguiente situación: puedo ejecutar y depurar el servicio. Pero no puedo depurar el indicador, porque cuando ejecuto el servicio ya carga el ejecutable del indicador.

No sé qué estoy haciendo mal, pero por lo que tengo entendido, no se puede ejecutar el código del indicador para depurarlo. ¿Es realmente así? ¿Podríais darme alguna pista?

 
fernandomsoares #:

Hola Daniel, ¡buenas noches!

Daniel, tengo la siguiente situación: puedo ejecutar y depurar el servicio. Pero no puedo depurar el indicador, porque cuando ejecuto el servicio ya carga el ejecutable del indicador.

No sé qué estoy haciendo mal, pero por lo que tengo entendido, no se puede ejecutar el código del indicador para depurarlo. ¿Es realmente así? ¿Podríais darme alguna pista?

NO estás haciendo nada mal.

De hecho, el servicio inicializa el indicador de control en cuanto todo está listo para que el usuario ejecute el servicio.

No entiendo muy bien por qué quieres depurar el indicador. Prácticamente no hay nada ejecutándose en él. Sólo sirve como forma de interacción entre el usuario y el servicio. Sin él, sería muy difícil controlar cuándo queremos reproducir o pausar el servicio. En cualquier caso, no estás haciendo nada malo por intentar estudiar cómo funciona el sistema. Pero como consejo, te aconsejo que leas atentamente los artículos. En ellos se explica detalladamente cómo funciona el sistema, lo que te ahorrará mucho esfuerzo intentando entender cómo se producen las interacciones. 😁👍

 

Hola Daniel, ¡buenos días!

Daniel, he investigado un poco sobre tu código y desarrollo en la plataforma Metatrader 5, para conseguir ejecutar un robot en la repetición / simulador que propones en tus artículos.

El robot se basa en el flujo de datos entrantes, es decir, cuenta los ticks entrantes y hace cálculos para indicar si ejecutar las operaciones.

Ya he tratado este mismo problema en otros post, y pido disculpas de antemano por mi insistencia. El caso es que he estudiado un poco más y he hecho las implementaciones que he creído necesarias para que el robot (EA) pueda recibir los ticks del servicio Replay.

Pero estoy teniendo el siguiente problema: El robot recibe los primeros ticks correctamente, uno a uno, pero después de los primeros 47 ticks recibidos (he puesto un contador), empieza a recibir los ticks muy espaciados, y no entiendo por qué.

Me gustaría mostraros la implementación y pediros ayuda para solucionar el problema, si es posible.

Estos son los cambios que he realizado:

- En la clase C_Replay (líneas en amarillo):

- En el método Event_OnTime:

- He creado una variable de tipo MqlTick para recibir el tick que se enviará al gráfico;

- Después de enviar la actualización de la barra(CustomRatesUpdate), puse un código para enviar el tick al gráfico y esperar a que sea procesado a través de la variable global "def_GlobalVariableTick";

inline int Event_OnTime(void)
                        {
                                bool    bNew;
                                int     mili, iPos;
                                u_Interprocess Info;
                                MqlTick TickToAdd[1];
                                static MqlRates Rate[1];
                                static datetime _dt = 0;
                                
                                if (m_ReplayCount >= m_Ticks.nTicks) return -1;
                                if (bNew = (_dt != m_Ticks.Info[m_ReplayCount].time))
                                {
                                        _dt = m_Ticks.Info[m_ReplayCount].time;
                                        Rate[0].real_volume = 0;
                                        Rate[0].tick_volume = 0;
                                }
                                mili = (int) m_Ticks.Info[m_ReplayCount].time_msc;
                                do
                                {
                                        while (mili == m_Ticks.Info[m_ReplayCount].time_msc)
                                        {
                                                Rate[0].close = m_Ticks.Info[m_ReplayCount].last;
                                                Rate[0].open = (bNew ? Rate[0].close : Rate[0].open);
                                                Rate[0].high = (bNew || (Rate[0].close > Rate[0].high) ? Rate[0].close : Rate[0].high);
                                                Rate[0].low = (bNew || (Rate[0].close < Rate[0].low) ? Rate[0].close : Rate[0].low);
                                                Rate[0].real_volume += (long) m_Ticks.Info[m_ReplayCount].volume_real;
                                                bNew = false;
                                                m_ReplayCount++;
                                        }
                                        mili++;
                                }while (mili == m_Ticks.Info[m_ReplayCount].time_msc);
                                Rate[0].time = m_Ticks.Info[m_ReplayCount].time;
                                CustomRatesUpdate(def_SymbolReplay, Rate, 1);
                                iPos = (int)((m_ReplayCount * def_MaxPosSlider) / m_Ticks.nTicks);
                                GlobalVariableGet(def_GlobalVariableReplay, Info.u_Value.df_Value);
                                if (Info.s_Infos.iPosShift != iPos)
                                {
                                        Info.s_Infos.iPosShift = (ushort) iPos;
                                        GlobalVariableSet(def_GlobalVariableReplay, Info.u_Value.df_Value);
                                }
				// Apenas plotará o tick no grafico se o robo tiver criado a variavel "def_GlobalVariableTick"
                                if (GlobalVariableCheck(def_GlobalVariableTick))
                                {
                                	TickToAdd[0]=m_Ticks.Info[m_ReplayCount];
             				Print("Tick enviado: Time: ", TickToAdd[0].time, " Time_msc: ", TickToAdd[0].time_msc, " Bid: ", TickToAdd[0].bid, " Ask: ", TickToAdd[0].ask, " Last: ", TickToAdd[0].last, " Volume: ", TickToAdd[0].volume_real);
                                	GlobalVariableSet(def_GlobalVariableTick, 1); // Quando o EA receber o tick (OnTick) irá alterar para ZERO
             		  		CustomTicksAdd(def_SymbolReplay, TickToAdd);
                                        short ctd=0;
                                	while (GlobalVariableGet(def_GlobalVariableTick) > 0 && (!_StopFlag) && ctd <= 50) { ctd++; Sleep(50) };
                                }
                                return (int)(m_Ticks.Info[m_ReplayCount].time_msc < mili ? m_Ticks.Info[m_ReplayCount].time_msc + (1000 - mili) : m_Ticks.Info[m_ReplayCount].time_msc - mili);
                        }


- Código para el robot (EA) que recibe el tick para procesarlo:

#define  def_GlobalVariableTick       "ReplayTick"
//+------------------------------------------------------------------+
int OnInit()
{
        GlobalVariableTemp(def_GlobalVariableTick);
        Print("Variavel Criada: ", def_GlobalVariableTick);
                
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason) 
{
   GlobalVariableDel(def_GlobalVariableTick);
}
//+------------------------------------------------------------------+
void OnTick() 
{
   MqlTick mTick;
   static int ctd=0;
   SymbolInfoTick(Symbol(),mTick);
   ctd++;
   Print(Symbol(), "   Tick Recebido ", ctd, ": Time: ", mTick.time, " Time_msc: ", mTick.time_msc, " Bid: ", mTick.bid, " Ask: ", mTick.ask, " Last: ", mTick.last, " Volume: ", mTick.volume);
   // .
   // .
   // Código de procesamiento del tick
   // .
   // .
   // Cambia el valor de la variable global a cero, para recibir el siguiente tick
   GlobalVariableSet(def_GlobalVariableTick, 0);
}
 

continuar ....

De esta forma, cuando necesites parar el robot para depurar, la repetición estará esperando hasta que pases la línea que pone la variable global "def_GlobalVariableTick" a CERO;

¿Lo has entendido?

 
fernandomsoares #:

Continuación de ....

De esta forma, cuando necesitara parar el robot para depurar, la repetición esperaría hasta que pasara la línea que pone la variable global "def_GlobalVariableTick" a CERO;

¿Entendido?

El detalle es que este mecanismo ha sufrido cambios. Echa un vistazo a los artículos más recientes, ya que te muestran cómo los ticks se liberan correctamente. Incluso puede seguirlos en la ventana de observación del mercado, el DOM. De momento tenemos el artículo de la parte 28 ya publicado en portugués. Así que este código que estás intentando retocar y manipular ya está completamente obsoleto. Necesitas seguir los artículos para mantenerte al día con el desarrollo del sistema. No te apegues a ningún código de ninguno de los artículos hasta que la serie esté completamente publicada. Porque sufrirán varios cambios a lo largo del tiempo, para poder cumplir lo prometido: DESARROLLE UN REPLAY / SIMULADOR y esto debería hacer posible usar cualquier cosa que ya tenga, o que esté desarrollando para usar en una cuenta DEMO o REAL. Ya sea en bolsa o en FOREX.

NO intente combinar su Asesor Experto, indicador o script con el REPLAY / SIMULADOR, al menos no todavía. Porque sufrirá cambios importantes en el código ... Sólo tiene que crear su código sin preocuparse por el REPLAY / SIMULADOR ... Llegará un momento en que dejaré de desarrollarlo brevemente para mostrarte cómo crear algunos módulos de apoyo. Cuando eso ocurra, podrás empezar a integrar tu código en él. E incluso entonces muy lentamente, porque cuando los módulos que te muestro cómo desarrollar estén a un cierto nivel de funcionalidad, se integrarán en el REPLAY / SIMULADOR ... aquí es cuando realmente necesitas entender cómo funcionará todo el sistema. De lo contrario, no podrás integrar tu código en el SERVICIO DE REPLAY / SIMULADOR.

Así que tómatelo con calma y estudia los artículos, siempre al día con lo que se está desarrollando.... 😁👍