Errori, bug, domande - pagina 3027

 
Сергей Таболин:

Gli indicatori sono il mio punto debole ))))

Ma!

O io non capisco proprio niente, o lei si sbaglia di poco.

Per quanto ne so, prev_calculated è un contatore di dati non calcolati. E una volta contati i dati in arrivo, quel contatore viene azzerato... Tipo, questo è tutto, amico, niente più nuovi dati da calcolare.... )))

E per quale motivo l'indicatore dovrebbe ricalcolare completamente in un caso simile - non lo so!

---------------

Ha mentito un po' ))))

Non sono gli indicatori che vengono ricalcolati, ma gli "indici" vengono ricalcolati per farli "sembrare belli" sulla storia ;)

il contatore viene azzerato per ragioni al di fuori del controllo del programmatore, come se l'indicatore fosse stato avviato per la prima volta!

Non vorrei che il mio messaggio si perdesse in mezzo a spiegazioni incomprensibili, ma alla fine ha raggiunto gli sviluppatori.



Dobbiamo notare la connessione tra il valore restituito da OnCalculate() e il secondo parametro di input prev_calculated. Quando si chiama la funzione, il parametro prev_calculated contiene un valore restituito da OnCalculate() nella chiamata precedente. Questo permette algoritmi economici per il calcolo dell 'indicatore personalizzato al fine di evitare calcoli ripetuti per quelle barre che non sono cambiate dalla precedente chiamata di questa funzione.

-Un calcolo che non funziona correttamente rompe l'intero concetto di calcolo economico.
 
Andrey Dik:
Il contatore viene azzerato per ragioni al di fuori del controllo del programmatore, come se l'indicatore funzionasse per la prima volta!

Non volevo che il mio messaggio si perdesse tra gli applausi incomprensibili, ma ha raggiunto gli stimati sviluppatori.

È così per ogni nuovo bar? Vengono rassicurati, vero?

Se non ogni barra, ci sono diverse ragioni per resettare il pre_calc.

 

Forum sul trading, sistemi di trading automatico e test di strategie di trading

Bug, bug, domande

Andrey Dik, 2021.05.27 13:53

cioè, il contatore pre_calcolato viene azzerato non appena appare la nuova barra del timeframe. significa che l'indicatore viene ricalcolato di nuovo come se fosse stato lanciato la prima volta.

Le è familiare una tale costruzione?

if (rates_total == prev_calculated) return rates_total;
  
int startInd = rates_total - prev_calculated;

for (int i = startInd; i >= 0; i--)
{
  //тут считаем индикатор, который обращается к другому индикатору на старшем ТФ
}

il problema non è nella logica EA (ridisegnare, non ridisegnare, sottodisegnare o altro) ma nel fatto che prev_calculated viene resettato mentre nessuno gli ha chiesto di farlo!

Credo che il problema sia:

if (rates_total == prev_calculated) return rates_total;

Non lasciate che l'indicatore chiamato su un altro TF calcoli ogni tick, e poi lo chiamate e c'è una sincronizzazione della storia e del calcolo da zero di quell'indicatore


Ho creato un test. l'indicatore chiamato conta tutto e non si resetta a prev_calculated == 0

Ho disegnato la chiusura nell'indicatore e riavvolgo l'evento con una nuova barra e prev_calculated == 0 :

// tst.mq5

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 start;
   static datetime t = 0;
   if(t != time[rates_total-1])
   {
      t = time[rates_total-1];
      Print(MQLInfoString(MQL_PROGRAM_NAME), " New bar ", t);
   }
   
   if(prev_calculated == 0)
   {
      start = 0;
      ArrayInitialize(Buffer, EMPTY_VALUE);
      Print(MQLInfoString(MQL_PROGRAM_NAME), " prev_calculated == 0");
   }
   else start = prev_calculated - 1;


   for(int i = start; i < rates_total; i++)
   {
      Buffer[i] = close[i];
   }
//--- return value of prev_calculated for next call
   return(rates_total);
}

chiamate questo indicatore (ottenete gli ultimi 2 valori del buffer) e disegnate anche la chiusura sul vostro TF:

input ENUM_TIMEFRAMES TF = PERIOD_M5;
int OnInit()
{
//--- indicator buffers mapping
   SetIndexBuffer(0, Buffer, INDICATOR_DATA);
   ind_handle = iCustom(NULL, TF, "NewFolder\\tst");
//---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| 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 start;
   static datetime t = 0;
   if(t != time[rates_total-1])
   {
      t = time[rates_total-1];
      Print(MQLInfoString(MQL_PROGRAM_NAME), " New bar ", t);
   }

   if(prev_calculated == 0)
   {
      start = 0;
      ArrayInitialize(Buffer, EMPTY_VALUE);
      Print(MQLInfoString(MQL_PROGRAM_NAME), " prev_calculated == 0");
   }
   else start = prev_calculated - 1;


   for(int i = start; i < rates_total; i++)
   {
      Buffer[i] = close[i];
   }
   double buf[];
   if(CopyBuffer(ind_handle, 0, 0, 2, buf) < 0) Print("Error CopyBuffer # ",GetLastError());
//--- return value of prev_calculated for next call
   return(rates_total);
}


ha eseguito l'ultimo indicatore su M1 , log:

2021.05.27 21:48:34.196 tst_tf (EURUSD,M1) tst_tf Nuova barra 2021.05.27 21:48:00

2021.05.27 21:48:34.197 tst_tf (EURUSD,M1) tst_tf prev_calculated == 0

2021.05.27 21:48:34.197 tst_tf (EURUSD,M1) Errore CopyBuffer # 4806

2021.05.27 21:48:34.197 tst (EURUSD,M5) tst Nuova barra 2021.05.27 21:45:00

2021.05.27 21:48:34.197 tst (EURUSD,M5) tst prev_calculated == 0

2021.05.27 21:49:01.636 tst_tf (EURUSD,M1) tst_tf new bar 2021.05.27 21:49:00

2021.05.27 21:50:00.149 tst_tf (EURUSD,M1) tst_tf Nuova barra 2021.05.27 21:50:00

2021.05.27 21:50:00.149 tst_tf (EURUSD,M5) tst Nuova barra 2021.05.27 21:50:00

2021.05.27 21:51:01.789 tst_tf (EURUSD,M1) tst_tf Nuova barra 2021.05.27 21:51:00

2021.05.27 21:52:02.832 tst_tf (EURUSD,M1) tst_tf Nuova barra 2021.05.27 21:52:00

2021.05.27 21:53:00.920 tst_tf (EURUSD,M1) tst_tf Nuova barra 2021.05.27 21:53:00

2021.05.27 21:54:02.778 tst_tf (EURUSD,M1) tst_tf Nuova barra 2021.05.27 21:54:00

2021.05.27 21:55:00.308 tst_tf (EURUSD,M1) tst_tf Nuova barra 2021.05.27 21:55:00

2021.05.27 21:55:00.308 tst_tf (EURUSD,M5) tst Nuova barra 2021.05.27 21:55:00

2021.05.27 21:56:00.118 tst_tf (EURUSD,M1) tst_tf Nuova barra 2021.05.27 21:56:00

2021.05.27 21:57:00.419 tst_tf (EURUSD,M1) tst_tf Nuova barra 2021.05.27 21:57:00

 
Andrey Khatimlianskii:

È così in ogni nuovo bar? Sono sovra-assicurati o qualcosa del genere...

Se non su ogni barra, ci sono diverse ragioni per resettare il pre_calc.

esattamente su ogni nuova barra del TF maggiore.

Per esempio, se l'indicatore lavora su M1 e accede all'indicatore su M5, allora ogni 5 minuti l'indicatore sarà completamente ricalcolato.

 
Igor Makanu:

Credo che il problema sia:

Non lasciate che l'indicatore chiamato su un altro TF calcoli ogni tick e poi lo chiamate e c'è una sincronizzazione storica e un calcolo da zero di quell'indicatore


Ho creato un test. l'indicatore chiamato conta tutto e non si resetta a prev_calculated == 0

Ho disegnato la chiusura nell'indicatore e riavvolgo l'evento con una nuova barra e prev_calculated == 0 :

chiamate questo indicatore (ottenete gli ultimi 2 valori del buffer) e disegnate anche la chiusura sul vostro TF:

Controllo la sincronizzazione dei dati sul TF superiore richiesto (M5) e la prontezza dell'indicatore su di esso, se non è pronto, allora esco.

Di conseguenza, l'indicatore funziona solo una volta all'apertura della barra M1, e non ad ogni tick:


//проверка готовности данных и индикатора на другом TF
if (SeriesInfoInteger (Symbol (), tf, SERIES_SYNCHRONIZED))
{
  if (iBars (Symbol (), tf) != BarsCalculated (handleFr)) return 0;
}
else return 0;

//проверка на наличие нового бара
if (rates_total == prev_calculated) return rates_total;

Spero che gli sviluppatori ascoltino le mie suppliche.

 
Andrey Dik:

Controllo la sincronizzazione dei dati sul TF superiore richiesto (M5) e la prontezza dell'indicatore su di esso, se non è pronto, allora esco.

Di conseguenza, l'indicatore funziona solo una volta all'apertura della barra M1, e non ad ogni tick:


Spero che gli sviluppatori ascoltino le mie suppliche.

questo non dovrebbe funzionare correttamente negli indicatori:

if (SeriesInfoInteger (Symbol (), tf, SERIES_SYNCHRONIZED))

se non mi sbaglio, nell'aiuto c'è un walkthrough dello script per la paginazione dei dati per tutti i TF e ci dovrebbe essere un avviso che i dati storici non possono essere richiesti dall'indicatore a causa del fatto che l'indicatore lavora in modo asincrono

e si raccomanda di usare BarsCalculated() una volta dopo aver legato l'handle


UPD: script per la paginazione della storia e spiegazione del perché non funziona negli indicatori:https://www.mql5.com/ru/docs/series/timeseries_access

 
Andrey Dik:

Controllo la sincronizzazione dei dati sul TF superiore richiesto (M5) e la prontezza dell'indicatore su di esso, se non è pronto, allora esco.

Di conseguenza, l'indicatore funziona solo una volta all'apertura della barra M1, e non ad ogni tick:


Devo davvero usare il mio pre-calcolo personalizzato? Spero che gli sviluppatori ascoltino le mie suppliche.

A cosa serve un tale assegno?

//проверка готовности данных и индикатора на другом TF
if (SeriesInfoInteger (Symbol (), tf, SERIES_SYNCHRONIZED))
{
  if (iBars (Symbol (), tf) != BarsCalculated (handleFr)) return 0;
}
else return 0;

Sarebbe molto più semplice scrivere return 0; senza condizione e basta.

Ad ogni nuova barra, la condizione sarà soddisfatta e tutte le barre saranno ricalcolate indipendentemente dalla sincronizzazione. Avete scritto un codice sconsiderato e fate finta che sia un bug terminale...

 
Un errore di compilazione:
union X1 { //(1) нормально
        char x11[INT_MAX/2+1];
};
union X2 { //(2) Error: 'X2' - struct is too large
        char x21[INT_MAX/2+1];
        char x22[INT_MAX/2+1];
};
Qual è la differenza fondamentale tra (1) e (2)?
 
L'unione con un solo campo è una cosa strana.
 
Alexey Viktorov:

Che senso ha un tale controllo?

Sarebbe più facile scrivere return 0; senza condizione e basta...

La condizione sarà soddisfatta ad ogni nuova barra e tutte le barre saranno ricalcolate indipendentemente dalla sincronizzazione. Avete scritto un codice avventato e l'avete spacciato per un bug terminale...

ripensaci.

Motivazione: