AiDataGenByLeo/GenericData/Base/Base.mqh

402 lines
25 KiB
MQL5
Raw Permalink Normal View History

2026-02-04 12:01:29 -05:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| Base.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
2026-02-05 11:53:16 -05:00
#ifndef AIDATAGENBYLEO_GENERIC_DATA_BASE_BASE_MQH
#define AIDATAGENBYLEO_GENERIC_DATA_BASE_BASE_MQH
2026-02-04 12:01:29 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#include "..\\..\\..\\MQLArticles\\Utils\\Basic.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
struct AiDataByLeoDataParamsParser
{
//--- Variables
// Parametros
string parameters[]; // Parametros
//---
AiDataByLeoDataParamsParser(int total_parameteres, const string& config, ushort param_sep = '|')
{
//---
if(total_parameteres <= 0)
return;
//---
// En caso solo haya 2 lineas pero hay parametros ya que de feura de rango
if(StringSplit(config, param_sep, parameters) != total_parameteres)
{
FastLog(FUNCION_ACTUAL, ERROR_TEXT, "Los parametros no tienen el mismo tama<00>o");
Remover();
return;
}
//---
for(int i = 0; i < total_parameteres; i++)
{
const int k = parameters[i].Find("=");
if(k >= 0)
parameters[i] = StringSubstr(parameters[i], k + 1);
else // Fatal
{
FastLog(FUNCION_ACTUAL, FATAL_ERROR_TEXT, "No se encontro el = ");
Remover();
}
}
}
//--- Leer
// Todo tipo de numero real o entero
template <typename T>
__forceinline T ReadNumber(const int index) { return (T)parameters[index]; }
// Timeframe de manera facil soporta M1, ....., H1....... D1, W1, para current se puede usar cualquier letra Current etc
ENUM_TIMEFRAMES ReadTimeframe(const int index)
{
//---
const uint len = parameters[index].Length();
const ushort first = parameters[index][0];
//---
if(first == 'M')
{
if(len == 2)
{
const int n = (parameters[index][1] - 48);
return (n < 1 || n > 6) ? _Period : ENUM_TIMEFRAMES(n);
}
else
if(len == 3)
{
if(parameters[index][1] == 'N') // MN
return PERIOD_MN1;
const int n = ((parameters[index][1] - '0') * 10 + (parameters[index][2] - '0'));
return (n == 10 || n == 12 || n == 15 || n == 20 || n == 30) ? ENUM_TIMEFRAMES(n) : _Period;
}
}
else
if(first == 'H')
{
const int n = ((len == 2) ? parameters[index][1] - '0' : (parameters[index][1] - '0') * 10 + (parameters[index][2] - '0'));
// Bitmask: 0001000101011110 = 0x115E
// Bits: [12][8][6][4][3][2][1] = v<EFBFBD>lidos
// Aqui lo que hamos es desplazar a la derecha y el primer bit debe de ser 1.. si se da u numero que no es..
// entonces el desplazamieot daria ene l bit 1 0 por lo que esto daria error
return (n < 13 && bool((0x115E >> n) & 1)) ? ENUM_TIMEFRAMES(16384 + n) : _Period;
}
else
if(first == 'D')
return PERIOD_D1;
else
if(first == 'W')
return PERIOD_W1;
//--- Cualquier otro caso Current
return _Period;
}
// Booleanos
__forceinline bool ReadBool(const int index)
{
const string val = parameters[index];
return (int(val) == 1 || val == "true" || val == "True" || val == "TRUE");
}
// Read string.. sin espacios 100% seguro
__forceinline string ReadStr(const int index) const
{
StringTrimLeft(parameters[index]);
StringTrimRight(parameters[index]);
return parameters[index];
}
//---
// Read number array
// " [10, 20, 30]"
template <typename T>
int ReadNumberArray(const int index, T& out[], const ushort& sep, int reserve = 0) const
{
//---
int pos = 0;
const int lenght = StringLen(parameters[index]);
ArrayResize(out, 0, reserve);
//---
while(parameters[index][pos] != '[')
{
if(++pos > lenght)
{
// No se encontro
return 0;
}
}
int start = pos + 1;
//---
while(parameters[index][pos] != ']')
{
if(++pos > lenght)
{
// No se encontro
return 0;
}
}
2026-02-05 08:18:56 -05:00
int end = pos-1;
2026-02-04 12:01:29 -05:00
//---
string arr[];
const int t = StringSplit(StringSubstrRange(parameters[index], start, end), sep, arr);
if(t == -1)
{
return 0;
}
else
{
ArrayResize(out, t, reserve);
2026-02-05 08:18:56 -05:00
for(int i = 0; i < t; i++)
2026-02-04 12:01:29 -05:00
{
out[i] = T(arr[i]);
}
//---
return t;
}
}
// Read String array
int ReadStringArray(const int index, string& out[], const ushort& sep, int reserve = 0) const
{
//---
int pos = 0;
const int lenght = StringLen(parameters[index]);
ArrayResize(out, 0, reserve);
//---
while(parameters[index][pos] != '[')
{
if(++pos > lenght)
{
// No se encontro
return 0;
}
}
int start = pos + 1;
//---
while(parameters[index][pos] != ']')
{
if(++pos > lenght)
{
// No se encontro
return 0;
}
}
2026-02-05 08:18:56 -05:00
int end =pos -1;
2026-02-04 12:01:29 -05:00
//---
const int t = StringSplit(StringSubstrRange(parameters[index], start, end), sep, out);
if(t == -1)
{
return 0;
}
else
return t;
}
};
//---
AiDataByLeoDataParamsParser EMPTY_AIDATABYLEO_DATA_PARSER(0, EMPTY_STRING);
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
// Nota importante por defecto se heredara de CAllClassEventsBasic, teniendo como eventos los basicos
// Si por alguna razon se requirere otros eventos como noticias etc.. entonces usetd puede definir AIDATA_LEO_FEATURE_FIRST
// Y como valor ponerle la clase "intermedia" para eventos de noticias (todas deberan de herad siempre de CAllClassEventsBasic)
// #define AIDATA_LEO_FEATURE_FIRST
//---
#ifdef AIDATA_LEO_FEATURE_FIRST
class CAiDataLeoFeature : public AIDATA_LEO_FEATURE_FIRST
#else
class CAiDataLeoFeature : public CAllClassEventsBasic
#endif
{
protected:
//--- Del modelo
2026-02-05 08:18:56 -05:00
string m_name; // Nombre del feature
string m_prefix; // Prefijo
const bool m_support_idx; // Soporta Idx?
bool m_init; // Bandera de inicialzacion
const int m_parameters_size; // Numero de parametros
int m_idx_arr_size; // Tama<EFBFBD>o de indices a generar
int m_idx_arr[]; // Array con los indices a generar
int m_idx_max; // Maximo valor idx
vector m_v; // Vector cache
vector m_extra_v; // Vector de tama<EFBFBD>o extra
const bool m_use_on_new_bar_m1; // Use OnNewBarM1
2026-02-04 12:01:29 -05:00
private:
//--- Especificos para matrix
ulong m_start_col;
ulong m_start_row;
ulong m_end_row;
protected:
//---
virtual bool OnInitEvent(AiDataByLeoDataParamsParser& config) = 0;
public:
//---
2026-02-14 20:47:37 -05:00
CAiDataLeoFeature(const int params_num, const string& name, const bool support_idx, const bool use_m1);
2026-02-06 08:18:57 -05:00
~CAiDataLeoFeature() {}
2026-02-04 12:01:29 -05:00
//--- Incializacion
bool Initialize(const string& parameters, int& idx_arr[]);
2026-02-14 20:47:37 -05:00
bool Initialize(const string& parameters, const int idx);
2026-02-04 12:01:29 -05:00
//--- Extra
void SetExtra(ulong start_col, ulong start_row, ulong end_row);
__forceinline ulong MtxStartCol() const { return m_start_col; }
__forceinline ulong MtxStartRow() const { return m_start_row; }
__forceinline ulong MtxEndRow() const { return m_end_row; }
//---
2026-02-05 08:18:56 -05:00
// Antencion amabas funciones tienen la misma firma esto debido a que se quiere aprovechar dos cossas
// Por un lado en OnNewBar para concpetos ICT, y por otro lado GetValue para indicadores...
2026-02-14 20:47:37 -05:00
virtual void OnNewBarM1(const datetime curr_time, const double bid, const double ask) {}
2026-02-04 12:01:29 -05:00
//--- Funcion principal
2026-02-14 20:47:37 -05:00
virtual vector GetValue(const datetime curr_time, const double bid, const double ask) { return m_v; } // Obtener vector
2026-02-04 12:01:29 -05:00
//--- Prefix
void Prefix(const string& new_value) { m_prefix = new_value; }
//---
string Summary() const;
//--- Getters
// Names
__forceinline string RealName() const { return m_name; }
__forceinline string FullName() const { return (m_name + m_prefix); }
__forceinline string Prefix() const { return m_prefix; }
// Extra
__forceinline bool SupportIdx() const { return m_support_idx; }
__forceinline int ParametersTotal() const { return m_parameters_size; }
2026-02-05 17:46:37 -05:00
__forceinline bool UseOnNewBarM1() const { return m_use_on_new_bar_m1; }
2026-02-04 12:01:29 -05:00
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-02-14 20:47:37 -05:00
CAiDataLeoFeature::CAiDataLeoFeature(const int params_num, const string& name, const bool support_idx, const bool use_m1)
2026-02-05 08:18:56 -05:00
: m_init(false), m_parameters_size(params_num), m_name(name), m_support_idx(support_idx), m_prefix(NULL), m_use_on_new_bar_m1(use_m1)
2026-02-04 12:01:29 -05:00
{
m_idx_arr_size = ArrayResize(m_idx_arr, 0);
}
//+------------------------------------------------------------------+
bool CAiDataLeoFeature::Initialize(const string &parameters, int& idx_arr[])
{
//---
if(m_init)
{
LogWarning("Clase ya inciada", FUNCION_ACTUAL);
return false;
}
//---
if(m_parameters_size > 0)
{
AiDataByLeoDataParamsParser config(m_parameters_size, parameters);
m_init = OnInitEvent(config);
}
else
{
m_init = OnInitEvent(EMPTY_AIDATABYLEO_DATA_PARSER);
}
//---
m_idx_arr_size = ArrayCopy(m_idx_arr, idx_arr);
m_v.Resize(ulong(m_idx_arr_size)); // El tama<EFBFBD>o de idx arr
m_idx_max = m_idx_arr[ArrayMaximum(m_idx_arr)];
2026-02-04 16:13:10 -05:00
2026-02-04 12:01:29 -05:00
//---
return m_init;
}
//+------------------------------------------------------------------+
2026-02-14 20:47:37 -05:00
bool CAiDataLeoFeature::Initialize(const string &parameters, const int idx)
2026-02-04 12:01:29 -05:00
{
//---
if(m_init)
{
LogWarning("Clase ya inciada", FUNCION_ACTUAL);
return false;
}
//---
if(m_parameters_size > 0)
{
AiDataByLeoDataParamsParser config(m_parameters_size, parameters);
m_init = OnInitEvent(config);
}
else
{
m_init = OnInitEvent(EMPTY_AIDATABYLEO_DATA_PARSER);
}
//---
m_idx_arr[ArrayResize(m_idx_arr, (m_idx_arr_size = 1)) - 1] = idx;
m_v.Resize(ulong(m_idx_arr_size)); // El tama<EFBFBD>o de idx arr
m_idx_max = m_idx_arr[0];
//---
return m_init;
}
//+------------------------------------------------------------------+
void CAiDataLeoFeature::SetExtra(ulong start_col, ulong start_row, ulong end_row)
{
m_start_col = start_col;
m_start_row = start_row;
m_end_row = end_row;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
string CAiDataLeoFeature::Summary(void) const
{
//---
string str = "";
for(int i = 0; i < m_idx_arr_size; i++)
{
str += string(m_idx_arr[i]) + ", ";
}
StringSetLength(str, str.Length() - 2);
//---
return StringFormat("[%s][%s](..)\n[Col=%I64u][Rows: %I64u -> %I64u] Indexes:\n[%s]", m_name, m_prefix, m_start_col, m_start_row, m_end_row, str);
}
//+------------------------------------------------------------------+
2026-02-05 11:53:16 -05:00
#endif // AIDATAGENBYLEO_GENERIC_DATA_BASE_BASE_MQH
2026-02-04 12:01:29 -05:00