Qualcuno sa come sviluppare un indicatore multicurrency? - pagina 3

 
4x_Gypsy:

Il grande indizio era "Ma non so come farlo".

Dalla mancanza di qualsiasi tipo di risposta da parte dell'OP è un'indicazione che c'è qualcosa di sbagliato. La mia "ipotesi" è che l'OP sia stato frustrato dalla mancanza di comprensione e abbia abbandonato il thread. C'è stato un periodo anni fa in cui ho fatto la stessa cosa. Ho imparato di più da diversi siti/forum che da questo perché nessuno si prendeva il tempo di rendersi conto di quanto fossi nuovo e postava continuamente esempi e discussioni completamente al di sopra della mia comprensione di allora.

Dal tuo punto di vista potresti avere ragione, d'altra parte ho visto molte domande che semplicemente trovavano risposta se solo si rischiava di dare un'occhiata veloce alle documentazioni e ti sentivi davvero un pazzo a rispondere a quelle domande ancora e ancora.

Inoltre c'è Google e un'opzione di ricerca qui. Se non so come fare qualcosa questo è il mio prossimo passo cercando di risolvere il problema da solo.

Nel caso dell'argomento di questo thread non so come codificare un sistema multi-valuta avrei risposto a Google o avrei cercato qui del codice già esistente.

 
gooly:

Dal tuo punto di vista potresti avere ragione, d'altra parte ho visto molte domande che hanno semplicemente trovato risposta se solo si rischia di dare un'occhiata veloce alle documentazioni e ti senti davvero un pazzo a rispondere a queste domande ancora e ancora.

Inoltre c'è Google e un'opzione di ricerca qui. Se non so come fare qualcosa questo è il mio prossimo passo cercando di risolvere il problema da solo.

Nel caso dell'argomento di questo thread non so come codificare un sistema multi-valuta avrei risposto a google o cercare qui il codice già esistente.

Grazie per il feedback, e sono contento che sia stato positivo. lol

Mi dispiace a chiunque sia interessato per il modo in cui mi sono presentato in questa situazione. Sono veramente un tipo di persona che ama la pace e non fa drammi, che di solito ignora la maggior parte delle cose con cui non sono d'accordo.

 

Ciao ragazzi,

Scusate per il lungo periodo senza attività qui. Ero in viaggio per lavoro e anche occupato con alcuni progetti e ho dovuto lasciare il progetto da parte per un po '.

Dopo aver letto gli aggiornamenti post, ho alcuni punti da chiarire:

  1. Non voglio che qualcuno codifichi tutte le cose per me, basta che mi mostri la giusta direzione e io faccio il resto. Bene... ora testerò la soluzione WHRoeder e farò le mie cose e più tardi posterò il risultato qui. Suggerimento WHRoeder:https://www.mql5.com/en/forum/158938
  2. Prima di creare questo argomento ho fatto una ricerca per post simili, ma non ho trovato... poi l'ho creato
  3. Mi dispiace che ci voglia molto tempo per rispondere, ma era davvero troppo lavoro, ma ora sto continuando a lavorare con l'indicatore
  4. Scusa per il mio povero inglese, la mia lingua è il portoghese e quando scrivo in inglese, devo usare il traduttore di google e non è perfetto.


 
Ecco il mio test.

Basta permettere agli utenti di informare i loro beni, e dopo, mostrare i valori alti/bassi di tutte le coppie.

Se una delle coppie selezionate è la stessa della finestra attiva, i suoi tassi sono aggiornati bene. Ma altre coppie mostrano solo i tassi quando l'indicatore è stato aggiunto... e non si aggiornano più...

Come potete vedere nell'immagine qui sotto, l'indicatore è stato aggiunto nella finestra GBPUSD... e i tassi GBPUSD sono stati aggiornati bene tick per tick. Ma EURUSD non si aggiorna e rimane con lo stesso valore.

Tariffe copiate


Di seguito, il codice dell'indicatore:

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

 
Ho provato a usare RefreshRates() ma sempre con lo stesso risultato... solo la coppia nella stessa finestra funziona, le altre coppie non si aggiornano.
 
wemersonrv:
Ho provato a usare RefreshRates() ma sempre con lo stesso risultato... solo la coppia alla stessa finestra funziona, le altre coppie non si aggiornano.

RefreshRates() non ha niente a che fare con i dati MqlRates. Il codice di esempio di WHRoeder è valido solo per le build Pre-600. Per l'ultima build, è necessario controllare i vari punti menzionati nel mio post, come testare i codici di ritorno di ArrayCopyRates(), così come i codici di errore, la dimensione dell'Array Rates e come precauzione aggiuntiva indicata da WHRoeder, la validità dell'attributo time.

PS! Se hai difficoltà con l'inglese, mandami un PM. Sono portoghese (Portogallo)

 

Ciao ragazzi.

Testando, ho incluso una "ricopiatura" dei tassi nella funzione OnCalculate... aggiungendo un ciclo che prima LIBERA l'array di coppie in tutte le iterazioni, poi copia nuovamente i tassi. Sembra funzionare e non restituisce errori.

Non so se questo è il modo migliore per fare ciò di cui ho bisogno, ma apparentemente funziona e senza errori.


   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: Testando, ho incluso una "ricopiatura" dei tassi nella funzione OnCalculate... aggiungendo un ciclo che prima LIBERA l'array di coppie in tutte le iterazioni, poi copia nuovamente i tassi. Sembra funzionare e non restituisce errori.
  1. Come indicato nella documentazione.
    Se i dati (il nome del simbolo e/o il timeframe differiscono da quelli attuali) vengono richiesti da un altro grafico, è possibile che il grafico corrispondente non sia stato aperto nel terminale client e che i dati necessari debbano essere richiesti al server. In questo caso, l'errore ERR_HISTORY_WILL_UPDATED (4066 - i dati storici richiesti sono in aggiornamento) sarà inserito nella variabile last_error, e si dovrà richiedere nuovamente
    E verificato qui
    ArrayCopyRates restituirà un errore se non c'è storia (ERR_NO_HISTORY_DATA = 4073.) Anche le chiamate ripetute falliscono finché il download non è completo. Quando c'è la storia ma non è aggiornata, ArrayCopyRates restituisce valido e imposta anche `_LastError` a ERR_HISTORY_WILL_UPDATED (= 4066.)
  2. Prova il tuo codice di ritorno, dormi e riprova se necessario. Cosa sono i valori di ritorno delle funzioni? Come si usano? - Forum MQL4 ed errori comuni nei programmi MQL4 e come evitarli - Articoli MQL4
 

Un aggiornamento per coloro che seguono questo thread!

Ho aiutato l'OP via PM a sistemare il suo codice perché ha difficoltà con l'inglese ed entrambi parliamo portoghese. Nei nostri test ci siamo imbattuti in un altro "strano" che sta accadendo con la funzione"ArrayCopyRates()". Quando si usa un array MqlRates con"ArrayCopyRates()" in un EA, l'array di dati è virtuale e riporta sempre lo stato attuale delle cose, quindi i dati sono sempre freschi.

Tuttavia, in un indicatore, questo non sembra essere il caso. L'array non è una copia virtuale ma una copia statica impostata nel tempo nel momento in cui è stato chiamato"ArrayCopyRates()". I dati non si aggiornano quando il Symbol è diverso dal simbolo del grafico. Quando è lo stesso simbolo del grafico, allora i dati dell'array sono "live" e si aggiornano come previsto, ma quando è di un altro simbolo, è una copia statica.

Quindi, per poter funzionare in un indicatore, si deve chiamare la funzione "ArrayCopyRates()" ad ogni chiamata all'evento OnCalculate() se sono necessari dati freschi.

 

Ciao a tutti.

  • FMIC, grazie per il tuo sostegno!
  • WHRoeder, grazie anche a te... Sei sempre presente per tutti noi!
  • Grazie a tutti i membri del forum per le vostre considerazioni e anche grazie per tutto il dibattito che si è generato in questo thread. È stato molto interessante!

Questa è (quasi) la stessa cosa che faccio dopo, ma la differenza è che eseguo un ArrayFree prima di ArrayCopyRates... e non faccio le convalide che mi hai aiutato.

Ecco il codice finale che FMIC mi ha aiutato. Ora funziona normalmente in un codice indicatore..:

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

}
Motivazione: