forked from nique_372/MQLArticles
283 lines
10 KiB
MQL5
283 lines
10 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| ExtraFunctions.mqh |
| |
//| Copyright 2025, Niquel Mendoza. |
| |
//| https://www.mql5.com/es/users/nique_372 |
| |
//+------------------------------------------------------------------+
| |
#property copyright "Copyright 2025, Niquel Mendoza."
| |
#property link "https://www.mql5.com/es/users/nique_372"
| |
#property strict
| |
| |
#ifndef MQLARTICLES_UTILS_EXTRAFUNCTIONS_MQH
| |
#define MQLARTICLES_UTILS_EXTRAFUNCTIONS_MQH
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
#include "..\\..\\ExtraCodes\\MultiTester\\MTTester.mqh"
| |
#include "Basic.mqh"
| |
#include "File.mqh"
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
void ExtractLogLinesAsArray(const datetime log_file_date, const datetime start_dt, const datetime end_dt, string& arr_lines[])
| |
{
| |
//--- Path al log de hoy
| |
static MqlDateTime dt;
| |
CTimeUtils::TimeToStructFast(log_file_date, dt);
| |
const string log_file_path = StringFormat("%s\\MQL5\\Logs\\%04d%02d%02d.log", TERMINAL_MT5_DATA_PAH, dt.year, dt.mon, dt.day);
| |
| |
//--- Abrimos via WinAPI
| |
const HANDLE h = kernel32::CreateFileW(log_file_path,
| |
0x80000000, // GENERIC_READ
| |
0x00000001 | 0x00000002, // FILE_SHARE_READ | FILE_SHARE_WRITE
| |
NULL,
| |
3, // OPEN_EXISTING
| |
0x80, // FILE_ATTRIBUTE_NORMAL
| |
0);
| |
if(h == -1)
| |
{
| |
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("No se pudo abrir el archivo, error=%d, file:\n%s", kernel32::GetLastError(), log_file_path));
| |
return;
| |
}
| |
| |
//--- Tamanio
| |
long file_size = 0;
| |
if(!kernel32::GetFileSizeEx(h, file_size) || file_size <= 2)
| |
{
| |
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("Archivo vacio o fallo GetFileSizeEx | error=%d", kernel32::GetLastError()));
| |
kernel32::CloseHandle(h);
| |
return;
| |
}
| |
| |
//--- Leemos
| |
const uint num_shorts = uint(file_size >> 1);
| |
ushort buffer[];
| |
ArrayResize(buffer, num_shorts);
| |
uint bytes_read = 0;
| |
OVERLAPPED ov = {};
| |
if(!kernel32::ReadFile(h, buffer, (uint)file_size, bytes_read, ov))
| |
{
| |
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("kernel32::ReadFile | error=%d", kernel32::GetLastError()));
| |
kernel32::CloseHandle(h);
| |
return;
| |
}
| |
kernel32::CloseHandle(h);
| |
| |
//--- Convertimos saltando BOM
| |
const string content = ShortArrayToString(buffer, 1);
| |
string lines[];
| |
const int total_lines = StringSplit(content, '\n', lines);
| |
ArrayResize(arr_lines, total_lines); // Valor inicial
| |
int t = 0;
| |
| |
//--- Segundos del dia para comparar
| |
static MqlDateTime s_dt;
| |
static MqlDateTime e_dt;
| |
CTimeUtils::TimeToStructFast(start_dt, s_dt);
| |
CTimeUtils::TimeToStructFast(end_dt, e_dt);
| |
const int start_secs = s_dt.hour * 3600 + s_dt.min * 60 + s_dt.sec;
| |
const int end_secs = e_dt.hour * 3600 + e_dt.min * 60 + e_dt.sec;
| |
| |
//--- Iteramos y filtramos
| |
int found = 0;
| |
for(int i = 0; i < total_lines; i++)
| |
{
| |
if(StringLen(lines[i]) < 10) // No cumple a cer candidado
| |
continue;
| |
| |
//--- Buscamos el timestamp dinamicamente por el primer ':'
| |
const int colon_pos = StringFind(lines[i], ":");
| |
if(colon_pos < 2) // Minimo se reuqiere el 2 por el (HH)
| |
continue;
| |
| |
//--- Extraemos HH:MM:SS
| |
const string ts = StringSubstr(lines[i], colon_pos - 2, 8);
| |
const int hh = int(StringSubstr(ts, 0, 2));
| |
const int mm = int(StringSubstr(ts, 3, 2));
| |
const int ss = int(StringSubstr(ts, 6, 2));
| |
const int secs = hh * 3600 + mm * 60 + ss;
| |
| |
//---
| |
if(secs >= start_secs && secs <= end_secs)
| |
{
| |
arr_lines[t++] = lines[i];
| |
}
| |
}
| |
| |
//---
| |
ArrayResize(arr_lines, t);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
void ExtractLogLinesAsStr(const datetime log_file_date, const datetime start_dt, const datetime end_dt, string& str, string sep = "\n")
| |
{
| |
//--- Path al log de hoy
| |
static MqlDateTime dt;
| |
CTimeUtils::TimeToStructFast(log_file_date, dt);
| |
const string log_file_path = StringFormat("%s\\MQL5\\Logs\\%04d%02d%02d.log", TERMINAL_MT5_DATA_PAH, dt.year, dt.mon, dt.day);
| |
| |
//--- Abrimos via WinAPI
| |
const HANDLE h = kernel32::CreateFileW(log_file_path,
| |
0x80000000, // GENERIC_READ
| |
0x00000001 | 0x00000002, // FILE_SHARE_READ | FILE_SHARE_WRITE
| |
NULL,
| |
3, // OPEN_EXISTING
| |
0x80, // FILE_ATTRIBUTE_NORMAL
| |
0);
| |
if(h == -1)
| |
{
| |
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("No se pudo abrir el archivo, error=%d, file:\n%s", kernel32::GetLastError(), log_file_path));
| |
return;
| |
}
| |
| |
//--- Tamanio
| |
long file_size = 0;
| |
if(!kernel32::GetFileSizeEx(h, file_size) || file_size <= 2)
| |
{
| |
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("Archivo vacio o fallo GetFileSizeEx | error=%d", kernel32::GetLastError()));
| |
kernel32::CloseHandle(h);
| |
return;
| |
}
| |
| |
//--- Leemos
| |
const uint num_shorts = uint(file_size >> 1);
| |
ushort buffer[];
| |
ArrayResize(buffer, num_shorts);
| |
uint bytes_read = 0;
| |
OVERLAPPED ov = {};
| |
if(!kernel32::ReadFile(h, buffer, (uint)file_size, bytes_read, ov))
| |
{
| |
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("kernel32::ReadFile | error=%d", kernel32::GetLastError()));
| |
kernel32::CloseHandle(h);
| |
return;
| |
}
| |
kernel32::CloseHandle(h);
| |
| |
//--- Convertimos saltando BOM
| |
const string content = ShortArrayToString(buffer, 1);
| |
string lines[];
| |
const int total_lines = StringSplit(content, '\n', lines);
| |
str = "";
| |
| |
//--- Segundos del dia para comparar
| |
static MqlDateTime s_dt;
| |
static MqlDateTime e_dt;
| |
CTimeUtils::TimeToStructFast(start_dt, s_dt);
| |
CTimeUtils::TimeToStructFast(end_dt, e_dt);
| |
const int start_secs = s_dt.hour * 3600 + s_dt.min * 60 + s_dt.sec;
| |
const int end_secs = e_dt.hour * 3600 + e_dt.min * 60 + e_dt.sec;
| |
| |
//--- Iteramos y filtramos
| |
int found = 0;
| |
for(int i = 0; i < total_lines; i++)
| |
{
| |
if(StringLen(lines[i]) < 10) // No cumple a cer candidado
| |
continue;
| |
| |
//--- Buscamos el timestamp dinamicamente por el primer ':'
| |
const int colon_pos = StringFind(lines[i], ":");
| |
if(colon_pos < 2) // Minimo se reuqiere el 2 por el (HH)
| |
continue;
| |
| |
//--- Extraemos HH:MM:SS
| |
const string ts = StringSubstr(lines[i], colon_pos - 2, 8);
| |
const int hh = int(StringSubstr(ts, 0, 2));
| |
const int mm = int(StringSubstr(ts, 3, 2));
| |
const int ss = int(StringSubstr(ts, 6, 2));
| |
const int secs = hh * 3600 + mm * 60 + ss;
| |
| |
//---
| |
if(secs >= start_secs && secs <= end_secs)
| |
{
| |
str += lines[i] + sep;
| |
}
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
void ExtractLastLogLines(const datetime log_file_date, const int num_lines, string& str, string sep = "\n")
| |
{
| |
//---
| |
static MqlDateTime dt;
| |
CTimeUtils::TimeToStructFast(log_file_date, dt);
| |
const string log_file_path = StringFormat("%s\\MQL5\\Logs\\%04d%02d%02d.log", TERMINAL_MT5_DATA_PAH, dt.year, dt.mon, dt.day);
| |
| |
//---
| |
const HANDLE h = kernel32::CreateFileW(log_file_path,
| |
0x80000000,
| |
0x00000001 | 0x00000002,
| |
NULL,
| |
3,
| |
0x80,
| |
0);
| |
if(h == -1)
| |
{
| |
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("No se pudo abrir el archivo, error=%d, file:\n%s", kernel32::GetLastError(), log_file_path));
| |
return;
| |
}
| |
| |
//---
| |
long file_size = 0;
| |
if(!kernel32::GetFileSizeEx(h, file_size) || file_size <= 2)
| |
{
| |
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("Archivo vacio o fallo GetFileSizeEx | error=%d", kernel32::GetLastError()));
| |
kernel32::CloseHandle(h);
| |
return;
| |
}
| |
| |
//---
| |
const uint num_shorts = uint(file_size >> 1);
| |
ushort buffer[];
| |
ArrayResize(buffer, num_shorts);
| |
uint bytes_read = 0;
| |
OVERLAPPED ov = {};
| |
if(!kernel32::ReadFile(h, buffer, (uint)file_size, bytes_read, ov))
| |
{
| |
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("kernel32::ReadFile | error=%d", kernel32::GetLastError()));
| |
kernel32::CloseHandle(h);
| |
return;
| |
}
| |
kernel32::CloseHandle(h);
| |
| |
//---
| |
const string content = ShortArrayToString(buffer, 1);
| |
string lines[];
| |
const int total_lines = StringSplit(content, '\n', lines);
| |
| |
//---
| |
const int count = MathMin(num_lines, total_lines);
| |
const int start = MathMax(0, total_lines - count);
| |
str = "";
| |
| |
//---
| |
for(int i = start; i < total_lines; i++)
| |
{
| |
if(StringLen(lines[i]) < 10)
| |
continue;
| |
str += lines[i] + sep;
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
void CloseAllChartsExceptChart(const long chart_no_close)
| |
{
| |
long chart_id = ::ChartFirst();
| |
while(chart_id != -1)
| |
{
| |
const long next = ::ChartNext(chart_id);
| |
if(chart_id != chart_no_close)
| |
::ChartClose(chart_id);
| |
chart_id = next;
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
#endif // MQLARTICLES_UTILS_EXTRAFUNCTIONS_MQH
|