2026-04-16 12:28:07 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| FolderTaskToCSV2.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 <TSN\\MQLArticles\\Utils\\File.mqh>
|
2026-04-30 16:09:33 -05:00 | | | #include <TSN\\MQLArticles\\Utils\\StrMacth.mqh>
|
2026-04-16 12:28:07 -05:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Inputs |
|
| | | //+------------------------------------------------------------------+
|
| | | input string InpFolder = "";
|
| | | input bool InpFolderIsInCommon = true;
|
| | | input string InpParamActiveGenerateName = "InpGenerateMode";
|
| | | input datetime InpDataStartDate = 0;
|
| | | input datetime InpDataEndDate = 0;
|
| | | input string InpCsvFileNameOutput = "task.csv";
|
| | | input bool InpCsvFileNameOutputIsInCommon = true;
|
2026-04-30 16:09:33 -05:00 | | | input string InpStrMatchExcluyed = "";
|
| | | input string InpStrMatchIncluyed = "*.set";
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-07-15 14:10:22 -05:00 | | | TSN::CFolderOpsBase g_simple_str_math;
|
2026-04-30 16:09:33 -05:00 | | |
|
2026-04-16 12:28:07 -05:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Expert initialization function |
|
| | | //+------------------------------------------------------------------+
|
| | | int OnInit()
|
| | | {
|
2026-04-30 16:09:33 -05:00 | | | //---
|
| | | g_simple_str_math.SetArrExcluyed(InpStrMatchExcluyed, '|');
|
| | | g_simple_str_math.SetArrIncluyed(InpStrMatchIncluyed, '|');
|
| | |
|
2026-04-16 12:28:07 -05:00 | | | //---
|
| | | TaskTester tasks[];
|
| | | int profundidad = 0;
|
| | | string sym = "";
|
| | | ENUM_TIMEFRAMES tf = PERIOD_CURRENT;
|
| | |
|
| | | //---
|
| | | ulong antes = GetTickCount64();
|
| | | Print(ProccesFolder(InpFolder, tasks, profundidad, sym, tf));
|
| | | 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, ENUM_TIMEFRAMES& curr_tf)
|
| | | {
|
| | | //---
|
| | | 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;
|
| | |
|
2026-04-30 16:09:33 -05:00 | | | //---
|
| | | if(g_simple_str_math.IsFileExcluyed(full_path))
|
| | | continue;
|
| | | if(!g_simple_str_math.IsFileIncluyed(full_path))
|
| | | continue;
|
| | |
|
2026-04-16 12:28:07 -05:00 | | | //---
|
| | | if(fn[StringLen(fn) - 1] == '\\')
|
| | | {
|
| | | prof++;
|
| | |
|
| | | if(prof == 1)
|
| | | {
|
| | | // Carpeta simbolo
|
| | | curr_symbol = fn;
|
| | | StringSetLength(curr_symbol, StringLen(curr_symbol) - 1);
|
| | | }
|
| | | else
|
| | | if(prof == 2)
|
| | | {
|
| | | string tf_name = fn;
|
| | | StringSetLength(tf_name, StringLen(tf_name) - 1);
|
| | | curr_tf = StrShortTimeframeToEnumNoRef(tf_name);
|
| | | }
|
| | | else
|
| | | {
|
| | | Print("No se procesa folder con mas de 2 de profundidad");
|
| | | prof--;
|
| | | continue;
|
| | | }
|
| | |
|
| | | //---
|
| | | if(!ProccesFolder(full_path, taskes, prof, curr_symbol, curr_tf))
|
| | | {
|
| | | 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;
|
| | | taskes[pos].timeframe = curr_tf; // TF desde carpeta, no desde setfile
|
| | |
|
| | | //---
|
| | | if(!ProccesSetFile(full_path, taskes[pos]))
|
| | | {
|
| | | printf("Fallo al procesar set file path = %s, se omitira para no dañar", full_path);
|
| | | return false;
|
| | | }
|
| | | }
|
| | | }
|
| | | while(FileFindNext(handle, fn));
|
| | |
|
| | | //---
|
| | | FileFindClose(handle);
|
| | |
|
| | | //---
|
| | | if(prof)
|
| | | {
|
| | | prof--;
|
| | | // Reseteamos TF al salir de carpeta timeframe
|
| | | if(prof == 1)
|
| | | curr_tf = WRONG_VALUE; // err
|
| | | else
|
| | | if(prof == 0)
|
| | | 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);
|
| | |
|
| | | //--- TF ya asignado desde carpeta, solo completamos el resto
|
| | | task.label_id = 0;
|
| | | task.label = FileRemoveExtensionNoRef(GetPureFileName(path));
|
| | | task.set_file = (InpFolderIsInCommon ? (TERMINAL_MT5_COMMON_PATH + "\\Files\\") : (TERMINAL_MT5_ROOT + "Files\\")) + path;
|
| | | task.start_date = InpDataStartDate;
|
| | | task.end_date = InpDataEndDate;
|
| | |
|
| | | //--- Modificamos el parametro de aidata gen
|
| | | int start_t = StringFind(content, InpParamActiveGenerateName);
|
| | | if(start_t == -1)
|
| | | {
|
| | | PrintFormat("No se encontrol el paramtro activar aidata: '%s', en setfile", InpParamActiveGenerateName);
|
| | | 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;
|
| | | }
|
| | |
|
| | | //---
|
| | | 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)
|
| | | {
|
| | | 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);
|
| | | }
|
| | | //+------------------------------------------------------------------+
|