Anyone know how to develop a multicurrency indicator ? - page 3

 
4x_Gypsy:

Big clue was "But i don't know how to do this.". 

From the lack of any kind of response from the OP is a indication that there is something wrong. My "guess" is the OP got frustrated from the lack of understanding and abandoned the thread. There was a time years ago when I did the same thing. I learned more from different sites/forums than this one because nobody was taking the time to realize how new I was and continually posted examples and had discussions completely above my understanding at the time.

Form your viewpoint you might be right, on the other hand I have seen many many questions which simply were answered if the just risk a quick look in the documentations and you really feel being a fool answering those questions again and again.

Further there is google and a search option here. If I don't know how to do something this is my next step trying to solve the problem on my own.

In case of the topic of this thread I don't know how to code a multi-currency system I would have answered google or search here for already existing code.

 
gooly:

Form your viewpoint you might be right, on the other hand I have seen many many questions which simply were answered if the just risk a quick look in the documentations and you really feel being a fool answering those questions again and again.

Further there is google and a search option here. If I don't know how to do something this is my next step trying to solve the problem on my own.

In case of the topic of this thread I don't know how to code a multi-currency system I would have answered google or search here for already existing code.

Thank you for the feedback, and glad it was positive. lol

I am sorry to whomever is concerned for the way I came across in this situation. I am truly a peace loving drama free kind of person who usually ignores most things I don't agree with. 

 

Hi guys,

Sorry for the long period without activity here. I was traveling to work and also busy with some projects and had to leave the project aside for a while .. 

After read the post updates, i have some points to clarify:

  1. I do not want to someone codes all stuffs for me, just need to show me the right direction and i do the rest. Well... i will test the WHRoeder solution now and make my things and later will post the result here. WHRoeder suggestion: https://www.mql5.com/en/forum/158938
  2. Before create this topic i've make a search for similar posts, but not found... then create it
  3. I'm sorry take a long time to respond, but it really was overworked but now I'm continuing to work with the indicator
  4. Sorry for my poor english! my language is portuguese and when i post english, need to use google translator and it's not perfect.

 


 
Here my test.

Just allow users to informe theyr assets, and after, show the all pairs High/Low values.

If, any of selectec pairs is the same as the active Window, his rates are updated fine. But other pairs only shows the rates when indicator was added... and not updates anymore...

As you can see on the image below, the indicator was added in GBPUSD window... and GBPUSD rates was updated fine tick by tick. But EURUSD does not updates and still with same value. 

Rates copied


Below, the indicator code:

//+------------------------------------------------------------------+
//|                                                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);
   
}
//+------------------------------------------------------------------+

 

 
I try to use RefreshRates() but still with the same result... only the pair at the same window works, other pairs not updates.
 
wemersonrv:
I try to use RefreshRates() but still with the same result... only the pair at the same window works, other pairs not updates.

RefreshRates() has nothing to do with the MqlRates data. WHRoeder's example code is only valid fro the Pre-600 builds. For the latest build, you need to check the various points mentioned in my post, such as testing the return codes of ArrayCopyRates(), as well as the Error codes, size of the Rates Array and as a added precaution pointed out by WHRoeder, the validity of the time attribute.

PS! If you are having difficulty with English, send me a PM. I am Portuguese (Portugal)

 

Hi guys.

Testing, i included a "recopy" of rates in OnCalculate function... by adding a loop that first FREE the array of pair in all iterations, then copy the rates again. Apears to be working and do not return error. 

I don't know if this is the best way to do what i need, but apparently it's working and without 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: Testing, i included a "recopy" of rates in OnCalculate function... by adding a loop that first FREE the array of pair in all iterations, then copy the rates again. Apears to be working and do not return error.
  1. As stated in the documentation.
    If data (symbol name and/or timeframe differ from the current ones) are requested from another chart, the situation is possible that the corresponding chart was not opened in the client terminal and the necessary data must be requested from the server. In this case, error ERR_HISTORY_WILL_UPDATED (4066 - the requested history data are under updating) will be placed in the last_error variable, and one will has to re-request
    And verified here
    ArrayCopyRates will return an error if there is no history at all (ERR_NO_HISTORY_DATA = 4073.) Repeated calls also fail until the download is complete. When there is history but not up to date, ArrayCopyRates returns valid AND also sets `_LastError` to ERR_HISTORY_WILL_UPDATED (= 4066.)
  2. Test your return code, sleep and retry if necessary. What are Function return values ? How do I use them ? - MQL4 forum and Common Errors in MQL4 Programs and How to Avoid Them - MQL4 Articles
 

An update to those following this thread!

I have been helping the OP via PM fix his code as he has difficulty with English and we both speak Portuguese. In our testing we came across another "funny" that is happening with the "ArrayCopyRates()" function. When using an MqlRates array with "ArrayCopyRates()" in an EA, the data array is a virtual one that always reports the current status of things, so data is always fresh.

However, in an Indicator, this does not seem to be the case. The array is not a virtual copy but instead a static copy set in time at the moment that the "ArrayCopyRates()" was called. The data does not update when the Symbol is different to the chart symbol. When it is the same symbol as the chart, then the array data is "live" and updates as expected, but when it is of another symbol, it is a static copy.

So, in order for it to work in an Indicator, one must call the"ArrayCopyRates()" function on every call to OnCalculate() event if fresh data is needed.

 

Hi all.

 

  • FMIC, thanks for your support !
  • WHRoeder, thank you too... You are always there for us all !
  • Thanks all forum members for your considerations and even thanks for the whole debate that has been generated in this thread. It was very interesting.!

This is (almost) the same thing i do later, but the difference is i run a ArrayFree before ArrayCopyRates... and i do not make the  validations you helped me.

 

Here the final code that FMIC helped me. It's working normally now in an indicator code..: 

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;
            }
         }
      }
   }

}
Reason: