Qualcuno sa come sviluppare un indicatore multicurrency? - pagina 4

 

Bene ragazzi, la prima parte è fatta (lettura dei tassi di tutte le coppie).

Ora ho bisogno di utilizzare i tassi di tutte le coppie copiate con la funzione ArrayCopyRates per potenziare alcuni indicatori grafici come un RSI... come ho disegnato nell'immagine qui sotto:

Nella mia domanda iniziale intendo sapere come fare questo... e non sulla lettura dei tassi. Non credo che avrò bisogno di copiare i tassi prima di disegnarlo, ma era bene sapere come fare... ora ho solo bisogno di scoprire un modo per dividere l'area dell'indicatore per tracciare tutte le coppie...

 
Capire. Allora tutti gli elementi devono essere disegnati come oggetti.
 

Questo è un indicatore che ho preso da qualche parte, non ho mai provato a decifrarlo. Mostra una rappresentazione di 3 timeframes del grafico corrente. La cosa assurda è che le candele sono disegnate con istogrammi. Abbastanza pulito, ma non è quello che mi interessa in questo momento.

Auguri

File:
 
Ok, grazie. Sono in viaggio al lavoro e al ritorno lo testerò.
 
Fernando Carreiro:

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 funzionare in un indicatore, si deve chiamare la funzione "ArrayCopyRates()" ad ogni chiamata all'evento OnCalculate() se sono necessari dati freschi.

Solo per espandere le tue scoperte Fernando - anche se il simbolo è lo stesso del grafico, se il timeframe è diverso allora l'array è statico.

Quindi per avere una copia virtuale, in un indicatore, deve essere lo stesso simbolo E lo stesso timeframe. Tutto il resto è statico.

 
honest_knave: Solo per espandere le tue scoperte Fernando - anche se il simbolo è lo stesso del simbolo del grafico, se il timeframe è diverso allora l'array è statico. Quindi per avere una copia virtuale, in un indicatore, deve essere lo stesso simbolo E lo stesso timeframe. Tutto il resto è statico.
Grazie per l'aggiornamento!
 
Ciao,

Ho cercato dappertutto una soluzione per questo problema e vorrei ringraziare tutti in questo thread per questa discussione.

Questo è il mio primo messaggio nel forum, quindi per favore fatemi sapere se ho perso qualche protocollo e sarò felice di correggere nel prossimo messaggio.

Sto cercando di sviluppare un indicatore molto semplice, ma la mia logica sembra sensibile al fatto che il grafico sia completamente aggiornato, ecco perché sono così interessato a questa discussione.

Il mio indicatore cerca di disegnare un fib sul range del giorno precedente (dal giorno alto al giorno basso o dal giorno basso al giorno alto) e sul giorno corrente traccia delle linee al massimo, al minimo e al 50% del fib. Se l'indicatore viene utilizzato su un broker GMT (candela giornaliera della domenica) l'utente può impostare un parametro di input per scegliere se il lunedì utilizza solo il range del venerdì o della domenica, oppure venerdì + domenica. Su un broker NY close (GMT+2) questo non fa differenza dato che non ci sono candele domenicali.

Un'altra caratteristica di questo indicatore è quella di permettere all'utente di spostare il fib e le linee (alta, 50% e bassa) del giorno corrente si adatteranno al nuovo range impostato dal fib. Questo permetterà all'utente di aggiustare il range nel caso in cui il range si contragga.

L'indicatore sarà utilizzato principalmente su più grafici a 1h, ma l'utente dovrebbe essere in grado di cambiare timeframe senza perdere le modifiche apportate al fib.

Per disegnare il fib ho bisogno di trovare non solo il massimo e il minimo del giorno precedente, ma anche il tempo di questi punti.

L'idea è semplice ma mi sono trovato di fronte ad alcune sfide.

Supponendo che sia metà settimana per trovare il massimo e il minimo del giorno precedente uso semplicemente:

       Hi = iHigh(NULL, PERIOD_D1, 1);
       Lo = iLow(NULL, PERIOD_D1, 1);

Va bene, ma ora ho bisogno di trovare il giorno precedente a che ora era il massimo e il minimo. Ho deciso di approssimare il tempo alla candela 1h al massimo e al minimo usando iHighest e iLowest. Ed è qui che sono iniziati i problemi.


Per usare iHighest e iLowest ho bisogno di specificare la prima candela 1h e la dimensione del range, quindi nel mio caso sarà la prima candela 1h e l'ultima 1h del giorno precedente. Così ho usato l'apertura della candela giornaliera precedente per l'inizio del giorno precedente e l'apertura della candela giornaliera del giorno corrente -1, per trovare la fine del giorno precedente:

       PrevDayBegin = iBarShift(NULL, PERIOD_H1, iTime(NULL, PERIOD_D1, 1));                
       PrevDayEnd = iBarShift(NULL, PERIOD_H1, iTime(NULL, PERIOD_D1, 0)-1);

E questo funziona benissimo se state usando l'indicatore solo sulle valute (sempre supponendo che sia a metà settimana) perché PrevDayBegin sarà l'indice della candela delle 0:00 1h e PrevDayEnd sarà l'indice della candela delle 23:00 1h. Il problema sta nei futures (indici, oro, greggio, ecc.). L'apertura della candela giornaliera è sempre alle 0:00, ma la prima candela sui futures è all'1am su GMT+2 broker, quindi la linea di codice sopra che calcola PrevDayBegin restituisce la candela 1h delle 23:00 del giorno precedente.

Ho quindi deciso di includere un pezzo di codice per accomodare questa situazione e spostare il PrevDayBegin fino a quando non si trova nello stesso giorno della settimana del PrevDayEnd:

       if(TimeDayOfWeek(iTime(NULL, PERIOD_H1, PrevDayBegin)) != TimeDayOfWeek(iTime(NULL, PERIOD_H1, PrevDayEnd)))
         PrevDayBegin--;  

E tutta questa logica funziona benissimo se avete tutte le candele 1h aggiornate, ma date un'occhiata al log qui sotto che mostra alcune stampe di quello che è successo oggi. Solo per riferimento ho chiuso MT4 il giorno prima in serata e l'ho riaperto oggi in mattinata (intorno alle 7 del mattino UK), quindi mancavano solo poche ore di dati nei grafici.

2017.02.09 06:56:20.613 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: == ALTRO GIORNO DELLA SETTIMANA ==
2017.02.09 06:56:20.613 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayEnd = 1 (2017.02.08 19:00)
2017.02.09 06:56:20.613 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayBegin = 20 (2017.02.08 00:00)

Guardando il log sembra che la candela più aggiornata sul grafico 1h sia stata 2017.02.08 20:00 (indice 0), quindi iBarShift(NULL, PERIOD_H1, iTime(NULL, PERIOD_D1, 0)-1) si avvicina a (indice 1) 2017.02.08 19:00. Di conseguenza tutti i calcoli per l'indicatore si confondono, perché iHighest e iLowest useranno l'intervallo sbagliato.

Sulla base delle discussioni precedenti ho provato e usato alcune delle soluzioni suggerite per aspettare che tutte le candele siano caricate prima di fare i calcoli, ma a quanto pare non funziona ancora.

Per esempio, in OnInit() ho incluso le seguenti linee di codice per attivare l'aggiornamento dei grafici su 1h, Daily e il timeframe corrente (solo nel caso in cui la piattaforma fosse chiusa quando il grafico era aperto su un timeframe diverso):

   // Triggers history update
   MqlRates mqlrates_array_d1[];
   MqlRates mqlrates_array_h1[];
   MqlRates mqlrates_array[];
  
   ArrayCopyRates(mqlrates_array_d1,NULL,PERIOD_D1);
   ArrayCopyRates(mqlrates_array_h1,NULL,PERIOD_H1);
   ArrayCopyRates(mqlrates_array,NULL,0);  
Un'altra cosa che ho notato è che sembra che MT4 aggiorni la candela più recente Time[0] sul timeframe che è aperto nel grafico prima di caricare tutto lo storico mancante, quindi ho deciso di testare se anche Time[1] fosse un prezzo valido.

Questo codice è stato inserito in OnCalculate() e si è basato sui codici di @whroeder1(qui) e @Fernando Carreiro& @Wemerson Guimaraes(qui):

bool isHistoryLoading;

OnInit();
:
isHistoryLoading = true;
:

OnCalculate( ... )
:
      MqlRates mqlrates_array_d1[];
      MqlRates mqlrates_array_h1[];
      MqlRates mqlrates_array[];
      
      if(isHistoryLoading)
        {      
         ResetLastError();        
        
         if(ArrayCopyRates(mqlrates_array_d1,NULL,PERIOD_D1)>0)
           {
            if(GetLastError() == 0)
              {
               if((iTime(NULL,PERIOD_D1,0) > 0) && (iTime(NULL,PERIOD_D1,1) > 0))
                 {
                  ResetLastError();
  
                  if(ArrayCopyRates(mqlrates_array_h1,NULL,PERIOD_H1)>0)
                    {
                     if(GetLastError() == 0)
                       {
                        if((iTime(NULL,PERIOD_H1,0) > 0) && (iTime(NULL,PERIOD_H1,1) > 0))
                          {
                           ResetLastError();
      
                           if(ArrayCopyRates(mqlrates_array,NULL,0)>0)
                             {
                              if(GetLastError() == 0)
                                {
                                 if((iTime(NULL,0,0) > 0) && (iTime(NULL,0,1) > 0))                            
                                   {
                                    isHistoryLoading = false;
                                
                                    if(DebugLog)
                                      Print("Chart up-to-date!");        
                                    }
                                }
                             }
                          }
                       }
                    }                      
                 }
              }
           }
        }
        
      if(isHistoryLoading)
        {
         if(DebugLog)
           Print("Waiting for chart to update!");
         return(rates_total);
        }    

:

E questo è il log quando la piattaforma è stata aperta e l'indicatore caricato per la prima volta:

2017.02.09 06:56:18.492 Indicatore personalizzato Prev_Day_Range_LRT_50_v0.6 SPX500,H1: caricato con successo
2017.02.09 06:56:18.630 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: inizializzato
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: grafico aggiornato!
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: L'indicatore non esiste! Crearlo.
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: == ALTRO GIORNO DELLA SETTIMANA ==
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayEnd = 20 (2017.02.07 23:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayBegin = 42 (2017.02.07 00:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR CurrDayBegin = (2017.02.08 00:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [0] = (2017.02.08 00:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [1] = (2017.02.07 00:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [2] = (2017.02.06 00:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR Giorno della settimana = 3
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR iHighest (Candela = 28) (Prezzo = 2299.33) (Ora = 2017.02.07 14:00:001)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR iLowest (Candela = 20) (Prezzo = 2287.88) (Tempo = 2017.02.07 23:00:001)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Fib da Time1=2017.02.07 14:00 Price1=2299.33 a Time2=2017.02.07 23:00 Price2=2287.88
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Trendline 'PDRTrend1 131296489639296384' da Time1=2017.02.08 00:00 Price1=2299.33 a Time2=2017.02.09 00:00 Price2=2299.33
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Trendline 'PDRTrend2 131296489639296384' da Time1=2017.02.08 00:00 Price1=2293.605 a Time2=2017.02.09 00:00 Price2=2293.605
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Trendline 'PDRTrend3 131296489639296384' da Time1=2017.02.08 00:00 Price1=2287.88 a Time2=2017.02.09 00:00 Price2=2287.88

Sembra che qualsiasi riferimento alle candele 0 e 1 o la funzione ArrayCopyRates stiano accedendo solo dove le informazioni sono già caricate nei grafici, quindi ArrayCopyRates sembra restituire un numero valido di elementi copiati e iTime(..., 0) e iTime(..., 1) stanno restituendo un prezzo valido per le ultime 2 candele memorizzate quando la piattaforma era chiusa il giorno precedente.

Ciò significa che l'indicatore è stato tracciato come se fosse ieri (PERIOD_D1 [0] = (2017.02.08 00:00)).

L'indicatore è costruito in modo che le linee alta, 50% e bassa siano sempre tracciate nel giorno corrente, anche se l'utente sposta il fib (queste sono le 3 linee di tendenza che mostrano nel log sopra). Quindi ho un pezzo di codice su OnCalculate() che testa se la linea di tendenza media è tracciata nel giorno corrente (l'utente ha un'opzione di input per disabilitare la linea superiore e inferiore, quindi l'unica linea che sarà sempre tracciata è quella media).

OnCalculate( ... )
:

      if(ObjectFind(Trend2Name) != -1)                // Check whether mid range line exists
        {
            
         if((TimeDay(ObjectGetInteger(0,Trend2Name,OBJPROP_TIME,0))==TimeDay(TimeCurrent()))
           && (TimeMonth(ObjectGetInteger(0,Trend2Name,OBJPROP_TIME,0))==TimeMonth(TimeCurrent()))
           && (TimeYear(ObjectGetInteger(0,Trend2Name,OBJPROP_TIME,0))==TimeYear(TimeCurrent()))) // Indicator has already been ploted today        
           {
            return(rates_total);
           }
         else     // Indicator exists but in a past date, so delete it and plot it on current day
           {
            if(DebugLog)
               Print("Indicator in a past date! Deleting it and creating it today!");
              
            if(ObjectFind(FibName) != -1)
              FiboLevelsDelete(0,FibName);              
            // Indicator will be created by the OnChartEvent() when it detects the fib was deleted.
           }
        }
      else        // Indicator doesn't exist, so create it
        {
         if(DebugLog)
            Print("Indicator doesn't exist! Creating it.");
         CreateIndicator();
        }
:

Dopo alcuni tick i dati vengono parzialmente caricati e il pezzo di codice di cui sopra rileverà che le linee sono state tracciate in un giorno precedente, cancellerà il fib e attiverà un ricalcolo degli intervalli e un nuovo disegno degli oggetti (cioè fib, trendline, ecc.).


2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Indicatore in una data passata! Cancellarlo e crearlo oggi!
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDRFibo 131296489639296384 cancellato!
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Eliminazione di PDRRectangle 131296489639296384
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Eliminazione PDRTrend1 131296489639296384
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Cancellazione PDRTrend2 131296489639296384
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Cancellazione PDRTrend3 131296489639296384

E poi torniamo al problema di cui parlavo all'inizio di questo messaggio. Il test che ho implementato sopra non fa attendere all'indicatore il caricamento completo della storia e quindi i range sono calcolati male sulla base di dati parziali.

Questa è una versione più completa del log mostrato all'inizio del messaggio che mostra che non solo PrevDayEnd è stato calcolato male come la 2a candela (indice 1) nel grafico 1h è (2017.02.07 21:00) ma anche CurrDayBegin che dovrebbe essere la 1a candela del giorno corrente nel grafico 1h è stato approssimato da iBarShift a (2017.02.08 06:00).

CurrDayBegin = iTime(NULL, PERIOD_D1, 0);
      
while(TimeDayOfWeek(iTime(NULL, PERIOD_H1, iBarShift(NULL, PERIOD_H1, CurrDayBegin))) != TimeDayOfWeek(TimeCurrent()))

     // If iBarShift can't find the 0am candle and returns the 11pm candle of prev day.

  CurrDayBegin = CurrDayBegin + 3600;        // Move 1h until you find the 1st candle of today.                                        

2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: == ALTRO GIORNO DELLA SETTIMANA ==
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayEnd = 1 (2017.02.07 21:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayBegin = 22 (2017.02.07 00:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR CurrDayBegin = (2017.02.08 06:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [0] = (2017.02.08 00:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [1] = (2017.02.07 00:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [2] = (2017.02.06 00:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR Giorno della settimana = 3
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR iHighest (Candela = 8) (Prezzo = 2299.33) (Ora = 2017.02.07 14:00:001)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR iLowest (Candela = 19) (Prezzo = 2288.57) (Tempo = 2017.02.07 03:00:001)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Fib da Time1=2017.02.07 03:00 Price1=2288.57 a Time2=2017.02.07 14:00 Price2=2299.33
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Trendline 'PDRTrend1 131296489639296384' da Time1=2017.02.08 06:00 Price1=2288.57 a Time2=2017.02.09 06:00 Price2=2288.57
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Trendline 'PDRTrend2 131296489639296384' da Time1=2017.02.08 06:00 Price1=2293.95 a Time2=2017.02.09 06:00 Price2=2293.95
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Trendline 'PDRTrend3 131296489639296384' da Time1=2017.02.08 06:00 Price1=2299.33 a Time2=2017.02.09 06:00 Price2=2299.33

Quindi, in poche parole, c'è un motivo per testare se tutto il materiale è stato caricato su un grafico? O mi manca qualcosa nel mio codice?

Grazie per avermi sopportato in questo messaggio molto lungo.

Fatemi sapere se volete vedere l'intero codice e il log. Preferirei non allegare il codice qui, ma sarei felice di inviarlo privatamente.

Questi sono screenshot dell'indicatore:

(1) Calcolato utilizzando la storia incompleta (si prega di notare che le linee orizzontali non iniziano all'inizio del giorno)

Indicatore calcolato con storia incompleta

(2) Ricalcolato usando la storia completa (linee orizzontali che iniziano all'inizio del giorno)

Indicatore ricalcolato usando la storia completa

Problems with ERR_HISTORY_WILL_UPDATED (4066 ) & weekends
Problems with ERR_HISTORY_WILL_UPDATED (4066 ) & weekends
  • www.mql5.com
Hi i m building a custom indicator and got problems with the 4066 Error...