Il Semplice Esempio di Creazione di un Indicatore Utilizzando la Logica Fuzzy
Introduzione
L'uso di vari metodi per l'analisi dei mercati finanziari è diventato sempre più popolare tra i trader negli ultimi anni. Vorrei dare il mio contributo e mostrare come creare un buon indicatore scrivendo un paio di dozzine di righe di codice. Inoltre, ti rivelerò brevemente le basi della logica fuzzy.
Chiunque sia interessato a questo tema e voglia approfondirlo può leggere i seguenti lavori:
2. Bocharnikov V. "Fuzzy Technology: Contesto Matematico. Pratica di Simulazione in Economia" (in russo).
3. S.N. Sivanandam, S. Sumathi, S.N. Deepa. Introduzione alla Logica Fuzzy utilizzando MATLAB.
4. C. Kahraman. Fuzzy Engineering Economics with Applications (studi su Fuzziness e Soft Computing ).
1. Nozioni di Base sulla Logica Fuzzy
Come spiegare alle nostre macchine di calcolo il significato di espressioni così semplici come "...un po' di più...", "...troppo veloce...", "...quasi niente..."? Infatti, è abbastanza possibile utilizzando gli elementi di teoria degli insiemi fuzzy, ovvero le cosiddette "funzioni di appartenenza". Ecco un esempio da А. Il libro di Leonenkov:
Descriviamo la funzione di appartenenza alla frase "caffè caldo": la temperatura del caffè va considerata compresa tra 0 e 100 gradi centigradi per il semplice motivo che a temperature inferiori a 0 gradi si trasformerà in ghiaccio, mentre a temperature superiori 100 gradi evaporerà. È abbastanza ovvio che una tazzina con una temperatura di 20 gradi non può essere definita calda, ovvero la funzione di appartenenza alla categoria "caldo" è pari a 0, mentre una tazzina con una temperatura di 70 gradi appartiene sicuramente alla categoria "caldo" e, quindi, il valore della funzione è uguale a 1 in questo caso.
Per quanto riguarda i valori di temperatura che si trovano tra questi due valori estremi, la situazione non è così definita. Alcune persone potrebbero considerare "calda" una tazza di caffè con una temperatura di 55 gradi, mentre altre potrebbero considerarla "non così calda". Questa è la "sfocatura".
Tuttavia, possiamo immaginare l'aspetto approssimativo della funzione di appartenenza: è "monotonicamente crescente":
La figura sopra mostra la funzione di appartenenza "lineare a tratti".
Pertanto, la funzione può essere definita dalla seguente espressione analitica:
Useremo tali funzioni per il nostro indicatore.
2. Funzione di Appartenenza
In un modo o nell'altro, il compito di qualsiasi indicatore tecnico è la determinazione dello stato attuale del mercato (piatto, trend rialzista, trend ribassista), nonché la generazione di segnali di ingresso/uscita dal mercato. Come si può fare questo con l'aiuto delle funzioni di appartenenza? Abbastanza facile.
Prima di tutto, dobbiamo definire le condizioni al contorno. Poniamo le seguenti condizioni al contorno: per «100% trend rialzista» sarà l'incrocio di EMA con periodo 2, basato sul prezzo tipico (H+L+C)/3 con bordo superiore Envelopes con parametri 8, 0.08, SMA , Close, mentre per «100% trend ribassista» si tratterà dell'attraversamento della stessa EMA con bordo inferiore Envelopes. Tutto ciò che si trova tra queste condizioni sarà considerato piatto. Aggiungiamo un altro envelope con i parametri 32, 0.15, SMA, Close.
Di conseguenza, otterremo due funzioni di appartenenza identiche. Il segnale di acquisto verrà attivato quando entrambe le funzioni sono pari a 1, mentre il segnale di vendita verrà attivato quando entrambe le funzioni sono rispettivamente pari a -1. Poiché è conveniente costruire grafici con l'intervallo da -1 a 1, il grafico risultante sarà ottenuto come media aritmetica di due funzioni F(x)= (f1(x)+f2(x))/2.
Ecco come appare sul grafico:
In questo caso la funzione di appartenenza avrà la seguente rappresentazione grafica:
Analiticamente può essere scritto come segue:
,
dove a e b sono rispettivamente le linee di envelope superiore e inferiore, mentre х è un valore di EMA(2).
Con la funzione definita, possiamo ora passare alla scrittura del codice dell'indicatore.
3. Creazione del Codice del Programma
Prima di tutto, dovremmo definire cosa e come disegneremo.
I risultati dei calcoli della funzione di appartenenza verranno visualizzati come una linea rispettivamente rossa e blu.
La media aritmetica verrà visualizzata come un istogramma dalla linea dello zero e dipinta in uno dei cinque colori a seconda del valore della funzione risultante:
Per questo verrà utilizzato lo stile di disegno DRAW_COLOR_HISTOGRAM.
Tracciamo rettangoli blu e rossi come segnali di acquisto/uscita sulle barre dell'istogramma, i cui valori sono uguali a 1 o -1.
Ora è il momento di eseguire MetaEditor e iniziare. Nuovo->Indicatore personalizzato->Avanti... Compila il campo "Parametri":
Crea i buffer:
Dopo aver fatto clic sul pulsante "Fine", riceviamo un codice sorgente e iniziamo a migliorarlo.
Prima di tutto, definiamo il numero di buffer. Sette di questi sono già stati creati dalla procedura guidata (5 per i dati, 2 per il colore). Noi abbiamo bisogno di altri 5.
#property indicator_minimum -1.4 // Setting fractional values #property indicator_maximum 1.4 // Expert Advisors wizard ignores fractional parts for some reason #property indicator_buffers 12 // Changing the value from 7 to 12 (5 more buffers have been added)Modifichiamo i parametri di input:
input string txt1="----------"; input int Period_Fast=8; input ENUM_MA_METHOD Method_Fast = MODE_SMA; /*Smoothing method*/ //moving average smoothing method input ENUM_APPLIED_PRICE Price_Fast = PRICE_CLOSE; input double Dev_Fast=0.08; input string txt2="----------"; input int Period_Slow=32; input ENUM_MA_METHOD Method_Slow = MODE_SMA; input ENUM_APPLIED_PRICE Price_Slow = PRICE_CLOSE; input double Dev_Slow=0.15; /*Deviation parameter*/ input string txt3="----------"; input int Period_Signal=2; input ENUM_MA_METHOD Method_Signal = MODE_EMA; input ENUM_APPLIED_PRICE Price_Signal = PRICE_TYPICAL; input string txt4="----------";
I commenti che seguono la variabile dichiarata sono molto utili. Il testo dei commenti viene inserito nella finestra dei parametri dell'indicatore.
Molto utile anche la possibilità di creare liste:
Riservando le variabili per gli handle e i buffer dell'indicatore:
int Envelopes_Fast; // Fast envelope int Envelopes_Slow; // Slow envelope int MA_Signal; // Signal line double Env_Fast_Up[]; // Fast envelope upper border double Env_Fast_Dn[]; // Fast envelope lower border double Env_Slow_Up[]; // Slow envelope upper border double Env_Slow_Dn[]; // Slow envelope lower border double Mov_Sign[]; // Signal line
Adesso passa alla funzione OnInit().
Aggiungiamo un po' di bellezza: specifica il nome dell'indicatore e rimuovi gli zeri decimali extra:
IndicatorSetInteger(INDICATOR_DIGITS,1); // setting display accuracy, we do not need some outstanding accuracy values string name; // indicator name StringConcatenate(name, "FLE ( ", Period_Fast, " , ", Dev_Fast, " | ", Period_Slow, " , ", Dev_Slow, " | ", Period_Signal, " )"); IndicatorSetString(INDICATOR_SHORTNAME,name);
e aggiungi i buffer mancanti:
SetIndexBuffer(7,Env_Fast_Up,INDICATOR_CALCULATIONS); SetIndexBuffer(8,Env_Fast_Dn,INDICATOR_CALCULATIONS); SetIndexBuffer(9,Env_Slow_Up,INDICATOR_CALCULATIONS); SetIndexBuffer(10,Env_Slow_Dn,INDICATOR_CALCULATIONS); SetIndexBuffer(11,Mov_Sign,INDICATOR_CALCULATIONS);
Il parametro INDICATOR_CALCULATIONS significa che i dati del buffer sono necessari solo per i calcoli intermedi. Non verrà visualizzato sul grafico.
Nota come vengono dichiarati gli indicatori con buffer di colore:
SetIndexBuffer(4,SignalBuffer1,INDICATOR_DATA); // All indicator buffers at first SetIndexBuffer(5,SignalBuffer2,INDICATOR_DATA); // as this is Color Histogram2, then it has 2 data buffers SetIndexBuffer(6,SignalColors,INDICATOR_COLOR_INDEX);// the color buffer comes next.
Riempire gli handle:
Envelopes_Fast = iEnvelopes(NULL,0,Period_Fast,0,Method_Fast,Price_Fast,Dev_Fast); Envelopes_Slow = iEnvelopes(NULL,0,Period_Slow,0,Method_Slow,Price_Slow,Dev_Slow); MA_Signal = iMA(NULL,0,Period_Signal,0,Method_Signal,Price_Signal);
Tutti i lavori con la funzione OnInit() sono finiti.
Ora creiamo la funzione che calcolerà il valore della funzione di appartenenza:
double Fuzzy(double x,double a, double c) { double F; if (a<x) F=1; // 100% uptrend else if (x<=a && x>=c) F=(1-2*(a-x)/(a-c));// Flat else if (x<c) F=-1; // 100% downtrend return (F); }
I preparativi sono finiti. Le variabili e i buffer vengono dichiarati, gli handle vengono assegnati.
Ora è il momento di procedere con la funzione di base OnCalculate().
Prima di tutto, scriviamo i valori degli indicatori necessari nei buffer intermedi. Usa la funzione CopyBuffer():
CopyBuffer(Envelopes_Fast, // Indicator handle UPPER_LINE, // Indicator buffer 0, // The point to start 0 - from the very beginning rates_total, // How many to be copied - All Env_Fast_Up); // The buffer the values are written in // - the rest are done in a similar way CopyBuffer(Envelopes_Fast,LOWER_LINE,0,rates_total,Env_Fast_Dn); CopyBuffer(Envelopes_Slow,UPPER_LINE,0,rates_total,Env_Slow_Up); CopyBuffer(Envelopes_Slow,LOWER_LINE,0,rates_total,Env_Slow_Dn); CopyBuffer(MA_Signal,0,0,rates_total,Mov_Sign);
Qui dobbiamo aggiungere il codice per l'ottimizzazione dei calcoli (viene eseguito il ricalcolo solo dell'ultima barra):
// declaring start variable for storing the index of the bar, recalculation of the indicator buffers will be // carried out from. int start; if (prev_calculated==0) // in case no bars have been calculated { start = Period_Slow; // not all indicators have been calculated up to this value, therefore, there is no point in executing the code } else start=prev_calculated-1; for (int i=start;i<rates_total;i++) { // All remaining code will be written here }
Non è rimasto molto del codice.
Impostando i parametri x, a, b, eseguendo il calcolo del valore della funzione di appartenenza e scrivendolo nell'apposito buffer:double x = Mov_Sign[i]; // Signal // Setting the first membership function parameters: double a1 = Env_Fast_Up[i]; // Upper border double b1 = Env_Fast_Dn[i]; // setting the first membership function value and writing it to the buffer Rule1Buffer[i] = Fuzzy(x,a1,b1); // Setting the second membership function parameters: double a2 = Env_Slow_Up[i]; // Upper border double b2 = Env_Slow_Dn[i]; // setting the second membership function value and writing it to the buffer Rule2Buffer[i] = Fuzzy(x,a2,b2);
Vengono costruite due linee di indicatori.
Ora calcoliamo il valore risultante.
ResultBuffer[i] = (Rule1Buffer[i]+Rule2Buffer[i])/2;
Quindi dovremmo dipingere le barre dell'istogramma con colori appropriati: poiché abbiamo cinque colori, allora ResultColors[i] può avere qualsiasi valore da 0 a 4.
In genere, il numero di colori possibili è 64. Pertanto, è una grande opportunità per applicare le proprie capacità creative.
for (int ColorIndex=0;ColorIndex<=4;ColorIndex++) { if (MathAbs(ResultBuffer[i])>0.2*ColorIndex && MathAbs(ResultBuffer[i])<=0.2*(ColorIndex+1)) { ResultColors[i] = ColorIndex; break; } }
Quindi dovremmo disegnare i rettangoli di segnale. Useremo lo stile di disegno DRAW_COLOR_HISTOGRAM2.
Ha due buffer di dati con una barra dell'istogramma e un buffer di colore che viene costruito tra di loro.
I valori dei buffer di dati saranno sempre gli stessi: 1.1 e 1.3 per un segnale di acquisto, rispettivamente -1.1 e -1.3 per un segnale di vendita.
EMPTY_VALUE significherà l'assenza del segnale.
if (ResultBuffer[i]==1) { SignalBuffer1[i]=1.1; SignalBuffer2[i]=1.3; SignalColors[i]=1; } else if (ResultBuffer[i]==-1) { SignalBuffer1[i]=-1.1; SignalBuffer2[i]=-1.3; SignalColors[i]=0; } else { SignalBuffer1[i]=EMPTY_VALUE; SignalBuffer2[i]=EMPTY_VALUE; SignalColors[i]=EMPTY_VALUE; }
Fai clic su "Compila" e voilà!
Conclusione
Cos'altro si può aggiungere? In questo articolo ho toccato l'approccio più elementare alla logica fuzzy.
C'è abbastanza spazio qui per vari esperimenti. Ad esempio, possiamo utilizzare la seguente funzione:
Penso che non sarà difficile per te scrivere l'espressione analitica per esso e trovare le condizioni adatte.
Buona fortuna!
Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/178
- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso