Si eres trader, seguro que sabes lo importante que es tener acceso a datos históricos completos para tus análisis y pruebas. En este artículo, te mostraré cómo utilizar este código para descargar todos los ticks disponibles de un símbolo en MetaTrader 5. ¿Listo para mejorar tus backtests?
Este sistema de trading escaneará el mercado de tu bróker y recopilará los símbolos de los cuales descargará todos los ticks, o hasta una fecha específica que tú decidas. Es ideal para crear gráficos personalizados a partir de esos ticks y realizar análisis más profundos.
Recuerda que los ticks se almacenan en la carpeta de datos, así que asegúrate de tener suficiente espacio en tu disco duro. Además, para facilitar la descarga de los símbolos, necesitarás un gestor de descargas primero.
Estructura CDownloadManager
La estructura CDownloadManager contiene toda la información que necesitamos:
struct CDownloadManager { bool m_started,m_finished; string m_symbols[],m_current; int m_index; }
- Estado de la descarga (iniciada/terminada)
- Lista de símbolos a escanear
- Símbolo actual
- Índice del símbolo que se está escaneando
También necesitaremos leer y escribir en el disco duro, así que creamos dos funciones rápidas para manejar cadenas de texto en archivos binarios.
Función para guardar cadenas en un archivo:
void writeStringToFile(int f,string thestring) { // Guardar cadena de símbolo 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); } }
Esta función recibe:
- El identificador del archivo f, que debe abrirse con los flags FILE_WRITE|FILE_BIN
- La cadena que se va a escribir en el archivo
La función escribe primero un entero que indica cuántos caracteres hay en la cadena y luego almacena cada carácter.
Función para cargar cadenas desde un archivo:
string readStringFromFile(int f) { string result=""; // Cargar cadena de símbolo 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); }
Esta función recibe:
- El identificador del archivo f, que debe abrirse con los flags FILE_READ|FILE_BIN
Lee primero un entero que indica cuántos caracteres se esperan en ese punto del archivo, luego lee cada carácter en un arreglo y finalmente genera una cadena a partir de ese arreglo que se devuelve como resultado.
Inicializando el Gestor de Descargas
Ahora, necesitamos una forma de inicializar el gestor y llenarlo a partir del mercado:
//+------------------------------------------------------------------+ //| Obtener símbolos del mercado | //+------------------------------------------------------------------+ void grab_symbols() { //! Solo desde el mercado! int s=SymbolsTotal(true); ArrayResize(m_symbols,s,0); for(int i=0;i<ArraySize(m_symbols);i++) { m_symbols[i]=SymbolName(i,true); } }
Es muy sencillo:
- Solicitamos cuántos símbolos hay en el mercado (activos)
- Redimensionamos nuestro arreglo m_symbols para recibirlos
- Recorremos los símbolos y solicitamos el nombre de cada símbolo
El siguiente paso es manejar el proceso de descarga de los datos del símbolo, así que necesitaremos una función que actúe como gestor:
//+------------------------------------------------------------------+ //| Gestionar el proceso de descarga de símbolos | //+------------------------------------------------------------------+ void manage(string folder,string filename) { // Esencialmente, esto inicia o navega al siguiente símbolo // si está configurado if(ArraySize(m_symbols)>0) { // Si no ha comenzado if(!m_started) { m_started=true; // Ir al primer símbolo 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; } // Si comenzó 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("Finalizado"); ExpertRemove(); return; } } } else { Print("Por favor, obtén los símbolos primero"); } }
¿Cómo funciona el sistema?
- Se abre el gráfico, necesitas al menos un gráfico y se establece un temporizador.
- Ese temporizador se ejecuta y cancelamos el temporizador.
- Verificamos si se trata de una nueva descarga o una descarga continuada.
- Si es una nueva descarga, configuramos el gestor obteniendo todos los símbolos.
- Si es una descarga continuada, descargamos datos del símbolo actual.
Esta es la parte del código que lleva a cabo la descarga en el temporizador:
//+------------------------------------------------------------------+ //| Temporizador | //+------------------------------------------------------------------+ void OnTimer() { //--- si está sincronizado if(SymbolIsSynchronized(_Symbol)&&TerminalInfoInteger(TERMINAL_CONNECTED)==1) { EventKillTimer(); //--- cargar el sistema aquí if(MANAGER.load(MANAGER_FOLDER,MANAGER_STATUS_FILE)) { //--- sistema cargado, estamos procesando un símbolo Comment("Sistema cargado y estamos procesando "+MANAGER.m_current); //--- carga de ticks //--- encontrar el tick más antiguo disponible en el bróker 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("Por favor, espera"); 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 más antiguo : "+TimeToString((datetime)(oldest/1000),TIME_DATE|TIME_MINUTES|TIME_SECONDS)+"\nCursor("+TimeToString((datetime)(cursorMSC/1000),TIME_DATE|TIME_MINUTES|TIME_SECONDS)+")\nIntentos("+IntegerToString(attempts)+")\nPor favor, espera la respuesta..."); } //--- en este punto tenemos el tick más antiguo //--- comenzamos a solicitar ticks desde el más antiguo al más nuevo if(oldest!=LONG_MAX) { ArrayFree(receiver); datetime newest_tick=0; //--- recibir la hora del último tick para este símbolo almacenado en symbol_time datetime most_recent_candle=(datetime)SymbolInfoInteger(_Symbol,SYMBOL_TIME); while(newest_tick<most_recent_candle) { //--- solicitar un nuevo lote comenzando desde el tick más antiguo con el límite de ticks especificado int pulled=CopyTicks(_Symbol,receiver,COPY_TICKS_ALL,oldest,tick_packets); if(pulled>0) { //--- si extraemos un nuevo lote, actualizamos nuestros tiempos descargados newest_tick=receiver[pulled-1].time; oldest=receiver[pulled-1].time_msc; ArrayFree(receiver); } //--- tiempo de espera para las solicitudes del servidor, puedes alterarlo si lo deseas Sleep(44); Comment("Se extrajo hasta "+TimeToString(newest_tick,TIME_DATE|TIME_MINUTES|TIME_SECONDS)+" hasta ahora"); } } else { Alert("Por favor, cierra el terminal \n ve a la carpeta de ticks \n y elimina las carpetas vacías"); ExpertRemove(); } //--- actualiza el gestor y sigue adelante MANAGER.manage(MANAGER_FOLDER,MANAGER_STATUS_FILE); } else { //--- obtener los símbolos del mercado para empezar la descarga Comment("Obteniendo MW y comenzando"); MANAGER.grab_symbols(); MANAGER.manage(MANAGER_FOLDER,MANAGER_STATUS_FILE); } } }
Publicaciones relacionadas
- Crea tu Asesor Experto con MQL5: Señales de Trading Basadas en Dark Cloud Cover y Piercing Line
- Señales de Trading con MQL5: Patrones de Estrellas y MFI
- MQL5 Wizard: Crea EAs con Señales de Trading basadas en Dark Cloud Cover y Piercing Line
- MQL5 Wizard: Crea un Asesor Experto con Señales de Bullish Harami y Bearish Harami + CCI
- Cómo Crear un Asesor Experto con MQL5: Señales de Trading Basadas en Estrellas y Estocástico