//-- enumerazioni enum ENUM_INTERSECT_DIRECTION { INTERSECT_DIRECTION_NONE= 0, // nessun incrocio INTERSECT_DIRECTION_UP = 1, // incrocio verso l'alto INTERSECT_DIRECTION_DOWN=-1, // incrocio verso il basso }; //-- parametri di input input uint InpPeriod = 10; // Periodo MA input int InpShift = 0; // Scostamento MA input ENUM_MA_METHOD InpMethod = MODE_SMA; // Metodo MA input ENUM_APPLIED_PRICE InpPrice = PRICE_CLOSE; // Prezzo Applicato alla MA //---variabili globali int ExtMaHandle; int ExtMaPeriod; double ExtData[2]; MqlRates ExtRates[2]; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- il periodo per calcolare la media mobile sarà uguale al valore predefinito (10) se viene specificato zeo nel parametro di input ExtMaPeriod=int(InpPeriod<1 ? 10 : InpPeriod); //-- creare un gestore per l'indicatore Media Mobile con i parametri specificati ExtMaHandle=iMA(Symbol(),PERIOD_CURRENT,ExtMaPeriod,InpShift,InpMethod,InpPrice); ResetLastError(); if(ExtMaHandle==INVALID_HANDLE) { PrintFormat("Failed to create iMA() handle. Error code: %d",GetLastError()); return(INIT_FAILED); } //-- ottenere l'ora dell'ultimo aggiornamento dei prezzi datetime tick_time=TickTime(); //-- ottenere i dati della media mobile e i dati sui prezzi dalle ultime due barre if(GetData(ExtMaHandle,ExtData,ExtRates) && tick_time!=0) { //-- se il prezzo è superiore alla MA if(ExtRates[1].close>ExtData[1]) { //-- creare un messaggio di testo e visualizzare l'Alert string message=StringFormat("Bar time: %s. The price is above the moving average",TimeToString(ExtRates[1].time)); Alert(message+" at "+TimeToString(tick_time,TIME_DATE|TIME_MINUTES|TIME_SECONDS)); /* Risultato: Alert: Bar time: 2024.02.16 18:00. The price is above the moving average at 2024.02.16 18:47:43 */ } else { //-- se il prezzo è inferiore alla MA if(ExtRates[1].close<ExtData[1]) { //-- creare un messaggio di testo e visualizzare l'Alert string message=StringFormat("Bar time: %s. The price is below the moving average.",TimeToString(ExtRates[1].time)); Alert(message+" at "+TimeToString(tick_time,TIME_DATE|TIME_MINUTES|TIME_SECONDS)); /* Risultato: Alert: Bar time: 2024.02.16 19:00. The price is below the moving average at 2024.02.16 19:33:14 */ } else { //-- creare un messaggio di testo e visualizzare l'Alert string message=StringFormat("Bar time: %s. The price and moving average are equal.",TimeToString(ExtRates[1].time)); Alert(message+" at "+TimeToString(tick_time,TIME_DATE|TIME_MINUTES|TIME_SECONDS)); /* Risultato: Alert: Bar time: 2024.02.16 20:00. The price and moving average are equal at 2024.02.16 20:12:22 */ } } } //-- successo return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { ResetLastError(); //-- ottenere i dati della media mobile e i dati sui prezzi dalle ultime due barre if(!GetData(ExtMaHandle,ExtData,ExtRates)) return; //-- ottenere la direzione del prezzo che incrocia la media mobile sulla barra corrente ENUM_INTERSECT_DIRECTION intersect=GetIntersectDirection(ExtData,ExtRates); //--- variabile per salvare il messaggio precedente static string message_prev=""; //-- se il prezzo ha attraversato la media mobile sulla barra corrente verso l'alto if(intersect==INTERSECT_DIRECTION_UP) { //-- ottenere l'ora del tick, in cui si è verificato l'incrocio datetime tick_time=TickTime(); if(tick_time==0) return; //-- creare un messaggio di testo string message=StringFormat("Bar time: %s. The price crossed the MA from bottom to top",TimeToString(ExtRates[1].time)); //-- se il messaggio precedente non è uguale a quello attuale, visualizzare l'Alert con il messaggio e l'ora del tick if(message!=message_prev) { Alert(message+" at "+TimeToString(tick_time,TIME_DATE|TIME_MINUTES|TIME_SECONDS)); message_prev=message; /* Risultato: Alert: Bar time: 2024.02.16 09:00. The price crossed the MA from bottom to top at 2024.02.16 09:20:35 */ } } //-- se il prezzo ha attraversato la media mobile sulla barra corrente verso il basso if(intersect==INTERSECT_DIRECTION_DOWN) { //-- ottenere l'ora del tick, in cui si è verificato l'incrocio datetime tick_time=TickTime(); if(tick_time==0) return; //-- creare un messaggio di testo string message=StringFormat("Bar time: %s. The price crossed the MA from top to bottom",TimeToString(ExtRates[1].time)); //-- se il messaggio precedente non è uguale a quello attuale, visualizzare l'Alert con il messaggio e l'ora del tick if(message!=message_prev) { Alert(message+" at "+TimeToString(tick_time,TIME_DATE|TIME_MINUTES|TIME_SECONDS)); message_prev=message; /* Risultato: Alert: Bar time: 2024.02.16 10:00. The price crossed the MA from top to bottom at 2024.02.16 10:42:15 */ } } } //+------------------------------------------------------------------+ //| Ottenere i dati di prezzo e media mobile in array | //+------------------------------------------------------------------+ bool GetData(int handle,double &ma_data[],MqlRates &price_data[]) { ResetLastError(); //-- ottenere i dati della media mobile dalle ultime due barre if(CopyBuffer(handle,0,0,2,ma_data)!=2) { PrintFormat("CopyBuffer() failed. Error code: %d",GetLastError()); return(false); } //-- ottenere i dati di prezzo per le ultime due barre if(CopyRates(Symbol(),PERIOD_CURRENT,0,2,price_data)!=2) { PrintFormat("CopyRates() failed. Error code: %d",GetLastError()); return(false); } return(true); } //+--------------------------------------------------------------------------------------+ //| Restituire la direzione del prezzo che incrocia la media mobile | //+--------------------------------------------------------------------------------------+ ENUM_INTERSECT_DIRECTION GetIntersectDirection(double &ma_data[],MqlRates &price_data[]) { double ma0=ma_data[1]; double ma1=ma_data[0]; double close0=price_data[1].close; double close1=price_data[0].close; if(close1<=ma1 && close0>ma0) return(INTERSECT_DIRECTION_UP); else { if(close1>=ma1 && close0<ma0) return(INTERSECT_DIRECTION_DOWN); else return(INTERSECT_DIRECTION_NONE); } } //+------------------------------------------------------------------+ //| Restituisce il tempo del tick in secondi | //+------------------------------------------------------------------+ datetime TickTime() { MqlTick tick={}; ResetLastError(); if(!SymbolInfoTick(Symbol(),tick)) { PrintFormat("SymbolInfoTick() failed. Error code: %d",GetLastError()); return(0); } return(tick.time); } |