//+------------------------------------------------------------------+ //| FolderTaskToCSV.mq5 | //| Copyright 2026,Niquel Mendoza. | //| https://www.mql5.com/en/users/nique_372 | //+------------------------------------------------------------------+ #property copyright "Copyright 2026,Niquel Mendoza." #property link "https://www.mql5.com/en/users/nique_372" #property version "1.00" #property strict //+------------------------------------------------------------------+ //| Include | //+------------------------------------------------------------------+ #include "..\\Backend\\Tester\\Saver.mqh" #include //+------------------------------------------------------------------+ //| Inputs | //+------------------------------------------------------------------+ input string InpFolder = ""; input bool InpFolderIsInCommon = true; input string InpParamTimeframeName = "InpTimeframe"; input string InpParamActiveGenerateName = "InpGenerateMode"; input datetime InpDataStartDate = 0; input datetime InpDataEndDate = 0; input string InpCsvFileNameOutput = "task.csv"; input bool InpCsvFileNameOutputIsInCommon = true; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- TaskTester tasks[]; int profundidad = 0; string sym = ""; ulong antes = GetTickCount64(); Print(ProccesFolder(InpFolder, tasks, profundidad, sym)); ulong desp = GetTickCount64(); PrintFormat("res = %I64u ", (desp - antes)); //--- CTaskSaver saver; string ms; if(!saver.Save(InpCsvFileNameOutput, tasks, ArraySize(tasks), (InpFolderIsInCommon ? FILE_COMMON : 0), false, ms)) { Print(ms); } //--- return(INIT_FAILED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool ProccesFolder(const string& main_folder, TaskTester& taskes[], int& prof, string& curr_symbol) { //--- string fn = ""; const long handle = FileFindFirst(main_folder + "*", fn, (InpFolderIsInCommon ? FILE_COMMON : 0)); if(handle == INVALID_HANDLE) { Print("No hay archivos en: ", main_folder); prof--; return true; } //--- do { const string full_path = main_folder + fn; //--- if(fn[StringLen(fn) - 1] == '\\') { prof++; if(prof == 1) { curr_symbol = fn; StringSetLength(curr_symbol, StringLen(curr_symbol) - 1) ; // Quitamos el \\ } else { Print("No se procesa folder con mas de 1 de profundidad"); prof--; continue; } //--- if(!ProccesFolder(full_path, taskes, prof, curr_symbol)) { PrintFormat("Fallo al procesar path =%s", full_path); return false; } } else { //--- const int pos = ArraySize(taskes); ArrayResize(taskes, pos + 1); //--- taskes[pos].symbol = curr_symbol; taskes[pos].symbol_folder = curr_symbol; //--- if(!ProccesSetFile(full_path, taskes[pos])) { printf("Fallo al procesar set file path = %s, se omitira para no dañar", full_path); return false; } // Devolvemos } } while(FileFindNext(handle, fn)); //--- FileFindClose(handle); //--- // Si esto se jeucta es por que prof=1; if(prof) { prof--; curr_symbol = ""; } //--- return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool ProccesSetFile(const string& path, TaskTester& task) { //--- ::ResetLastError(); int fh = FileOpen(path, FILE_READ | FILE_BIN | (InpFolderIsInCommon ? FILE_COMMON : 0)); if(fh == INVALID_HANDLE) { PrintFormat("Fallo al abrir el archivo =%s, ultimo error = %d", path, ::GetLastError()); return false; } //--- const ulong size = FileSize(fh); string content = FileReadString(fh, int(size)); FileClose(fh); //--- int start_t = StringFind(content, InpParamTimeframeName); if(start_t == -1) { PrintFormat("No se encontrol el paramtro timeframe: '%s', en setfile: %s", InpParamTimeframeName, path); return false; } int start_e = StringFind(content, "=", start_t); if(start_e == -1) { Print("No se encontrol el ="); return false; } int end = StringFind(content, "|", start_e); if(end == -1) { Print("No se encontrol el |"); return false; } /* return StringFormat("%d|%s|%s|%s|%s|%s|%s|%d", int(timeframe), // [0] symbol, // [1] set_file, // [2] TimeToString(start_date), // [3] TimeToString(end_date), // [4] symbol_folder, // [5] label, // [6] label_id); // [7] */ // Asignamos los valores basicos task.timeframe = ENUM_TIMEFRAMES(int(StringSubstr(content, start_e + 1, end - 1))); task.label_id = 0; task.label = FileRemoveExtensionNoRef(GetPureFileName(path)); task.set_file = (InpFolderIsInCommon ? (TERMINAL_MT5_COMMON_PATH + "\\Files\\") : (TERMINAL_MT5_ROOT + "Files\\")) + path; // Relativo al mismo ahora una cosa este folder se debera de copiar tal cual luego a Profiles\\Tester\\ task.start_date = InpDataStartDate; task.end_date = InpDataEndDate; //--- Modicamos el parametro de aidatagen start_t = StringFind(content, InpParamActiveGenerateName); if(start_t == -1) { PrintFormat("No se encontrol el paramtro activar aidata: '%s', en setfile", InpParamActiveGenerateName); return false; } start_e = StringFind(content, "=", start_t); if(start_e == -1) { Print("No se encontrol el ="); return false; } end = StringFind(content, "|", start_e); if(end == -1) { Print("No se encontrol el |"); return false; } //--- start_e++; end--; //--- int pos = 0; //Inp=false| const static ushort short_arr_true[4] = {'t', 'r', 'u', 'e'}; for(int i = start_e; i <= end; i++) { if(pos >= 4) { //Print("Supera"); DeleteFromStr(content, i, end); break; } content.SetChar(i, short_arr_true[pos++]); } //--- ::ResetLastError(); fh = FileOpen(path, FILE_WRITE | FILE_TXT | (InpFolderIsInCommon ? FILE_COMMON : 0), 0); if(fh == INVALID_HANDLE) { PrintFormat("Fallo al abrir el archivo =%s, ultimo error = %d", path, ::GetLastError()); return false; } ::FileWriteString(fh, content); FileClose(fh); //--- return true; } //+------------------------------------------------------------------+ // [a][b][c][d][e] void DeleteFromStr(string& str, int pos_from, int pos_to) { const int count = (pos_to - pos_from) + 1; const int total = StringLen(str) - count; for(int i = pos_from; i < total; i++) { str.SetChar(i, str[i + count]); } str.Truncate(total); } //+------------------------------------------------------------------+