MQLArticles/Utils/ExtraFunctions.mqh

228 lines
8.4 KiB
MQL5
Raw Permalink Normal View History

2026-03-09 16:35:08 -05:00
//+------------------------------------------------------------------+
//| 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"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void TerminalAutoTrading(bool enable)
{
//---
const bool e = (bool)TerminalInfoInteger(TERMINAL_TRADE_ALLOWED);
if(e == enable)
return;
//---
HANDLE hwnd = MTTESTER::GetTerminalHandle();
if(!hwnd)
return;
//---
user32::SetForegroundWindow(hwnd);
Sleep(50);
//---
user32::keybd_event(0x11, 0, 0, 0);
user32::keybd_event(0x45, 0, 0, 0);
user32::keybd_event(0x45, 0, 2, 0);
user32::keybd_event(0x11, 0, 2, 0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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", TerminalInfoString(TERMINAL_DATA_PATH), 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", TerminalInfoString(TERMINAL_DATA_PATH), 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;
}
}
}
//+------------------------------------------------------------------+
#endif // MQLARTICLES_UTILS_EXTRAFUNCTIONS_MQH