Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 31

 
Artyom Trishkin:

Hai almeno guardato il codice che ti sto mostrando? L'hai eseguito?

Non stavo chiedendo come riempire il buffer dell'indicatore, ma perché vengono restituiti valori vuoti se prendo valori da AO non dalla barra corrente.
Ho capito - non c'è storia, sta caricando, e mentre sta caricando AO da un timeframe non nativo restituisce un errore "no data".

Voglio controllare se la storia è completamente caricata per non entrare nel ciclo dell'indicatore.

Se usate CopyBuffer nell'indicatore per ricevere dati da un altro indicatore, è necessario:

  1. Girate il vostro buffer degli indicatori in modo che la barra più a destra del grafico corrisponda all'indice "0" nel buffer degli indicatori.
  2. Così, "la barra corrente" nell'indicatore "iMTF_AO.mq5" sarà la barra più a destra del grafico, e corrisponderà all'indice "0" nel buffer dell'indicatore "Buffer[]".
  3. E per ottenere la "barra corrente" dall'indicatore (CopyBuffer(handle,0,shift,1,array)) il parametro "shift" deve essere uguale a "0".

Se non volete girare il buffer dell'indicatore, fate così (temporaneamente): AO(0) - per capire come ottenere i valori di un altro indicatore da un INDICATORE. Potreste ottenere un errore una o due volte, ma questo è fino a quando la serie temporale è costruita, e poi i valori saranno stabili.

 
Artyom Trishkin:
Hai visto la mia risposta? L'avete provato?
 
Vladimir Karputov:

Se usate CopyBuffer in un indicatore per recuperare dati da un altro indicatore, dovreste:

  1. Invertite il vostro buffer degli indicatori in modo che la barra più a destra del grafico corrisponda all'indice "0" nel buffer degli indicatori.
  2. Così, "la barra corrente" nell'indicatore "iMTF_AO.mq5" sarà la barra più a destra del grafico, e corrisponderà all'indice "0" nel buffer dell'indicatore "Buffer[]".
  3. E per ottenere la "barra corrente" dall'indicatore (CopyBuffer(handle,0,shift,1,array)) il parametro "shift" deve essere uguale a "0".

Se non volete girare il buffer dell'indicatore, fate così (temporaneamente): AO(0) - per capire come ottenere i valori di un altro indicatore da un INDICATORE. Potreste ottenere un errore una o due volte - ma questo fino a quando una serie temporale è costruita, e poi i valori saranno stabili.

1. Il mio codice ce l'ha e c'era subito:

   ArraySetAsSeries(Buffer,true);
   int bars=Bars(NULL,PeriodForWork);
   datetime time_limit=GetTime(Symbol(),PeriodForWork,bars-1);
   int limit_p=GetBarShift(Symbol(),Period(),time_limit);
   if(rates_total<1) return(0);

2. lo fa.

3. shift è uguale all'indice del ciclo i. E il ciclo va dall'inizio dei dati storici (rates_total-1) alla fine (ai dati attuali)

Un'altra domanda è che dovremmo calcolare questi dati rispetto a un TF non nativo per non ottenere dati da barre mancanti. E dobbiamo determinare prima del ciclo che la storia della TF desiderata sia completamente sincronizzata.

 
Artyom Trishkin:

1. Il mio codice ce l'ha e l'ha avuto subito:

2. è il modo in cui è.

3. shift è uguale all'indice del ciclo i. E il ciclo va dall'inizio dei dati storici (rates_total-1) alla fine (ai dati attuali)

Un altro problema è che abbiamo bisogno di calcolare questi dati in relazione a un timeframe non nativo in modo da non ottenere dati da barre mancanti. E dovremmo determinare prima del ciclo che la storia del lasso di tempo necessario sia completamente sincronizzata.


Rielaborare il ciclo per chiamare AO: put da "0" a qualche valore (ora da qualche valore a zero). Quando gli errori si verificano - confrontare in una volta: il numero di barre calcolate ("limit_p") e tassi_totale dell'indicatore corrente.


Aggiunto: e qui queste linee cancellano tutti gli sforzi di "limite" calcolato (se ci riferiamo al tempo non nativo):

   if(limit>1) 
     {
      limit=rates_total-1;
     }

Approssimativamente, all'inizio (quando si accedeva a un timeframe non nativo) "limit" era uguale a 156, ma sotto BACK! e "limit" diventava "154566666666".



 
Alexey Kozitsyn:
Avete provato la sincronizzazione? Inoltre, gli sviluppatori consigliano di mantenere aggiornati i dati del TF/simbolo richiesto attraverso il timer.

No, non l'ho ancora provato. Ho visto circa il supporto della rilevanza dei dati, mi ricordo - lo so.

Ma inizialmente è necessario uscire da OnCalculate() se i dati della data specificata e della data corrente non sono ancora sincronizzati.

Capisco quello attuale:

if(rates_total<1) return(0);

A proposito di dato - è necessario controllare il suo Bars() - il loro numero invece di rates_total.

Ma non conosco il limite - può essere controllato sul timeframe corrente (come esempio da un altro indicatore):

   int limit=rates_total-prev_calculated;
   if(limit>1) {
      limit=rates_total-4;
      ArrayInitialize(BufferAoDN,EMPTY_VALUE);
      ArrayInitialize(BufferAoUP,EMPTY_VALUE);
      ArrayInitialize(BufferMacdDN,EMPTY_VALUE);
      ArrayInitialize(BufferMacdUP,EMPTY_VALUE);
      ArrayInitialize(BufferRsiDN,EMPTY_VALUE);
      ArrayInitialize(BufferRsiUP,EMPTY_VALUE);
      ArrayInitialize(BufferStochDN,EMPTY_VALUE);
      ArrayInitialize(BufferStochUP,EMPTY_VALUE);
      }

Ma in questo indicatore di prova otteniamo i dati sia dal timeframe corrente (mostra i calcoli in OnCalculate()) che da quello specificato - per ottenere i dati AO dal timeframe specificato.

Non riesco ancora a ricordare come calcolare tutti i dati necessari per il numero di barre - perché il ciclo dovrebbe iniziare con la barra corrispondente al tempo della barra della storia con il primo dato esistente o quello corrente o quello specificato - dove è minore - da quella barra si inizia il ciclo. Il limite dovrebbe anche essere calcolato correttamente per rilevare l'apparizione di una nuova barra, che dovrebbe portare al ricalcolo completo o al ricalcolo della sola barra corrente (a seconda di ciò che è successo - l'apertura di una nuova barra o il caricamento della storia).

Forse, sto cercando di pensare tutto in una volta, e penso un sacco di cose inutili...

 
Vladimir Karputov:


Rielaborare la chiamata del ciclo a AO: mettere da "0" e a qualche valore (ora da qualche valore a zero). Quando si verificano errori - confronta subito: il numero di barre calcolate ("limit_p") e tassi_totale dell'indicatore corrente.


Aggiunto: e queste linee cancellano tutti gli sforzi del "limite" calcolato (se si riferiscono a un lasso di tempo non nativo):

grossomodo, all'inizio (quando ci si rivolge a un tempo non nativo) "limite" è diventato 156, e sotto BATCH! e "limite" è già diventato "154566666666"

Sì, l'ho scritto subito che ho fatto un casino qui in fretta e furia.

Ma non cambierò il ciclo - c'è un indicatore abbastanza complesso in cui tutto è costruito sul calcolo della storia dall'inizio alla fine - è più facile ricalcolare i limiti e ottenere i dati che riscrivere l'intero indicatore - tutta la sua logica.

 
Artyom Trishkin:

No, non l'ho ancora provato. Ho visto circa il supporto della rilevanza dei dati, mi ricordo - lo so.

Ma inizialmente è necessario uscire da OnCalculate() se i dati sul timeframe specificato e quello corrente non sono ancora sincronizzati.

Quello attuale è chiaro:

Non è proprio così. Quando si carica inizialmente il terminale con l'indicatore si può ottenere non quello che ci si aspetta. Durante il giorno e se ci sono interruzioni di connessione - ci possono essere anche errori.

A proposito dell'uscita da OnCalculate(): la prima richiesta Bars() dovrebbe essere fatta in fase di inizializzazione, poi in OnCalculate() controllare la sincronizzazione dei TF attuali e necessari. Se non c'è sincronizzazione, lasciare.

 
Artyom Trishkin:

Sì, è quello che ho detto subito, che ho sbagliato in fretta.

Non voglio cambiare il ciclo, c'è un indicatore abbastanza complicato, che si basa sul calcolo della storia dall'inizio alla fine - è più facile ricalcolare i limiti e ricevere i dati correttamente, che riscrivere l'intero indicatore - tutta la sua logica.

Artem, cosa intendi per "dall'inizio alla fine"?

Pensi che capovolgere tutti gli array sia la soluzione migliore?

Perché

ArraySetAsSeries(Buffer,true);

se stai copiando solo un valore?

Quando si copiano TF diversi da quello corrente, è meglio passare il tempo della barra necessaria alla funzione CopyBuffer(). Altrimenti, non copierà la barra che volete.

 
Alexey Viktorov:

1. artyom, cosa intende per "dall'inizio alla fine"?

2. Pensi che capovolgere tutti gli array sia la soluzione migliore?

3. Perché

4. Se si copia solo 1 valore?

Quando si copia il tempo della barra richiesta alla funzione CopyBuffer() che non è il timeframe corrente, è meglio passarlo. Altrimenti, non copierà la barra che volete.

1. L'inizio dei dati storici è la prima barra della storia con il tempo di apertura più breve, la fine dei dati storici è la barra attuale.

2. Sto copiando da un 4 a un 5.

Bene, perché in Buffer[] i dati sono scritti in loop da rates_total-1 a 0. Se non lo facciamo come una serie temporale, sarà mostrato avanti e indietro sul grafico.

4. Voglio copiare un valore in un momento del tempo, che corrisponde ai dati della barra i di un dato timeframe.

Guarda come è laconico e facile ottenere i dati non del timeframe corrente in mql4. Mi chiedo come sia possibile ricevere i dati dell'indicatore in mql5 e non funziona - c'è sempre l'errore 4806 se passo il timeframe che non corrisponde al timeframe del grafico in cui lavora l'indicatore nella funzione di ricezione dei dati AO.

//+------------------------------------------------------------------+
double GetDataAO(string sy, int timeframe, int shift) {
   double array[1];
   ZeroMemory(array);
#ifdef __MQL4__
   array[0]=iAO(sy,timeframe,shift);
#else 
   ResetLastError();
   if(CopyBuffer(handle_ao,0,shift,1,array)==WRONG_VALUE) {
      Print(__FUNCTION__," > Error: ",GetLastError());
      return(0);
      }
#endif 
   return(array[0]);
}
//+------------------------------------------------------------------+

Allo stesso tempo, in OnInit() viene creato il manico dell'indicatore che corrisponde al prezzo corrente dal quale vogliamo ricevere i dati:

handle_ao=iAO(symbol,periodForWork);

Cioè, in qualsiasi momento, non importa come passiamo la f, la maniglia viene creata con la f necessaria (selezionata nelle impostazioni). Ma i dati AO possono essere ottenuti solo se la funzione selezionata nelle impostazioni e la funzione corrente coincidono. Se non coincidono, allora zero viene sempre restituito dalla funzione.

La domanda è: PERCHE'?

 
Artyom Trishkin:

1. L'inizio dei dati storici è la prima barra della storia con il tempo di apertura più breve, la fine dei dati storici è la barra attuale.

2. Sto riscrivendo da quattro a cinque.

Bene, perché in Buffer[] i dati sono scritti in loop da rates_total-1 a 0. Se non lo facciamo come una serie temporale, sarà mostrato avanti e indietro sul grafico.

4. Copio un valore alla volta che corrisponde ai dati della barra i del timeframe dato.

Guarda come è laconico e facile ricevere dati non del timeframe corrente in mql4. Mi chiedo come sia possibile ricevere i dati dell'indicatore in mql5 e non funziona - c'è sempre l'errore 4806 se passo il timeframe che non corrisponde al timeframe del grafico in cui lavora l'indicatore nella funzione di ricezione dei dati AO.

Allo stesso tempo, in OnInit() viene creato il manico dell'indicatore che corrisponde al prezzo corrente dal quale vogliamo ricevere i dati:

Cioè, in qualsiasi momento, non importa come passiamo la f, la maniglia viene creata con la f necessaria (selezionata nelle impostazioni). Ma i dati AO possono essere ottenuti solo se la funzione selezionata nelle impostazioni e la funzione corrente coincidono. Se non corrispondono, viene sempre restituito zero dalla funzione.

La domanda: PERCHE'?

1. Solo un chiarimento. Ora capisco che stiamo parlando della stessa cosa.

Lo capisco, ma non sono d'accordo che sia necessario invertire gli array. È necessario avere un indicatore per due terminali? È quasi come fare 2in1 una falce e un'ascia.

3. come ho capito Buffer[] è usato dal ricevitore nella funzione CopyBuffer() per ottenere solo 1 valore di indicatore.

4. Non avete prestato attenzione alla cosa più importante. L'inizio della copia del valore dell'indicatore non dovrebbe essere determinato dall'indice della barra, ma dal tempo della barra i-esima.

int  CopyBuffer( 
   int       indicator_handle,     // handle индикатора 
   int       buffer_num,           // номер буфера индикатора 
   datetime  start_time,           // с какой даты 
   int       count,                // сколько копируем 
   double    buffer[]              // массив, куда будут скопированы данные 
   );
Motivazione: