Confronto tra la media mobile (e qualsiasi altro indicatore) e l'errore

 

Ciao a tutti!

Sto scrivendo un EA basato sull'incrocio di SMA (o meglio pensavo di averlo già fatto, perché sembra essere semplice). Ma... Ho affrontato un problema. L'Expert Advisor funziona secondo il seguente principio: quando appare una nuova barra, analizza i valori SMA delle ultime due barre, senza contare l'ultima appena apparsa (la penultima e la precedente). Confronto i valori in modo apparentemente corretto come descritto qui. L'unica eccezione è che iMA è chiamato con l'ultimo parametro (offset in barre) 1 e 2 rispettivamente. Approssimativamente così (se il codice viene riscritto per analogia con il citato):

// берем два соседних значения Быстрой МА
double fast0=iMA(Symbol(), Period(), 10, 0, MODE_SMA, PRICE_CLOSE, 1);
double fast1=iMA(Symbol(), Period(), 10, 0, MODE_SMA, PRICE_CLOSE, 2);
 
// берем два значения Медленной МА
double slow0=iMA(Symbol(), Period(), 20, 0, MODE_SMA, PRICE_CLOSE, 1);
double slow1=iMA(Symbol(), Period(), 20, 0, MODE_SMA, PRICE_CLOSE, 2);
 
// сравниваем значения и определяем направление пересечения
if (fast0>slow0 && fast1<slow1) Print("Пересечение ВВЕРХ");
if (fast0<slow0 && fast1>slow1) Print("Пересечение ВНИЗ");

L'Expert Advisor funziona in una forma primitiva in presenza di un segnale di incrocio sul principio di chiudere il trade precedente - aprirne uno nuovo. Naturalmente, se tutti i crossover vengono rilevati, allora le operazioni saranno sempre eseguite una dopo l'altra (VENDERE - COMPRARE - VENDERE - COMPRARE - ...). Cioè, l'Expert Advisor ha un solo trade aperto in qualsiasi momento (beh, eccetto il momento prima di entrare nel primissimo trade). Quindi ecco l'essenza del problema... Per il timeframe minuto e periodi SMA 5 e 34 per la chiusura nel tester di strategia nella barra del 17.02.2015 alle 01:24 ho catturato una situazione interessante. I moti con queste caratteristiche si incrociano perfettamente direttamente alla chiusura della barra. Ecco l'immagine:

17.02.2015 01:24

Per scopi di debug, ho emesso le informazioni. La corrispondenza nel registro rispetto al codice dato è la seguente:

SMAFastCurrent =fast0

SMASlowCurrent =slow0

SMAFastPrevious =fast1

SMASlowPrevious=slow1 e

SMACurDifference = SMAFastCurrent - SMASlowCurrent

SMAPrevDifference = SMAFastPreviousc - SMASlowPreviousc (cioè la differenza trafast0,slow0 efast1,slow1 rispettivamente).

Quindi, quando queste differenze cambiano di segno, significa che si tratta di un segnale di attraversamento Mooving. Ma in questo particolare esempio il controllo per più o meno non funziona. I valori di queste differenze sono mostrati nel log. Il rettangolo rosso mostra i valori delle differenze sulla barra successiva al problema (a 1:25), arancione - su quella successiva (a 1:26). Ed è chiaro che i valori SMACurDifference sulla barra precedente e SMAPrevDifference sulla barra attuale devono essere uguali (la barra attuale diventa la precedente e la nuova barra prende il suo posto). Quindi, poiché l'incrocio Mooving avviene alla chiusura della barra problematica a 1:24, sulla barra successiva (a 1:25) i valori di SMAFastCurrent e SMASlowCurrent sono uguali (circa). Il debugger li stampa generalmente uguali entro 5 cifre (SMAFastCurrent = 1.13371 SMASlowCurrent = 1.13371 vedi figura). La loro differenza è infinitesimale ma non 0 (SMACurDifference = 2.220446049250313e-016). Nella barra successiva la loro differenza agli stessi valori esatti diventa esattamente zero (confrontare SMACurDifference in rosso e SMAPrevDifference nei rettangoli arancioni). In realtà non è chiaro poi come tagliare questi errori, se anche valori apparentemente identici danno differenze diverse. Da qui due domande:

1. Perché la differenza degli stessi muwings appena contati al momento dell'alternanza di due barre adiacenti, dà un risultato diverso?

2. Pensavo di introdurre un po' di epsilon e confrontarlo con esso, piuttosto che con lo zero. Ma di solito si fa per confrontare un infinitesimo con 0. E il caso in cui devo determinare il cambio di segno di questo infinitesimo?

Naturalmente posso analizzare tre barre adiacenti, ma è ancora teoricamente possibile che ai prezzi delle loro chiusure i movimenti si tocchino ad una distanza infinitesimale. Mi rendo conto che una tale situazione si verifica raramente (soprattutto se prendiamo un arco di tempo più ampio), ma può ancora verificarsi. E dobbiamo prenderlo in qualche modo e rilevare l'incrocio di Mouveins anche in questo caso.

Grazie in anticipo per qualsiasi aiuto!

Навигатор по форуму и ответы на часто задаваемые вопросы. Настоятельно Рекомендуется к Прочтению! - MQL4 форум
  • www.mql5.com
Навигатор по форуму и ответы на часто задаваемые вопросы. Настоятельно Рекомендуется к Прочтению! - MQL4 форум
 

Prova la normalizzazione e il confronto.

Il manuale di riferimento MQL4 (ed è lo stesso per MQL5) dice di aprire su"Real Types (double, float)":

"...Non si possono confrontare due numeri reali per l'uguaglianza l'uno con l'altro. Nella maggior parte dei casi, due numeri apparentemente identici possono rivelarsi disuguali a causa della differenza di 15 cifre decimali. Per confrontare correttamente due numeri reali, bisogna confrontare la differenza normalizzata di questi numeri con un valore zero...."

"... è fortemente sconsigliato confrontare due numeri reali tra loro per l'uguaglianza, poiché tale confronto non è corretto.

..............


Se però è necessario confrontare due numeri reali per l'uguaglianza, lo si può fare in due modi diversi. Il primo modo è quello di confrontare la differenza tra i due numeri con qualche piccolo valore che definisce la precisione del confronto.

.............


Il secondo metodo consiste nel confrontare la differenza normalizzata di due numeri reali con un valore zero. È inutile confrontare la differenza di numeri normalizzati con lo zero, perché qualsiasi operazione matematica con numeri normalizzati dà come risultato un risultato non normalizzato.

...."

 
rosomah:

Prova la normalizzazione e il confronto.

Il manuale di riferimento MQL4 (ed è lo stesso per MQL5) dice di aprire su"Real Types (double, float)":

"...Non si possono confrontare due numeri reali per l'uguaglianza l'uno con l'altro. Nella maggior parte dei casi, due numeri apparentemente identici possono rivelarsi disuguali a causa della differenza di 15 cifre decimali. Per confrontare correttamente due numeri reali, bisogna confrontare la differenza normalizzata di questi numeri con un valore zero...."

"È categoricamente sconsigliato confrontare due numeri reali tra loro per l'uguaglianza, poiché questo confronto non è valido.

..............


Se però è necessario confrontare due numeri reali per l'uguaglianza, lo si può fare in due modi diversi. Il primo modo è quello di confrontare la differenza tra i due numeri con qualche piccolo valore che definisce la precisione del confronto.

.............


Il secondo modo è confrontare la differenza normalizzata di due numeri reali con lo zero. È inutile confrontare la differenza di numeri normalizzati con lo zero, perché qualsiasi operazione matematica con numeri normalizzati dà come risultato un risultato non normalizzato.

...."

So bene che confrontare i numeri reali per l'uguaglianza non è possibile. Non ci sono confronti di uguaglianza nel codice che ho citato. E non ce n'è nemmeno bisogno. Quello che abbiamo qui è una situazione in cui abbiamo bisogno di catturare cambiamenti di segno infinitesimale che potrebbero anche raggiungere lo 0. Paragonare semplicemente tutto a più o uguale a 0 in questo caso è anche pericoloso. E la normalizzazione può essere ancora più pericolosa qui... I valori iniziali di MA sono normalizzati ad un numero sconosciuto (più piccolo è il timeframe, più piccolo è il valore di MA). Se si applica la normalizzazione a una cifra costante dopo la virgola, può risultare che tutti i valori di MA saranno esattamente 0. Ad essere onesti, non capisco bene quale sia la differenza tra due valori di MA...

 

gammaray:

So bene che confrontare i numeri reali sull'uguaglianza non è possibile. Nel codice che ho citato, non ci sono confronti di uguaglianza. E non ce n'è nemmeno bisogno. Quello che abbiamo qui è una situazione in cui abbiamo bisogno di catturare cambiamenti di segno infinitesimale che possono benissimo raggiungere lo 0. Paragonare semplicemente tutto a più o uguale a 0 è pericoloso anche in questo caso. E la normalizzazione può essere ancora più pericolosa qui... I valori iniziali di MA sono normalizzati ad un numero sconosciuto (più piccolo è il timeframe, più piccolo è il valore di MA). Se si applica la normalizzazione a una cifra costante dopo la virgola, può risultare che tutti i valori di MA saranno esattamente 0. Ad essere onesti, non capisco bene quale sia la differenza tra due valori di MA...

Perché la normalizzazione è più pericolosa?

Quindi:

...

Se avete bisogno di confrontare due numeri reali per l'uguaglianza, potete farlo in due modi diversi. Il primo modo è quello di confrontare la differenza tra i due numeri con qualche piccolo valore che stabilisce la precisione del confronto.

...

Il secondo modo consiste nel confrontare la differenza normalizzata di due numeri reali con un valore zero. Confrontare la differenza dei numeri normalizzati con lo zero è inutile, poiché qualsiasi operazione matematica con numeri normalizzati produce un risultato non normalizzato.

Esempio:

bool CompareDoubles(double number1,double number2)
  {
   if(NormalizeDouble(number1-number2,8)==0) return(true);
   else return(false);
  }
void OnStart()
  {
   double d_val=0.3;
   float  f_val=0.3;
   if(CompareDoubles(d_val,f_val)) Print(d_val,"equals",f_val);
   else Print("Different: d_val = ",DoubleToString(d_val,16),
              "  f_val = ",DoubleToString(f_val,16));
// Результат: Different: d_val= 0.3000000000000000   f_val= 0.3000000119209290
  }
  • E la mia personale esperienza pratica (per dirla modestamente, non è piccola in termini di numero di controlli meticolosi del funzionamento del programma, dove ho applicato e ancora applico per confrontare i numeri con il doppio, in termini di correttezza delle condizioni che scattano sulla base di tali confronti),
Questo mi permette di considerare tali confronti non solo non minacciosi:
if(NormalizeDouble(number1-number2,dig)==0)
if(NormalizeDouble(number1-number2,dig)>0)
if(NormalizeDouble(number1-number2,dig)<0)

// dig=Digits();

ma, al contrario, una variazione di uno dei due modi che può, come dice la Documentazione, essere applicata ai confronti di numeri doppi.

Perché:

Non si possono confrontare due numeri reali per l'uguaglianza tra loro. Nella maggior parte dei casi, due numeri apparentemente identici possono rivelarsi disuguali a causa di una differenza di valore di 15 cifre decimali. Per confrontare correttamente due numeri reali, la differenza normalizzata di questi numeri deve essere confrontata con zero.



P./S.: È successo che il primo metodo della Documentazione era meno conveniente per me da usare, anche sulla base di compiti che, di regola, risolvo da solo. Di conseguenza non ho molta esperienza con il primo modo.

Ma quando si usa il secondo modo (cioè confrontando la differenza normalizzata di due numeri reali con il valore zero nell'espressione dell'operatore condizionale), non ci sono problemi.

Ma se ho fatto un confronto di numeri non normalizzati (qui intendo, incluso, quello che ho fatto senza usare il primo metodo), allora sì, c'era, che ho trovato l'innesco errato di condizioni sulla base di confronti di numeri di tipo doppio.

 
gammaray:

Queste sono le frasi della Documentazione:

Il secondo metodo consiste nel confrontare la differenza normalizzata di due numeri reali con zero. Confrontare la differenza di numeri normalizzati con lo zero è inutile, perché qualsiasi operazione matematica con numeri normalizzati dà un risultato non normalizzato.

Per me si percepisce che, in termini semplicistici, nelle operazioni matematiche (e comprese le varie trasformazioni) non si dovrebbe fare qualcosa del genere:

// dig=Digits();

double delta=NormalizeDouble(number1-number2,dig);

if (delta>0)


Cioè, nel post precedente sopra ho dato esempi di confronti della differenza normalizzata di due numeri reali con un valore zero. E in questo post, confrontando la differenza dei numeri normalizzati con lo zero (nella mia comprensione del testo delle frasi sopra dalla Documentazione).

Questo è tutto, in poche parole.

 

gammaray:

...

Cosa farà la normalizzazione della differenza tra i due valori MA, ad essere onesti, non lo capisco bene

P./S.: Su questo punto, potete semplicemente mettere Print() nel vostro codice per un po' per vedere cosa verrà emesso su una grande quantità di dati. In Stampa stampate i valori non normalizzati e normalizzati (fino a qualche decimale, anche più grande di quello del grafico dove farete gli esperimenti) ottenuti da operazioni matematiche. Compresi semplicemente i valori iMA non normalizzati e normalizzati, poiché sono formati sulla base di operazioni matematiche.

Per sicurezza, permettetemi anche di specificare che quando si stampano valori non normalizzati e normalizzati di tipo doppio, questi devono essere convertiti, ovviamente, da valore numerico a valore testuale usando DoubleToString (e in DoubleToString sperimentare il numero di cifre decimali).

 
gammaray:

P./S.: Voglio anche aggiungere che penso che negli esempi di qualsiasi schema scritto per coloro che vogliono imparare la programmazione MQL4, i calcoli matematici di normalizzazione dei valori possono non essere prescritti o/e non direttamente specificati:

  • per la facilità di comprensione degli schemi di formazione di qualsiasi condizione;
  • Non sempre e/o non dappertutto la normalizzazione può essere richiesta (compreso il fatto che si può supporre di applicare per diversi livelli di errori tollerabili da parte dei compiti e, di conseguenza, diversa ulteriore normalizzazione (o mancanza di essa) dei risultati delle operazioni matematiche sul numero di cifre decimali per alcuni compiti individuali);
  • e/o, molto probabilmente, si presume che uno sviluppatore conosca la Documentazione e/o la legga, per chiarire le sue domande.
Qualcosa del genere.
 
È più preciso.
// сравниваем значения и определяем направление пересечения
if (fast0>slow0 && fast1<=slow1) Print("Пересечение ВВЕРХ");
if (fast0<slow0 && fast1>=slow1) Print("Пересечение ВНИЗ");

Cioè, non ha tenuto conto del fatto che i valori di ma potrebbero anche essere uguali.

сравнивать вещественные числа на равенство нельзя

leggermente diverso.
 
Aleksey Lebedev:
Un po' su qualcos'altro.

Dipende da cosa avete in mente e per quali compiti/obiettivi.

Quindi, nello scrivere i post di questo thread, mi sto basando su:

  • Lo screenshot e le domande nel primo post;
  • il secondo post dell'autore del thread (sui pericoli della normalizzazione),

e, di conseguenza, da qui e, per dirla in breve, dal significato dei miei post sopra:

Con l'aiuto della normalizzazione possibilità di impostare/regolare il livello richiesto di accuratezza dei confronti (e/o dei valori di uscita) e/o accettabile per certi compiti e obiettivi errori, che a sua volta permette l'attivazione delle condizioni del programma esattamente dove e come era previsto quando si prescrivono condizioni specifiche nel codice. E il confronto della differenza normalizzata con lo zero, permette di aggiustare/regolare non solo per i confronti che utilizzano l'operazione delle relazioni: "==".


P./S.: Così su ogni caso specificherò ancora una volta, che il confronto dei numeri reali dal primo modo da due elencati qui, dovuto al confronto di una differenza di numeri con qualsiasi piccolo valore, non posso nominare peggiore, che l'applicazione di normalizzazione, quando è necessario per regolare il livello di confronti (incluso, come per me il secondo modo è apparso più conveniente, il primo e non ha considerato per sé più dettagliato per l'applicazione pratica).


 

Questo non ha nulla a che fare con mql in linea di principio. Prendiamo un linguaggio di programmazione astratto. In questo particolare esempio che ho dato, il problema principale è che i valori della differenza di muwings in una stessa barra non sono uguali (2e-16 nel primo calcolo ed esattamente 0 nel secondo). In questo caso, questa intersezione non può essere determinata in alcun modo. Se torniamo a mql, la normalizzazione implica l'arrotondamento del numero (o meglio, semplicemente l'eliminazione di tutti i numeri dopo un certo segno, come nella funzione Sish floor, ma fino a un certo numero decimale). Quindi come faccio a sapere a quale cifra normalizzare? Se viene scelta la cifra sbagliata, tutti i valori possono SEMPRE essere arrotondati esattamente a 0. Quindi la normalizzazione è pericolosa qui e generalmente non risolve il problema.

Per quanto riguarda quello che ha scritto Alexey Lebedev. Sì, stavo pensando in questa direzione. Ma se confrontiamo entrambe le differenze per più o uguale a 0, c'è la probabilità di ottenere un falso segnale (per esempio, la situazione teoricamente possibile quando i movimenti tra barre vicine hanno esattamente gli stessi valori). Allora la loro differenza non cambia il segno (non c'è crossover), ma il segnale per il crossover sarà determinato programmaticamente. Si potrebbe mettere solo un confronto a maggiore o uguale a, come avete suggerito. Ma allora il problema è che nel calcolo in questa situazione prima non sarà uguale a 0 (2e-16), e sulla prossima barra sarà esattamente 0 ma sarà un confronto rigoroso.

È importante capire perché la stessa differenza, se calcolata su barre diverse, non produce lo stesso risultato. Se il risultato fosse lo stesso, il problema si risolverebbe sempre introducendo un confronto non rigoroso

 

gammaray:

Ma poi tutto il problema è che quando si calcola in questa situazione all'inizio non sarà uguale a 0 (2e-16), e sulla prossima barra sarà già esattamente 0, ma ci sarà già un confronto rigoroso.

È importante capire perché la stessa differenza, se calcolata su barre diverse, non produce lo stesso risultato. Se il risultato fosse lo stesso, il problema si risolverebbe sempre introducendo un confronto non rigoroso

Molto probabilmente il calcolo della funzione iMA è ottimizzato. Primo valore = somma(close)/N, secondo = valore precedente di MA+(new close-old close)/N.

Motivazione: