¿Alguien sabe cómo desarrollar un indicador multidivisa? - página 3

 
4x_Gypsy:

La gran pista fue "Pero no sé cómo hacer esto".

La falta de cualquier tipo de respuesta del OP es una indicación de que hay algo mal. Mi "suposición" es que el OP se frustró por la falta de comprensión y abandonó el hilo. Hubo un tiempo, hace años, en que hice lo mismo. Aprendí más en diferentes sitios/foros que en este porque nadie se tomaba el tiempo de darse cuenta de lo nuevo que era y continuamente ponía ejemplos y tenía discusiones completamente por encima de mi entendimiento en ese momento.

Desde tu punto de vista puede que tengas razón, por otro lado he visto muchas preguntas que simplemente se respondían si se arriesgaban a echar un vistazo rápido en las documentaciones y realmente te sientes como un tonto respondiendo a esas preguntas una y otra vez.

Además, aquí hay una opción de búsqueda en Google. Si no sé cómo hacer algo, este es mi siguiente paso para intentar resolver el problema por mi cuenta.

En el caso del tema de este hilo no sé cómo codificar un sistema multidivisa habría respondido a google o buscar aquí el código ya existente.

 
gooly:

Desde tu punto de vista, puede que tengas razón, pero por otro lado he visto muchas preguntas que simplemente se respondían si se arriesgaban a echar un vistazo rápido a la documentación y realmente te sientes como un tonto respondiendo a esas preguntas una y otra vez.

Además, aquí hay una opción de búsqueda en Google. Si no sé cómo hacer algo, este es mi siguiente paso para intentar resolver el problema por mi cuenta.

En el caso del tema de este hilo no sé cómo codificar un sistema multidivisa habría respondido a google o buscar aquí el código ya existente.

Gracias por los comentarios y me alegro de que sean positivos. lol

Lo siento a quien corresponda por la forma en que me encontré en esta situación. Realmente soy un tipo de persona amante de la paz y libre de dramas que suele ignorar la mayoría de las cosas con las que no estoy de acuerdo.

 

Hola chicos,

Perdón por el largo periodo sin actividad aquí. Estuve viajando por trabajo y también ocupado con algunos proyectos y tuve que dejar el proyecto de lado por un tiempo...

Después de leer las actualizaciones de correos, tengo algunos puntos que aclarar:

  1. No quiero que alguien codifique todas las cosas por mi, solo necesito que me muestren la dirección correcta y yo hago el resto. Bueno... voy a probar la solución de WHRoeder ahora y hacer mis cosas y más tarde se publicará el resultado aquí. Sugerencia de WHRoeder:https://www.mql5.com/en/forum/158938
  2. Antes de crear este tema he hecho una búsqueda de mensajes similares, pero no se encuentra ... a continuación, crear
  3. Lo siento tomar un largo tiempo para responder, pero realmente estaba sobrecargado de trabajo, pero ahora estoy continuando a trabajar con el indicador
  4. Lo sientopor mi pobre Inglés! mi idioma es portugués y cuando publico Inglés, necesidad de utilizar el traductor de Google y no es perfecto.


 
Aquí mi prueba.

Sólo permite a los usuarios informar de sus activos, y después, mostrar los valores altos/bajos de todos los pares.

Si alguno de los pares seleccionados es el mismo que el de la Ventana activa, sus tasas se actualizan bien. Pero otros pares sólo muestra las tasas cuando el indicador fue añadido... y no se actualiza más...

Como puede ver en la imagen de abajo, el indicador fue agregado en la ventana de GBPUSD... y las tasas de GBPUSD fueron actualizadas bien tick por tick. Pero EURUSD no se actualiza y sigue con el mismo valor.

Tarifas copiadas


Abajo, el código del indicador:

//+------------------------------------------------------------------+
//|                                                MultiCurrency.mq4 |
//|                         Copyright 2016, Wemerson Couto Guimarães |
//|                  https://www.mql5.com/pt/users/wemersonrv/seller |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Wemerson Couto Guimarães"
#property link      "https://www.mql5.com/pt/users/wemersonrv/seller"
#property version   "1.00"
#property strict
#property indicator_separate_window

input string UsePairs="EURUSD,GBPUSD"; // Pares separados por vírgula.

