forked from nique_372/AiDataTaskRuner
145 lines
5.3 KiB
MQL5
145 lines
5.3 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| TrainingLauncher.mq5 |
| |||
//| 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 version "1.00"
| |||
#property strict
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Include |
| |||
//+------------------------------------------------------------------+
| |||
#include "Def.mqh"
| |||
#include <TSN\\ExtraCodes\\Func.mqh>
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Global variables |
| |||
//+------------------------------------------------------------------+
| |||
input string InpFileNameArgs = "";
| |||
input int InpFileCommonFlag = 0;
| |||
input string InpArgsConfigJson = "";
| |||
input string InpArgsResJson = "";
| |||
input string InpArgsLockBin = "";
| |||
input string InpArgsBaseTerminalPath = "";
| |||
// 1 hora (3600 * 1000) en ms
| |||
input uint InpPyTimeoutMs = 3600000;
| |||
#define WAIT_TIMEOUT_VAL 0x102
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Expert initialization function |
| |||
//+------------------------------------------------------------------+
| |||
int OnInit()
| |||
{
| |||
//---
| |||
::ResetLastError();
| |||
const int fh = ::FileOpen(InpFileNameArgs, FILE_READ | FILE_TXT | InpFileCommonFlag);
| |||
if(fh == INVALID_HANDLE)
| |||
{
| |||
FastLog(FUNCION_ACTUAL, FATAL_ERROR_TEXT, ::StringFormat("Fallo al abrir el archivo args = %s, ultimo error = %d", InpFileNameArgs, ::GetLastError()));
| |||
ResFinal(AIDATATASKRUNNNER_TRAINIG_OUT_ERR_EXE_PY);
| |||
return INIT_PARAMETERS_INCORRECT;
| |||
}
| |||
// Lecutra del archivo
| |||
const string path_file_py = ::FileReadString(fh);
| |||
const string extension = ::FileReadString(fh);
| |||
::FileClose(fh);
| |||
const string args = "--config \"" + (InpArgsBaseTerminalPath + InpArgsConfigJson) + "\""
| |||
+ " --results \"" + (InpArgsBaseTerminalPath + InpArgsResJson) + "\""
| |||
+ " --lock \"" + (InpArgsBaseTerminalPath + InpArgsLockBin) + "\"";
| |||
const string cmd = "\"" + path_file_py + "\" " + args;
| |||
| |||
//--- Lanzamos el proceso
| |||
PROCESS_INFORMATION pi;
| |||
STARTUPINFOW si;
| |||
::ZeroMemory(si);
| |||
si.cb = sizeof(si);
| |||
| |||
const int created = CreateProcessW(NULL, cmd, NULL, NULL, false, 0, NULL, NULL, si, pi);
| |||
if(created == 0)
| |||
{
| |||
FastLog(FUNCION_ACTUAL, FATAL_ERROR_TEXT,
| |||
::StringFormat("Fallo CreateProcessW, ultimo error = %d", kernel32::GetLastError()));
| |||
ResFinal(AIDATATASKRUNNNER_TRAINIG_OUT_ERR_EXE_PY);
| |||
return INIT_FAILED;
| |||
}
| |||
| |||
//--- Esperamos
| |||
const uint wait = WaitForSingleObject(pi.hProcess, InpPyTimeoutMs);
| |||
uint exit_code = 1;
| |||
GetExitCodeProcess(pi.hProcess, exit_code);
| |||
CloseHandle(pi.hProcess);
| |||
CloseHandle(pi.hThread);
| |||
| |||
//--- Vericamos como quedo el resultado
| |||
if(wait == WAIT_TIMEOUT_VAL)
| |||
{
| |||
FastLog(FUNCION_ACTUAL, FATAL_ERROR_TEXT, "Timeout — el py tardó demasiado");
| |||
ResFinal(AIDATATASKRUNNNER_TRAINIG_OUT_TIMEOUT);
| |||
return INIT_FAILED;
| |||
}
| |||
| |||
//---
| |||
if(exit_code != AIDATATASKRUNNNER_TRAINIG_OUT_RES)
| |||
{
| |||
FastLog(FUNCION_ACTUAL, FATAL_ERROR_TEXT, ::StringFormat("Py terminó con exit_code = %u", exit_code));
| |||
ResFinal(exit_code);
| |||
return INIT_FAILED;
| |||
}
| |||
| |||
// exit_code == 0 py escribió res.json correctamente
| |||
// Solo creamos el lock.bin para despertar al panel
| |||
const int fh2 = ::FileOpen(InpArgsLockBin, FILE_WRITE | FILE_BIN | InpFileCommonFlag, 0);
| |||
if(fh2 != INVALID_HANDLE)
| |||
::FileClose(fh2);
| |||
| |||
//---
| |||
return(INIT_FAILED); // Sale solo
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Expert deinitialization function |
| |||
//+------------------------------------------------------------------+
| |||
void OnDeinit(const int reason)
| |||
{
| |||
//---
| |||
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| Expert tick function |
| |||
//+------------------------------------------------------------------+
| |||
void OnTick()
| |||
{
| |||
//---
| |||
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
void ResFinal(int finish_code)
| |||
{
| |||
//--- Creacion del json
| |||
::ResetLastError();
| |||
const int fh = ::FileOpen(InpArgsResJson, FILE_WRITE | FILE_TXT | InpFileCommonFlag, 0);
| |||
if(fh != INVALID_HANDLE)
| |||
{
| |||
::FileWriteString(fh, ::StringFormat("{\"finish\":%d}", finish_code));
| |||
::FileClose(fh);
| |||
}
| |||
else
| |||
{
| |||
FastLog(FUNCION_ACTUAL, FATAL_ERROR_TEXT, ::StringFormat("Fallo al escribir res.json, ultimo error = %d", ::GetLastError()));
| |||
| |||
}
| |||
| |||
//--- Creasion del bin
| |||
::ResetLastError();
| |||
const int fh2 = ::FileOpen(InpArgsLockBin, FILE_WRITE | FILE_BIN | InpFileCommonFlag, 0);
| |||
if(fh2 != INVALID_HANDLE)
| |||
::FileClose(fh2);
| |||
else
| |||
{
| |||
FastLog(FUNCION_ACTUAL, FATAL_ERROR_TEXT, ::StringFormat("Fallo al escribir lock.bin, ultimo error = %d", ::GetLastError()));
| |||
}
| |||
}
| |||
//+------------------------------------------------------------------+
|