497 lines
30 KiB
MQL5
497 lines
30 KiB
MQL5
//+------------------------------------------------------------------+
|
|
string get_header(string _filename)
|
|
{
|
|
int _fh = FileOpen(_filename, FILE_ANSI | FILE_COMMON | FILE_CSV | FILE_READ, "\n");
|
|
string header = FileReadString(_fh);
|
|
FileClose(_fh);
|
|
return header;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
int numero_lineas_csv(string _filename)
|
|
{
|
|
int lineas = 0;
|
|
int _fh = FileOpen(_filename, FILE_ANSI | FILE_COMMON | FILE_CSV | FILE_READ, "\n");
|
|
while(!FileIsEnding(_fh))
|
|
{
|
|
FileReadString(_fh);
|
|
lineas++;
|
|
}
|
|
FileClose(_fh);
|
|
return lineas;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
int numero_columnas_csv(string _filename)
|
|
{
|
|
int _fh = FileOpen(_filename, FILE_ANSI | FILE_COMMON | FILE_CSV | FILE_READ, "\n");
|
|
string linea = FileReadString(_fh);
|
|
string columnas[];
|
|
StringSplit(linea, ',', columnas);
|
|
FileClose(_fh);
|
|
return ArraySize(columnas);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
matrix cargar_atributos_csv(string _filename, string &out_cabezera, int num_clases = 1)
|
|
{
|
|
int num_columnas = numero_columnas_csv(_filename);
|
|
int num_lineas = numero_lineas_csv(_filename);
|
|
matrix atributos(num_lineas - 1, num_columnas - num_clases);
|
|
int _fh = FileOpen(_filename, FILE_ANSI | FILE_COMMON | FILE_CSV | FILE_READ, "\n");
|
|
if(_fh == INVALID_HANDLE)
|
|
{
|
|
Print(__FUNCTION__, "::Error: No se pudo abrir el archivo ", _filename);
|
|
return atributos;
|
|
}
|
|
// Leer cabecera (ignorar)
|
|
out_cabezera = FileReadString(_fh);
|
|
int index = 0;
|
|
while(!FileIsEnding(_fh))
|
|
{
|
|
string linea = FileReadString(_fh);
|
|
if(StringLen(linea) == 0) // Ignorar líneas vacías
|
|
continue;
|
|
string datos[];
|
|
StringSplit(linea, ',', datos);
|
|
// Validar si la línea tiene el número esperado de columnas
|
|
if(ArraySize(datos) != num_columnas)
|
|
{
|
|
Print("Advertencia: Línea mal formada en archivo CSV: ", linea);
|
|
continue;
|
|
}
|
|
vector atributos_linea(num_columnas - num_clases);
|
|
for(int i = 0; i < num_columnas - num_clases; i++)
|
|
atributos_linea.Set(i, StringToDouble(datos[i]));
|
|
atributos.Row(atributos_linea, index);
|
|
index++;
|
|
}
|
|
FileClose(_fh);
|
|
return atributos;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Función para extraer una columna de un CSV |
|
|
//+------------------------------------------------------------------+
|
|
string ExtractCSVColumn(string file_name, int col_index, ushort separator = ',')
|
|
{
|
|
string result = "";
|
|
string sym = ShortToString(separator);
|
|
// Abrir el archivo CSV en modo lectura
|
|
int handle = FileOpen(file_name, FILE_READ | FILE_CSV);
|
|
if(handle == INVALID_HANDLE)
|
|
{
|
|
Print(__FUNCTION__, "::Error al abrir el archivo: ", file_name);
|
|
return "";
|
|
}
|
|
|
|
// Leer el archivo línea por línea hasta el final
|
|
while(!FileIsEnding(handle))
|
|
{
|
|
string line = FileReadString(handle);
|
|
|
|
// Dividir la línea por comas en un arreglo de strings
|
|
string columns[];
|
|
int count = StringSplit(line, separator, columns);
|
|
|
|
// Verificar que la columna deseada exista en esta línea
|
|
if(count > col_index)
|
|
{
|
|
// Si ya hay contenido en 'result', se añade una coma como separador
|
|
if(result != "")
|
|
result += sym;
|
|
result += columns[col_index];
|
|
}
|
|
}
|
|
|
|
FileClose(handle);
|
|
return result;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
matrix cargar_clases_csv(string _filename, int num_clases = 1)
|
|
{
|
|
int num_columnas = numero_columnas_csv(_filename);
|
|
int num_lineas = numero_lineas_csv(_filename);
|
|
matrix clases(num_lineas - 1, num_clases);
|
|
int _fh = FileOpen(_filename, FILE_ANSI | FILE_COMMON | FILE_CSV | FILE_READ, "\n");
|
|
FileReadString(_fh);
|
|
int index = 0;
|
|
while(!FileIsEnding(_fh))
|
|
{
|
|
vector clases_linea(num_clases);
|
|
string linea = FileReadString(_fh);
|
|
string datos[];
|
|
StringSplit(linea, ',', datos);
|
|
for(int i = 0; i < num_clases; i++)
|
|
{
|
|
clases_linea.Set(i, StringToDouble(datos[num_columnas - num_clases + i]));
|
|
}
|
|
clases.Row(clases_linea, index);
|
|
index++;
|
|
}
|
|
FileClose(_fh);
|
|
return clases;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
struct file_data_csv
|
|
{
|
|
private:
|
|
string file_cabezera;
|
|
int file_handle;
|
|
string file_name;
|
|
bool create;
|
|
|
|
public:
|
|
|
|
void Create(string new_file_name, string cabezera, int open_flags = FILE_WRITE | FILE_CSV | FILE_COMMON)
|
|
{
|
|
this.file_name = new_file_name;
|
|
this.file_cabezera = cabezera;
|
|
this.file_handle = FileOpen(this.file_name, open_flags);
|
|
create = true;
|
|
if(this.file_handle == INVALID_HANDLE)
|
|
{
|
|
Print(__FUNCTION__"::Error al abrir el archivo: ", this.file_name, ", ultimo error: ", GetLastError());
|
|
}
|
|
FileWrite(this.file_handle, cabezera);
|
|
};
|
|
inline string GetFileName()
|
|
{
|
|
return this.file_name;
|
|
}
|
|
inline void Close()
|
|
{
|
|
FileClose(this.file_handle);
|
|
}
|
|
inline void Write(string text)
|
|
{
|
|
FileWrite(this.file_handle, text);
|
|
}
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
void DeleteFileWithChecks(string fileName, int commonFlag = FILE_COMMON)
|
|
{
|
|
ResetLastError();
|
|
|
|
// Comprobar si el archivo existe en la ubicación especificada
|
|
if(FileIsExist(fileName, commonFlag))
|
|
{
|
|
// Intentar eliminar el archivo
|
|
if(FileDelete(fileName, commonFlag))
|
|
{
|
|
// Confirmación de que el archivo fue eliminado
|
|
Print("Archivo '", fileName, "' eliminado correctamente.");
|
|
}
|
|
else
|
|
{
|
|
// Informar del error al intentar eliminar el archivo
|
|
int errCode = GetLastError();
|
|
Print("Error al eliminar el archivo '", fileName, "'. Código de error: ", errCode);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// El archivo no existe, informar al usuario
|
|
Print("El archivo '", fileName, "' no existe en la ubicación especificada.");
|
|
}
|
|
}
|
|
|
|
// Función para cambiar el nombre de un archivo en la carpeta de datos comunes o local
|
|
void RenameFileWithChecks(const string oldFileName, int commonFlag, const string newFileName, int modeFlags)
|
|
{
|
|
// Comprobar si el archivo original existe
|
|
if(FileIsExist(oldFileName, commonFlag))
|
|
{
|
|
// Intentar cambiar el nombre del archivo
|
|
if(FileMove(oldFileName, commonFlag, newFileName, modeFlags))
|
|
{
|
|
// Confirmación de que el nombre del archivo fue cambiado
|
|
Print("El archivo '", oldFileName, "' ha sido renombrado a '", newFileName, "' correctamente.");
|
|
}
|
|
else
|
|
{
|
|
// Informar del error al intentar cambiar el nombre del archivo
|
|
int errCode = GetLastError();
|
|
Print("Error al cambiar el nombre del archivo de '", oldFileName, "' a '", newFileName, "'. Código de error: ", errCode);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// El archivo no existe, informar al usuario
|
|
Print("El archivo '", oldFileName, "' no existe en la ubicación especificada.");
|
|
}
|
|
}
|
|
|
|
struct Filas
|
|
{
|
|
string datos[];
|
|
};
|
|
|
|
struct CSV
|
|
{
|
|
Filas data[];
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool CSVToArray(const string &fileName, bool common_flag, CSV &file, ushort line_separator, uint code_page = CP_ACP)
|
|
{
|
|
// Limpia el array existente
|
|
ArrayResize(file.data, 0);
|
|
|
|
int flags = common_flag ? FILE_COMMON : 0;
|
|
|
|
// Verifica que el archivo exista
|
|
if(!FileIsExist(fileName, flags))
|
|
{
|
|
printf("%s:: El archivo %s no existe", __FUNCTION__, fileName);
|
|
return false; // Sale de la función si el archivo no existe
|
|
}
|
|
|
|
flags = !common_flag ? (FILE_READ | FILE_CSV) : (FILE_READ | FILE_CSV | FILE_COMMON);
|
|
|
|
ResetLastError();
|
|
// Abre el archivo en modo lectura
|
|
const int fileHandle = FileOpen(fileName, flags, "\n", code_page);
|
|
if(fileHandle == INVALID_HANDLE)
|
|
{
|
|
Print(__FUNCTION__, ":: Error al abrir el archivo: ", fileName, " | ultimo error: ", GetLastError());
|
|
return false; // Sale de la función si no se puede abrir el archivo
|
|
}
|
|
|
|
// Lee el archivo línea por línea
|
|
while(!FileIsEnding(fileHandle))
|
|
{
|
|
const string line = FileReadString(fileHandle);
|
|
if(StringLen(line) > 0)
|
|
{
|
|
|
|
ArrayResize(file.data, file.data.Size() + 1);
|
|
string linea[];
|
|
StringSplit(line, line_separator, linea);
|
|
|
|
ArrayResize(file.data[file.data.Size() - 1].datos, linea.Size());
|
|
|
|
for(int i = 0; i < ArraySize(linea) ; i++)
|
|
file.data[file.data.Size() - 1].datos[i] = linea[i];
|
|
|
|
}
|
|
}
|
|
|
|
// Cierra el archivo
|
|
printf("%s:: Exito al cargar el archivo %s, numero de filas %d", __FUNCTION__, fileName, ArraySize(file.data));
|
|
FileClose(fileHandle);
|
|
return true;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
string StringTrim(const string text)
|
|
{
|
|
int start = 0;
|
|
int end = StringLen(text) - 1;
|
|
|
|
while(start <= end && StringGetCharacter(text, start) <= ' ')
|
|
start++;
|
|
|
|
while(end >= start && StringGetCharacter(text, end) <= ' ')
|
|
end--;
|
|
|
|
if(start > end)
|
|
return "";
|
|
|
|
return StringSubstr(text, start, end - start + 1);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
string vector_to_string(const vector &v, string separator = ",")
|
|
{
|
|
string vector_str = "";
|
|
ulong length = v.Size();
|
|
|
|
for(ulong i = 0; i < length; i++)
|
|
vector_str += DoubleToString(v[i], 14) + (i == length - 1 ? "" : separator);
|
|
|
|
return vector_str;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
vector string_to_vector(const string str, ushort separator = ',')
|
|
{
|
|
string valores_linea[];
|
|
StringSplit(str, separator, valores_linea);
|
|
int num_valores = ArraySize(valores_linea);
|
|
|
|
vector v(num_valores);
|
|
|
|
for(int i = 0; i < num_valores; i++)
|
|
v[i] = StringToDouble(valores_linea[i]);
|
|
|
|
return v;
|
|
|
|
|
|
}
|
|
|
|
//---
|
|
// Convierte un CSV en una matriz, opcionalmente saltando la cabecera
|
|
bool CSVToMatrix(string fileName,
|
|
matrix& out_mtx,
|
|
bool common_flag,
|
|
bool file_have_header,
|
|
ushort line_separator,
|
|
string &out_header)
|
|
{
|
|
// Limpia el array existente
|
|
out_mtx.Resize(0, 0);
|
|
|
|
// Verifica que el archivo exista
|
|
int flags = common_flag ? FILE_COMMON : 0;
|
|
if(!FileIsExist(fileName, flags))
|
|
{
|
|
Print(__FUNCTION__, ":: El archivo ", fileName, " no existe");
|
|
return false;
|
|
}
|
|
|
|
ResetLastError();
|
|
// Abre el archivo en modo lectura CSV
|
|
flags = common_flag == false ? (FILE_READ | FILE_CSV) : (FILE_READ | FILE_CSV | FILE_COMMON);
|
|
int fileHandle = FileOpen(fileName, flags, "\n");
|
|
if(fileHandle == INVALID_HANDLE)
|
|
{
|
|
Print(__FUNCTION__, ":: Error al abrir el archivo: ", fileName, " | ultimo error: ", GetLastError());
|
|
return false;
|
|
}
|
|
|
|
// Si hay cabecera y no estamos al final, la leemos y descartamos
|
|
if(file_have_header && !FileIsEnding(fileHandle))
|
|
{
|
|
out_header =FileReadString(fileHandle);
|
|
}
|
|
|
|
int cols = 0;
|
|
|
|
// Lee el resto del archivo línea por línea
|
|
while(!FileIsEnding(fileHandle))
|
|
{
|
|
string line = FileReadString(fileHandle);
|
|
if(StringLen(line) == 0) // omite líneas vacías
|
|
continue;
|
|
|
|
// Añade una nueva fila a out_mtx
|
|
out_mtx.Resize(out_mtx.Rows() + 1, out_mtx.Cols());
|
|
int row = (int)out_mtx.Rows() - 1;
|
|
|
|
// Divide la línea según el separador
|
|
string fields[];
|
|
StringSplit(line, line_separator, fields);
|
|
|
|
|
|
// Ajusta el número de columnas y asigna los valores
|
|
if(cols == 0)
|
|
{
|
|
out_mtx.Resize(out_mtx.Rows(), ArraySize(fields));
|
|
cols = ArraySize(fields);
|
|
}
|
|
|
|
vector v(ArraySize(fields));
|
|
|
|
if(v.Size() != cols)
|
|
{
|
|
printf("%s: Error critico la linea %s\n Es invalida el numero de columnas de esa fila es diferente a %I32d", __FUNCTION__, line, cols);
|
|
continue;
|
|
}
|
|
|
|
for(int i = 0; i < ArraySize(fields); i++)
|
|
v[i] = StringToDouble(fields[i]);
|
|
|
|
|
|
out_mtx.Row(v, row);
|
|
}
|
|
|
|
// Cierra el archivo y retorna éxito
|
|
FileClose(fileHandle);
|
|
return true;
|
|
}
|
|
|
|
bool MatrixToCSV(string fileName,
|
|
matrix &mtx,
|
|
bool common_flag,
|
|
string header,
|
|
ushort line_separator = ',')
|
|
{
|
|
int flags = FILE_WRITE | FILE_CSV;
|
|
if(common_flag)
|
|
flags |= FILE_COMMON;
|
|
|
|
// Abrir el archivo
|
|
int file = FileOpen(fileName, flags, "\n");
|
|
if(file == INVALID_HANDLE)
|
|
{
|
|
Print(__FUNCTION__, " Error al abrir el archivo CSV: ", fileName);
|
|
return false;
|
|
}
|
|
|
|
// Escribir encabezado si se proporciona
|
|
if(StringLen(header) > 0)
|
|
FileWriteString(file, header + "\n");
|
|
|
|
// Obtener dimensiones
|
|
int rows = (int)mtx.Rows();
|
|
int cols = (int)mtx.Cols();
|
|
|
|
// Escribir los datos
|
|
for(int i = 0; i < rows; i++)
|
|
{
|
|
string line = "";
|
|
for(int j = 0; j < cols; j++)
|
|
{
|
|
if(j > 0) line += ShortToString(line_separator);
|
|
line += DoubleToString(mtx[i][j], 8);
|
|
}
|
|
FileWriteString(file, line + "\n");
|
|
}
|
|
|
|
FileClose(file);
|
|
Print(__FUNCTION__, " Exportación completada: ", fileName);
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Extrae columnas especificadas de una matriz |
|
|
//+------------------------------------------------------------------+
|
|
matrix ExtraerMaxtriDeMatrix(const matrix &m, ulong start_col, ulong end_col)
|
|
{
|
|
matrix out = { };
|
|
|
|
// Verifica rangos válidos
|
|
if(start_col < 0 || end_col >= m.Cols() || start_col > end_col)
|
|
{
|
|
Print(__FUNCTION__, " Error: índices de columna inválidos.");
|
|
return m; // retorna matriz vacía
|
|
}
|
|
|
|
// Número de filas y columnas que tendrá la nueva matriz
|
|
ulong rows = m.Rows();
|
|
printf("%s | Numero de columnas totales %I64u | Start %I64u | End %I64u", __FUNCTION__, m.Cols(), start_col, end_col);
|
|
|
|
// Copia los datos desde la matriz original a la matriz resultado
|
|
for(ulong i = start_col ; i <= end_col; i++)
|
|
{
|
|
out.Resize(rows, out.Cols() + 1);
|
|
vector c = m.Col(i);
|
|
out.Col(c, out.Cols() - 1);
|
|
}
|
|
|
|
return out;
|
|
}
|
|
//+------------------------------------------------------------------+
|