Ciao a tutti, oggi voglio parlarvi di un Expert Advisor che può aiutarvi a scaricare tutti i tick disponibili per un simbolo specifico sul vostro conto di trading. Questo è particolarmente utile per chi desidera effettuare backtest dettagliati o creare grafici personalizzati a partire dai tick.
Il codice di questo EA esplorerà la vostra lista di strumenti e scaricherà tutti i tick disponibili, fino a una data specifica. Ricordatevi che i terminali salveranno i tick nella cartella dei dati, quindi assicuratevi di avere spazio sufficiente sul disco rigido.
Per facilitare il download dei simboli, abbiamo bisogno di un download manager. La struttura CDownloadManager conterrà tutte le informazioni necessarie per gestire il processo.
struct CDownloadManager { bool m_started, m_finished; string m_symbols[], m_current; int m_index; }
- Lo stato del download (iniziato/finalizzato)
- La lista dei simboli da esaminare
- Il simbolo corrente
- L'indice del simbolo in esame
In aggiunta, avremo bisogno di funzioni per leggere e scrivere sul disco rigido. Dato che lavoriamo con i simboli, creiamo due funzioni per gestire la scrittura e la lettura delle stringhe dai file binari.
Funzione per salvare la stringa su file:
void writeStringToFile(int f,string thestring) { // salva la stringa del simbolo char sysave[]; int charstotal=StringToCharArray(thestring,sysave,0,StringLen(thestring),CP_ACP); FileWriteInteger(f,charstotal,INT_VALUE); for(int i=0;i<charstotal;i++) { FileWriteInteger(f,sysave[i],CHAR_VALUE); } }
Questa funzione riceve:
- Il manico del file f, di un file aperto per la scrittura con flag binario FILE_WRITE|FILE_BIN
- La stringa da scrivere nel file
Scrive un intero che rappresenta la lunghezza della stringa e poi memorizza ciascun carattere della stringa.
Funzione per caricare la stringa dal file:
string readStringFromFile(int f) { string result=""; // carica la stringa del simbolo char syload[]; int charstotal=(int)FileReadInteger(f,INT_VALUE); if(charstotal>0) { ArrayResize(syload,charstotal,0); for(int i=0;i<charstotal;i++) { syload[i]=(char)FileReadInteger(f,CHAR_VALUE); } result=CharArrayToString(syload,0,charstotal,CP_ACP); } return(result); }
Questa funzione riceve:
- Il manico del file f di un file aperto per la lettura con flag binario, FILE_READ|FILE_BIN
Legge un intero che rappresenta quanti caratteri ci si aspetta in quel punto del file. Procede quindi a leggere ciascun carattere in un array di char e poi crea una stringa da quell'array che viene restituita come risultato della lettura.
Torniamo alla struttura CDownloadManager. Abbiamo bisogno di un modo per inizializzare il manager e riempirlo con i simboli dalla lista di strumenti:
//+------------------------------------------------------------------+ //| Estrai i simboli dalla lista di strumenti | //+------------------------------------------------------------------+ void grab_symbols() { //! solo dalla lista di strumenti ! int s=SymbolsTotal(true); ArrayResize(m_symbols,s,0); for(int i=0;i<ArraySize(m_symbols);i++) { m_symbols[i]=SymbolName(i,true); } }
Abbastanza semplice:
- Chiediamo quanti simboli ci sono nella lista di strumenti (attivi)
- Ridimensioniamo il nostro array m_symbols per riceverli
- Iteriamo attraverso i simboli totali e richiediamo il nome di ciascun simbolo
Ora siamo responsabili anche della gestione del download dei dati dei simboli, quindi avremo bisogno di una funzione che essenzialmente gestisca il processo:
//+------------------------------------------------------------------+ //| Gestisci il processo di download dei simboli | //+------------------------------------------------------------------+ void manage(string folder,string filename) { // essenzialmente inizia o naviga al simbolo successivo // se impostato if(ArraySize(m_symbols)>0) { // se non iniziato if(!m_started) { m_started=true; // vai al primo simbolo m_current=m_symbols[0]; m_index=1; save(folder,filename); if(_Symbol!=m_current) { ChartSetSymbolPeriod(ChartID(),m_current,_Period); } else { ENUM_TIMEFRAMES new_period=PERIOD_M1; for(int p=0;p<ArraySize(TFS);p++) { if(_Period!=TFS[p]) { new_period=TFS[p]; break; } } ChartSetSymbolPeriod(ChartID(),m_current,new_period); } return; } // se iniziato else { m_index++; if(m_index<=ArraySize(m_symbols)) { m_current=m_symbols[m_index-1]; save(folder,filename); if(_Symbol!=m_current) { ChartSetSymbolPeriod(ChartID(),m_current,_Period); } return; } else { m_finished=true; FileDelete(folder+"\"+filename); Print("Finito"); ExpertRemove(); return; } } else { Print("Per favore, estrai prima i simboli"); } }
Come funziona il sistema:
- Il grafico si apre, abbiamo bisogno di un grafico, e viene impostato un timer.
- Quel timer viene eseguito, annulliamo il timer
- Controlliamo se si tratta di un nuovo download o di un download continuato
- Se è un nuovo download, lo impostiamo estraendo tutti i simboli
- Se è un download continuato, scarichiamo i dati per il simbolo corrente
Questa è la parte del codice che gestisce il download temporizzato:
//+------------------------------------------------------------------+ //| Timer | //+------------------------------------------------------------------+ void OnTimer() { //--- se sincronizzato if(SymbolIsSynchronized(_Symbol)&&TerminalInfoInteger(TERMINAL_CONNECTED)==1) { EventKillTimer(); //--- carica il sistema qui if(MANAGER.load(MANAGER_FOLDER,MANAGER_STATUS_FILE)) { //--- sistema caricato, stiamo processando un simbolo Comment("Sistema caricato e stiamo processando "+MANAGER.m_current); //--- caricamento dei tick //--- trova il tick più vecchio disponibile presso il broker int attempts=0; int ping=-1; datetime cursor=flatten(TimeTradeServer()); long cursorMSC=((long)cursor)*1000; long jump=2592000000;//60*60*24*30*1000; MqlTick receiver[]; long oldest=LONG_MAX; Comment("Attendere prego"); while(attempts<5) { ping=CopyTicks(_Symbol,receiver,COPY_TICKS_ALL,cursorMSC,1); if(ping==1) { if(receiver[0].time_msc==oldest) { attempts++; } else { attempts=0; } if(receiver[0].time_msc<oldest) { oldest=receiver[0].time_msc; } cursorMSC-=jump; if(limitDate&&receiver[0].time<=oldestLimit) { break; } } else { attempts++; } Sleep(44); Comment("Tick più vecchio: "+TimeToString((datetime)(oldest/1000),TIME_DATE|TIME_MINUTES|TIME_SECONDS)+"\nCursore("+TimeToString((datetime)(cursorMSC/1000),TIME_DATE|TIME_MINUTES|TIME_SECONDS)+")\nTentativi("+IntegerToString(attempts)+")\nAttendere la risposta..."); } //--- a questo punto abbiamo il tick più vecchio //--- inizia a richiedere i tick dal più vecchio al più nuovo if(oldest!=LONG_MAX) { ArrayFree(receiver); datetime newest_tick=0; //--- ricevi il tempo dell'ultimo tick per questo simbolo memorizzato in symbol_time datetime most_recent_candle=(datetime)SymbolInfoInteger(_Symbol,SYMBOL_TIME); while(newest_tick<most_recent_candle) { //--- richiedi un nuovo lotto partendo dal tempo più vecchio con il limite di tick specificato int pulled=CopyTicks(_Symbol,receiver,COPY_TICKS_ALL,oldest,tick_packets); if(pulled>0) { //--- se estraiamo un nuovo lotto aggiorniamo i tempi scaricati newest_tick=receiver[pulled-1].time; oldest=receiver[pulled-1].time_msc; ArrayFree(receiver); } //--- timeout delle richieste al server, alteralo se vuoi Sleep(44); Comment("Estratti fino a "+TimeToString(newest_tick,TIME_DATE|TIME_MINUTES|TIME_SECONDS)+" fino ad ora"); } } else { Alert("Chiudi il terminale vai alla cartella dei tick e cancella le cartelle vuote"); ExpertRemove(); } //--- aggiorna il manager e passa oltre MANAGER.manage(MANAGER_FOLDER,MANAGER_STATUS_FILE); } else { //--- estrai i simboli dalla lista di strumenti per iniziare il download Comment("Estraendo MW e avviando"); MANAGER.grab_symbols(); MANAGER.manage(MANAGER_FOLDER,MANAGER_STATUS_FILE); } }
Post correlati
- Rilevare il Venerdì della Prima Settimana del Mese: La Guida per il Giorno NFP
- EA Efficiente: Come Aggiungere la Chiusura del Venerdì per Migliorare le Performance
- Utilità Market Watch Panel: il tuo alleato in MetaTrader 4
- MQL5 Wizard: Creare Trading Signals con Morning/Evening Stars e MFI per MetaTrader 5
- MQL5 Wizard: Creare Expert Advisor per Segnali di Trading con Bullish Harami, Bearish Harami e MFI