Ciao trader! Oggi voglio condividere con voi come recuperare gli eventi economici di alta importanza da ForexFactory.com e integrarli nel vostro Expert Advisor (EA) in MetaTrader 4. Mentre sto sviluppando un EA per il petrolio greggio e il Brent, ho avuto la necessità di ottenere data e ora esatte del rapporto sulle scorte di petrolio. Questo rapporto viene generalmente pubblicato il mercoledì alle 10:30 ora di New York, ma in caso di festività, la data di rilascio può cambiare. È fondamentale per il mio EA, quindi ho deciso di utilizzare un servizio online per validare la data di rilascio.
La prima cosa da fare è aggiungere, nella scheda OPZIONI | EXPERT ADVISOR, il sito web da utilizzare per effettuare la WebRequest, che sarà http://www.forexfactory.com/ (vedi immagine 1).

Successivamente, dobbiamo definire una struttura nel nostro codice per memorizzare gli eventi. Questa struttura andrà posizionata nella parte superiore del codice, dichiarando DailyEvents come variabile globale con un numero massimo di eventi memorizzati definito dalla variabile MaxDailyEvents.
// Definisci la struttura degli eventi struct EVENTS { string time; string title; string currency; bool displayed; }; #define MaxDailyEvents 20 // Se pensi di avere più di 20 eventi di alta importanza, aumenta questo numero. EVENTS DailyEvents[MaxDailyEvents];
Ora dobbiamo recuperare il codice HTML da ForexFactory.com e analizzarlo. Non preoccuparti se non sei esperto di HTML, ti guiderò passo dopo passo :)
Iniziamo a costruire l'URL per la WebRequest. Poiché vogliamo solo il calendario per il giorno attuale e non per l'intera settimana, impostiamo il parametro day della richiesta alla data di oggi e inviamo la richiesta.
string url="http://www.forexfactory.com/calendar.php?day="; url += MthName(Month()) + DoubleToStr(Day(), 0) + "." + DoubleToStr(Year(), 0);
Dopo aver inviato la richiesta, verifichiamo il codice di errore (se presente) e convertiamo l'array di caratteri restituito in una stringa. Questo facilita l'analisi del codice HTML.
// Invia la richiesta web ResetLastError(); res = WebRequest("GET", url, cookie, NULL, timeout, post, 0, result, headers); // Controlla eventuali errori if(res == -1) { Print("Errore nella WebRequest. Codice errore = ", GetLastError()); MessageBox("Aggiungi l'indirizzo 'http://forexfactory.com/' nella lista degli URL consentiti nella" + " scheda 'Expert Advisors'", "Errore", MB_ICONINFORMATION); return(false); }
Se non ci sono errori, convertiamo l'array di caratteri result in una stringa per una migliore analisi.
// Converti l'array di caratteri in una stringa HTML = CharArrayToString(result);
Ora che abbiamo una stringa, possiamo utilizzare la funzione StringFind per localizzare gli elementi HTML. Prima di tutto, assicuriamoci che l'HTML restituito sia effettivamente per la data di oggi e tagliamo tutto ciò che precede questo tag HTML. Utilizziamo la funzione GetHTMLElement per analizzare il codice HTML e restituire il valore compreso tra i tag HTML specificati. Ecco la sua definizione.
// Calendario caricato, assicurati che sia per la data di oggi int i = StringFind(HTML, "<span class=\"date\">"); if(i == -1) return(false); HTML = StringSubstr(HTML, i); string date = GetHTMLElement(HTML, "<span>", "</span>"); if(date != MthName(Month()) + " " + DoubleToStr(Day(), 0)) return(false);
Adesso che abbiamo confermato che il calendario restituito è per la data di oggi, iniziamo ad analizzare ogni riga della tabella e ad estrarre gli elementi necessari: ora dell'evento, valuta, impatto e titolo dell'evento. Dobbiamo fare questo per ogni riga della tabella presente nel codice HTML fino alla fine del calendario o fino a raggiungere il numero massimo di eventi giornalieri.
Una volta estratti i dati di ciascuna riga, li aggiungiamo alla struttura DailyEvents.
// Ora ottieni le righe della tabella per ogni evento lasttime = NULL; cnrt = 0; date = DoubleToStr(Year(), 0) + "." + DoubleToStr(Month(), 0) + "." + DoubleToStr(Day(), 0) + " "; do { // Ottieni informazioni sull'evento time = GetHTMLElement(HTML, "<td class=\"calendar__cell calendar__time time\">", "</td>"); if(StringFind(time, "<a name=\"upnext\"") == 0) time = GetHTMLElement(time, "class=\"upnext\">", "</span>"); if(StringLen(time) != 0) lasttime = time; if(StringLen(time) == 0) time = lasttime; time = date + time; currency = GetHTMLElement(HTML, "<td class=\"calendar__cell calendar__currency currency\">", "</td>"); impact = GetHTMLElement(HTML, "<span title=\"", "\" class=\""); i = StringFind(impact, " Impact"); if(i != -1) impact = StringSubstr(impact, 0, i); title = GetHTMLElement(HTML, "\"calendar__event-title\">", "</span>"); // È un evento di alta importanza? if(StringFind(Symbol(), currency) != -1 && impact == "High") { // Aggiungi alla struttura degli eventi giornalieri DailyEvents[cntr].displayed = false; DailyEvents[cntr].time = time; DailyEvents[cntr].title = title; DailyEvents[cntr++].currency = currency; } // Taglia la stringa HTML alla successiva riga della tabella i = StringFind(HTML, "</tbody> </table> </td> </tr> "); if(i != -1) HTML = StringSubstr(HTML, i+30); if(StringFind(HTML, "</table> <div class=\"foot\">") == 0) i = -1; } while(i != -1 || cntr == MaxDailyEvents);
Una volta analizzate tutte le righe della tabella e raggiunta la fine del calendario, dobbiamo visualizzare gli eventi sul grafico. Se l'evento è nel futuro, vogliamo visualizzare una linea verticale, mentre in passato non mostriamo nulla.
// Visualizza gli eventi di alta importanza, se presenti lasttime = NULL; for(cntr = 0; cntr < MaxDailyEvents; cntr++) { if(StringLen(DailyEvents[cntr].time) == 0) break; // Crea un marcatore di evento sul grafico se l'ultimo mercato non era alla stessa ora if(lasttime != DailyEvents[cntr].time) { res = cntr; // Se abbiamo un 'pm' nella stringa, aggiungi 12 ore all'ora if(StringFind(DailyEvents[cntr].time, "pm") != -1) DailyEvents[cntr].time = TimeToStr(StrToTime(DailyEvents[cntr].time) + 43200); if(ObjectCreate(0, Event + cntr, OBJ_EVENT, 0, StrToTime(DailyEvents[cntr].time), 0)) { ObjectSetString(0, Event + cntr, OBJPROP_TEXT, DailyEvents[cntr].title + " (" + DailyEvents[cntr].currency + ")"); ObjectSetInteger(0, Event + cntr, OBJPROP_COLOR, Red); ObjectSetInteger(0, Event + cntr, OBJPROP_WIDTH, 2); ObjectSetInteger(0, Event + cntr, OBJPROP_BACK, true); ObjectSetInteger(0, Event + cntr, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, Event + cntr, OBJPROP_SELECTED, false); ObjectSetInteger(0, Event + cntr, OBJPROP_HIDDEN, true); ObjectSetString(0, Event + cntr, OBJPROP_TOOLTIP, DailyEvents[cntr].title + " (" + DailyEvents[cntr].currency + ")"); } // Crea una linea verticale se l'evento è nel futuro if(TimeCurrent() < TimeOffset(DailyEvents[cntr].time, 0)) { if(ObjectCreate(0, VLine + cntr, OBJ_VLINE, 0, TimeOffset(DailyEvents[cntr].time, 0), 0)) { ObjectSetInteger(0, VLine + cntr, OBJPROP_COLOR, Red); ObjectSetInteger(0, VLine + cntr, OBJPROP_WIDTH, 1); ObjectSetInteger(0, VLine + cntr, OBJPROP_BACK, true); ObjectSetInteger(0, VLine + cntr, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, VLine + cntr, OBJPROP_SELECTED, false); ObjectSetInteger(0, VLine + cntr, OBJPROP_HIDDEN, true); ObjectSetString(0, VLine + cntr, OBJPROP_TOOLTIP, DailyEvents[cntr].title + " (" + DailyEvents[cntr].currency + ")"); } } else DailyEvents[cntr].displayed = true; } else { title = ObjectGetString(0, Event + res, OBJPROP_TOOLTIP); title += "\n" + DailyEvents[cntr].title + " (" + DailyEvents[cntr].currency + ")"; ObjectSetString(0, Event + res, OBJPROP_TOOLTIP, title); if(TimeCurrent() < TimeOffset(DailyEvents[cntr].time, 0)) ObjectSetString(0, VLine + res, OBJPROP_TOOLTIP, title); } lasttime = DailyEvents[cntr].time; }
Se gli eventi sono nel futuro, voglio notificare l'utente riguardo a un evento imminente se è entro 5 minuti dall'ora attuale e rimuovere la linea verticale. Questo si fa aggiungendo un po' di codice nella funzione start() del tuo EA o indicatore.
//+------------------------------------------------------------------+ //| Funzione di avvio dell'Expert | //+------------------------------------------------------------------+ void start() { string event = NULL; // C'è un evento di alta importanza nei prossimi 5 minuti? for(int i = 0; i < MaxDailyEvents; i++) { if(StringLen(DailyEvents[i].time) == 0) break; if(TimeCurrent() >= StrToTime(DailyEvents[i].time) - 300 && TimeCurrent() < StrToTime(DailyEvents[i].time) && !DailyEvents[i].displayed) { // Evento tra 5 minuti... event += DailyEvents[i].title + " (" + DailyEvents[i].currency + "), "; DailyEvents[i].displayed = true; // Elimina la linea verticale associata all'evento if(ObjectFind("VLine" + DoubleToStr(i, 0)) >= 0) ObjectDelete("VLine" + DoubleToStr(i, 0)); } } // Qualcosa da visualizzare? if(StringLen(event) != 0) { event += "tra 5 minuti."; Alert(event); } }
Infine, dobbiamo ottenere gli eventi giornalieri. Questo si fa aggiungendo una riga nella tua funzione OnInit().
//+------------------------------------------------------------------+ //| Funzione di inizializzazione dell'Expert | //+------------------------------------------------------------------+ int OnInit() { // Ottieni gli eventi di oggi GetHighImpactEvents(); return(INIT_SUCCEEDED); }
Facile e veloce! Puoi ovviamente modificare il codice per visualizzare tutti gli eventi per la coppia di valute o aggiungere parametri di input al tuo indicatore o EA per specificare quale impatto visualizzare (alto, medio o basso) e, naturalmente, aggiungere un controllo per il cambio di giorno a mezzanotte per ottenere una nuova lista di eventi giornalieri, ma ora lascio a te il divertimento di giocarci! :)
Buon trading!
-Claude.
Post correlati
- MQL5 Wizard: Creare Trading Signals con Morning/Evening Stars e MFI per MetaTrader 5
- Rilevare il Venerdì della Prima Settimana del Mese: La Guida per il Giorno NFP
- MQL5 Wizard: Crea Trading Signals con 3 Corvi Neri/3 Soldati Bianchi e RSI
- Utilizzare MQL5 Wizard per generare segnali di trading: Hammer e Hanging Man con CCI
- MQL5 Wizard: Creare Trade Signals con Hammer/Hanging Man e RSI