WorkflowsByLeo/Src/Steps/RunEA.mqh
Nique_372 270de4275a
2026-04-09 06:52:25 -05:00

211 lines
6.5 KiB
MQL5

//+------------------------------------------------------------------+
//| RunEA.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 WORKFLOWSBYLEO_STEPS_RUNEA_MQH
#define WORKFLOWSBYLEO_STEPS_RUNEA_MQH
//+------------------------------------------------------------------+
//| Include |
//+------------------------------------------------------------------+
#include <TSN\\ExtraCodes\\Expert.mqh>
#include <TSN\\MQLArticles\\Utils\\File.mqh>
#include "..\\Final\\Orquestador.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CWorkStepGenericRunEa : public CWorkflowStep
{
private:
MqlParam m_ea_params[];
const long m_current_chart_id;
ENUM_TIMEFRAMES m_timeframe;
string m_symbol;
uint8_t m_flags;
int m_timeout_segundos;
int m_ms_sincronizar;
string m_expert_name;
public:
CWorkStepGenericRunEa(void) : CWorkflowStep("RunEA", "Generic", false, 0), m_current_chart_id(ChartID()) {}
~CWorkStepGenericRunEa(void) {}
//---
bool Init(const CYmlNode& parameters) override final;
int Run() override final;
};
//---
WORKFLOWS_FACTORY_DEFINE_CREATOR(CWorkStepGenericRunEa, GenericRunEa, "RunEA", "Generic")
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#define WORFFLOWSTEP_GENERIC_RUNEA_IDX_EXPERT (0)
#define WORFFLOWSTEP_GENERIC_RUNEA_IDX_SIMOLO (1)
#define WORFFLOWSTEP_GENERIC_RUNEA_IDX_TIMEFRAME (2)
//---
bool CWorkStepGenericRunEa::Init(const CYmlNode &parameters)
{
//--- Parametros fijos
CYmlNode fixed = parameters["fixed"];
if(fixed.Size() < 2)
{
LogError("Como minimo se requiere 1 parametro, en el se ubica el nombre del expert relativo a MQL5\\", FUNCION_ACTUAL);
return false;
}
// Reserve
ArrayResize(m_ea_params, 1);
// EA Name
if(!m_wf.AssingMqlParam(m_ea_params[0], fixed["name"], TYPE_STRING))
{
LogError("No se pudo asignar el nombre del ea", FUNCION_ACTUAL);
return false;
}
m_expert_name = FileRemoveExtensionNoRef(GetPureFileName(m_ea_params[0].string_value));
// Symbol
m_symbol = m_wf.TranslateStr(fixed["symbol"], "_Symbol");
if(m_symbol == "_Symbol")
m_symbol = _Symbol;
// Timeframe
m_timeframe = m_wf.TranslateEnum<ENUM_TIMEFRAMES>(fixed["timeframe"], "_Period");
//Print(EnumToString(m_timeframe));
// Flags
m_flags = EXPERT::FlagsPermisosStrToFlags(m_wf.TranslateStr(fixed["run_flags"], ""), '|');
//Print(m_flags);
// MS sincronizacion
m_ms_sincronizar = m_wf.TranslateNumber<int>(fixed["ms_sincronizacion"], "1000");
// Timeout
m_timeout_segundos = m_wf.TranslateNumber<int>(fixed["timeout_segundos"], "0");
if(m_timeout_segundos == 0)
{
LogError("Timeout no valido, debe de ser mayor a 0", FUNCION_ACTUAL);
return false;
}
//--- Parametros dinamicos Array
int k = 1;
CYmlNode ea_parameters_node = parameters["ea_params"];
ArrayResize(m_ea_params, (1 + ea_parameters_node.Size()));
CYmlIteratorArray it = ea_parameters_node.BeginArr();
// Print(ArraySize(m_ea_params) - 1);
//---
// los 3 primeros parametros
while(it.IsValid())
{
//---
CYmlNode parametro = it.Val();
//--- Objeto (implicito)
if(parametro.IsObject())
{
//---
// Movemos al key
// (no use next tokens por que quiero moverme posiciones)
// si uso next token me muevo hacia el siguinete obj (se salta todo el obj)
if(!parametro.MoveNextPositionsThis(1)) // [OBJ] -> [KEY base] (End se conserva)
{
LogError("Se intento mover al siguiente key pero no se pudo revise la sintazxis del yml", FUNCION_ACTUAL);
return false;
}
// Saltamos a val
// false dado que perdimos el contexto en
if(!parametro.MoveToNextToken()) // [KEYBASE][KEYINFO] a [ARR]
{
// Print(parametro.m_idx);
// Print(parametro.m_end);
//Print(EnumToString(parametro.GetType()));
LogError("Se intento mover al siguiente valor pero no se pudo revise la sintazxis del yml", FUNCION_ACTUAL);
return false;
}
}
// else: arr
//--- Asignamos
// [TYPE, VALOR]
//Print(parametro.Size());
if(!m_wf.AssingMqlParam(m_ea_params[k++], parametro.At(1), parametro.At(0).ToString())) // 1 = valor | 0 = tipo
{
ArrayResize(m_ea_params, 0); // En caso de ejeuccino dara fallo
LogError(StringFormat("Fallo al asingnar el valor al parametro, posible = %s tipo invalido", EnumToString(parametro.GetType())), FUNCION_ACTUAL);
return false;
}
// Print(EnumToString(m_ea_params[k - 1].type));
//---
it.Next();
}
//---
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int CWorkStepGenericRunEa::Run(void)
{
//---
const long chart_id = OpenChartAndDevoler(m_current_chart_id, m_symbol, m_timeframe, m_ms_sincronizar);
//---
if(chart_id == -1)
{
LogError("No se pudo abrir un grafico", FUNCION_ACTUAL);
return 1;
}
//--- Lanza el EA
if(!EXPERT::Run(chart_id, m_ea_params, m_flags))
{
LogError("Fallo al ejecutar ea", FUNCION_ACTUAL);
ArrayPrint(m_ea_params);
//Print(TYPE_STRING);
::ChartClose(chart_id);
return 1;
}
//---
int c = 0;
bool is_t = false;
while(ChartGetString(chart_id, CHART_EXPERT_NAME) == m_expert_name)
{
Sleep(500);
if((++c >> 1) >= m_timeout_segundos)
{
is_t = true;
break;
}
}
//---
::ChartClose(chart_id);
//---
if(is_t)
{
LogError(StringFormat("Ejecucion del EA %s, supero el timeout", m_expert_name), FUNCION_ACTUAL);
}
//---
return is_t;
}
//+------------------------------------------------------------------+
#endif // WORKFLOWSBYLEO_STEPS_RUNEA_MQH