struct pair_struct{
   string symbol;
   MqlRates rates[];
};
pair_struct pairs[];
bool initial;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){
   int i=0, j=0, c;
   string _pairs[], msg="";
   bool pairok=false;
   initial = true;
   ENUM_INIT_RETCODE result = INIT_SUCCEEDED;
   
   StringSplit(UsePairs, StringGetCharacter(",",0), _pairs);
   
   for( i=0; i< ArraySize(_pairs); i++){
      pairok=false;
      
      for( j=0; j<SymbolsTotal(true); j++){
         if( SymbolName(j, true) == _pairs[i]){
            pairok=true;
            break;
         }
      }
      if( pairok ){
         c=ArraySize(pairs);
         ArrayResize(pairs, c+1);
         pairs[c].symbol = _pairs[i];
      }else{
         msg += _pairs[i] + ", ";
      }
   }
   if( msg != "" ){
      string invalids = ArraySize(pairs)== 1?"Invalid Pair: ": "Invalid Pairs: ";
      msg = invalids +  StringSubstr(msg,0,StringLen(msg)-2) + ". Please Check!";
      Alert(msg);
      result = INIT_PARAMETERS_INCORRECT;
   }else{
      for(i=0; i<ArraySize(pairs); i++){
         ArrayCopyRates( pairs[i].rates, pairs[i].symbol, PERIOD_CURRENT );
      }
   }   
   
   return(result);

}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
   
   Comment("");
   
}

//+------------------------------------------------------------------+
//| 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[])
  {

   int i=0;
   if( initial ){
      for( i=0; i<ArraySize(pairs); i++){
         if(pairs[i].rates[0].time == 0) return(rates_total);
      }
      initial=false;
   }
   
   string log="";
   
   for(i=0; i<ArraySize(pairs); i++){
      log += "\nPair: " + pairs[i].symbol + 
             " - High: "+ DoubleToStr(pairs[i].rates[0].high, Digits()) + 
             " - Low: "+ DoubleToStr(pairs[i].rates[0].low, Digits());
   }

   Comment( "\n\n*** Pair Rates***\n" + log );
   return(rates_total);
   
}
//+------------------------------------------------------------------+

 
Intento usar RefreshRates() pero sigo con el mismo resultado... sólo funciona el par en la misma ventana, los otros pares no se actualizan.
 
wemersonrv:
Intento utilizar RefreshRates() pero sigo con el mismo resultado... sólo funciona el par en la misma ventana, los otros pares no se actualizan.

RefreshRates() no tiene nada que ver con los datos de MqlRates. El código de ejemplo de WHRoeder sólo es válido para las builds Pre-600. Para la última versión, es necesario comprobar los diversos puntos mencionados en mi post, como la comprobación de los códigos de retorno de ArrayCopyRates(), así como los códigos de error, el tamaño de la matriz de tarifas y, como precaución adicional señalada por WHRoeder, la validez del atributo de tiempo.

¡PS! Si tienes dificultades con el inglés, envíame un PM. Soy portugués (Portugal)

 

Hola chicos.

Probando, he incluido un "recuento" de tarifas en la función OnCalculate... añadiendo un bucle que primero libera el array de pares en todas las iteraciones, y luego vuelve a copiar las tarifas. Parece que funciona y no devuelve error.

No sé si esta es la mejor manera de hacer lo que necesito, pero aparentemente está funcionando y sin erros.


   int i=0;
   if( initial ){
      for( i=0; i<ArraySize(pairs); i++){
         if(pairs[i].rates[0].time == 0) return(rates_total);
      }
      initial=false;
   }

   // My change to recopy rates every tick by adding a loop at starting of OnCalculate() to do this
   // AS FMIC says, ArrayCopyRates needs the array without content, 
   // then before recopy, free the array.
   for(i=0; i<ArraySize(pairs); i++){
      ArrayFree(pairs[i].rates);
      ArrayCopyRates(pairs[i].rates, pairs[i].symbol, PERIOD_CURRENT);
   }
 
wemersonrv: Probando, he incluido un "recuento" de tarifas en la función OnCalculate... añadiendo un bucle que primero libera el array de pares en todas las iteraciones, y luego copia las tarifas de nuevo. Parece que funciona y no devuelve error.
  1. Como se indica en la documentación.
    Si se solicitan datos (nombre del símbolo y/o marco temporal diferentes a los actuales) de otro gráfico, es posible que el gráfico correspondiente no se haya abierto en el terminal cliente y haya que solicitar los datos necesarios al servidor. En este caso, el error ERR_HISTORY_WILL_UPDATED (4066 - los datos históricos solicitados están en proceso de actualización) se colocará en la variable last_error, y habrá que volver a solicitar
    Y verificado aquí
    ArrayCopyRates devolverá un error si no hay historial en absoluto (ERR_NO_HISTORY_DATA = 4073.) Las llamadas repetidas también fallan hasta que se complete la descarga. Cuando hay historial pero no está actualizado, ArrayCopyRates devuelve válido y también establece `_LastError` a ERR_HISTORY_WILL_UPDATED (= 4066.)
  2. Pruebe su código de retorno, duerma y reintente si es necesario. ¿Qué son los valores de retorno de las funciones? ¿Cómo los utilizo? - Foro MQL4 y Errores comunes en los programas MQL4 y como evitarlos - Artículos MQL4
 

¡Una actualización para aquellos que siguen este hilo!

He estado ayudando al OP vía PM a arreglar su código ya que tiene dificultades con el inglés y ambos hablamos portugués. En nuestras pruebas nos encontramos con otra "gracia" que está sucediendo con la función "ArrayCopyRates()". Cuando se utiliza un array de MqlRates con "ArrayCopyRates()" en un EA, el array de datos es uno virtual que siempre informa del estado actual de las cosas, por lo que los datos son siempre frescos.

Sin embargo, en un Indicador, este no parece ser el caso. El array no es una copia virtual sino una copia estática fijada en el tiempo en el momento en que se llamó a"ArrayCopyRates()". Los datos no se actualizan cuando el Símbolo es diferente al símbolo del gráfico. Cuando es el mismo símbolo del gráfico, entonces los datos del array están "vivos" y se actualizan como se espera, pero cuando es de otro símbolo, es una copia estática.

Por lo tanto, para que funcione en un indicador, hay que llamar a la función "ArrayCopyRates()" en cada llamada al evento OnCalculate() si se necesitan datos frescos.

 

Hola a todos.

  • FMIC, gracias por tu apoyo.
  • WHRoeder, graciastambién... ¡Siempre estás ahí para todos nosotros!
  • Gracias a todos los miembros del foro por sus consideraciones e incluso gracias por todo el debate que se ha generado en este hilo. ¡Ha sido muy interesante!

Esto es (casi) lo mismo que hago después, pero la diferencia es que ejecuto un ArrayFree antes del ArrayCopyRates... y no hago las validaciones que me ayudaste.

Aquí el código final que me ayudó FMIC. Ahora funciona normalmente en un código indicador..:

input string UsePairs="NZDCAD,EURUSD,GBPUSD,USDJPY"; // pairs separated by commas
struct pair_struct{
   string symbol;
   MqlRates rates[];
   bool valid;
};
pair_struct pairs[];
bool initial;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){
   
   int i=0, j=0, c;
   string _pairs[], msg="";
   bool pairok=false;
   initial = true;
   ENUM_INIT_RETCODE result = INIT_SUCCEEDED;
   
   StringSplit(UsePairs, StringGetCharacter(",",0), _pairs);
   
   for( i=0; i< ArraySize(_pairs); i++){
      pairok=false;
      
      for( j=0; j<SymbolsTotal(true); j++){
         if( SymbolName(j, true) == _pairs[i] ){
            pairok=true;
            break;
         }
      }
      if( pairok ){
         c=ArraySize(pairs);
         ArrayResize(pairs, c+1);
         pairs[c].symbol = _pairs[i];
         pairs[c].valid = false;
      }else{
         msg += _pairs[i] + ", ";
      }
   }
   if( msg != "" ){
      string invalids = ArraySize(pairs)== 1?"Invalid Pair: ": "Invalid Pairs: ";
      msg = invalids +  StringSubstr(msg,0,StringLen(msg)-2) + ". Please Check!";
      Alert(msg);
      result = INIT_PARAMETERS_INCORRECT;
   }
   return(result);

}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
   
   Comment("");
   
}

//+------------------------------------------------------------------+
//| 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[])
  {

   InitializeRates();
   
   int i=0;
   string log="";
   for(i=0; i<ArraySize(pairs); i++){
      log += "\nPar: " + pairs[i].symbol;
      if( pairs[i].valid ){
         log += " - Time: "+ TimeToString( pairs[i].rates[0].time ) + 
                " - Open: "+ DoubleToString( pairs[i].rates[0].open, (int)MarketInfo( pairs[i].symbol, MODE_DIGITS ) ) +
                " - Close: "+ DoubleToString( pairs[i].rates[0].close, (int)MarketInfo( pairs[i].symbol, MODE_DIGITS ) ) +
                " - High: "+ DoubleToString( pairs[i].rates[0].high, (int)MarketInfo( pairs[i].symbol, MODE_DIGITS ) ) +
                " - Low: "+ DoubleToString( pairs[i].rates[0].low, (int)MarketInfo( pairs[i].symbol, MODE_DIGITS ) );
      }else{
         log += " - Currently not valid!";
      }
   }

   Comment( "\n\n*** Pair Rates***\n" + log );
   return(rates_total);
   
}
//+------------------------------------------------------------------+

void InitializeRates(){
 
   for( int i=0; i<ArraySize( pairs ); i++ ){
      pairs[i].valid = false;
      ResetLastError();
      if( ArrayCopyRates(pairs[i].rates, pairs[i].symbol, PERIOD_CURRENT) > 0 ){
         if( _LastError == 0 ){
            if( ArraySize(pairs[i].rates) > 0 ){
               if( pairs[i].rates[0].time > 0 )
                  pairs[i].valid = true;
            }
         }
      }
   }

}
Razón de la queja: