MetaTrader5
Scarica la Storia Completa dei Tick di un Simbolo con MetaTrader 5
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);
}
}
2025.02.22