269 lines
8 KiB
MQL5
269 lines
8 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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 <TSN\\MQLArticles\\Utils\\File.mqh>
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 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);
|
|
}
|
|
//+------------------------------------------------------------------+
|