Adwizard/Optimization/OptimizerTask.mqh

339 lines
25 KiB
MQL5
Raw Permalink Normal View History

2025-04-11 13:28:40 +03:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| OptimizerTask.mqh |
//| Copyright 2024, Yuriy Bykov |
//| https://www.mql5.com/ru/users/antekov |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Yuriy Bykov"
#property link "https://www.mql5.com/ru/users/antekov"
2025-04-11 15:16:52 +03:00
#property version "1.05"
2025-04-11 13:28:40 +03:00
// $C=:F8O 70?CA:0 8A?>;=O5<>3> D09;0 2 >?5@0F8>==>9 A8AB5<5
#import "shell32.dll"
int ShellExecuteW(int hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd);
#import
2025-04-11 15:16:52 +03:00
#include "../Database/Database.mqh"
#include "../Utils/MTTester.mqh" // https://www.mql5.com/ru/code/26132
2025-04-11 13:28:40 +03:00
//+------------------------------------------------------------------+
//| ;0AA 4;O 7040G8 >?B8<870F88 |
//+------------------------------------------------------------------+
class COptimizerTask {
protected:
enum {
TASK_TYPE_UNKNOWN,
TASK_TYPE_EX5,
TASK_TYPE_PY
} m_type; // "8? 7040G8 (MQL5 8;8 Python)
ulong m_id; // 45=B8D8:0B>@ 7040G8
string m_setting; // !B@>:0 8=8F80;870F88 ?0@0<5B@>2 A>25B=8:0 4;O B5:CI59 7040G8
string m_fileName; // <O D09;0 107K 40==KE
string m_pythonPath; // >;=K9 ?CBL : 8=B5@?@5B0B>@C Python
// >;CG5=85 ?>;=>3> 8;8 >B=>A8B5;L=>3> ?CB8 : 7040==><C D09;C 2 B5:CI59 ?0?:5
string GetProgramPath(string name, bool rel = true);
// >;CG5=85 AB@>:8 8=8F80;870F88 87 ?0@0<5B@>2 7040G8
void Parse();
// >;CG5=85 B8?0 7040G8 87 ?0@0<5B@>2 7040G8
void ParseType();
public:
// !B@C:BC@0 40==KE 4;O GB5=8O >4=>9 AB@>:8 @57C;LB0B0 70?@>A0
struct params {
string expert;
int optimization;
string from_date;
string to_date;
int forward_mode;
string forward_date;
double deposit;
string symbol;
string period;
string tester_inputs;
ulong id_task;
int optimization_criterion;
} m_params;
// >=AB@C:B>@
COptimizerTask(string p_fileName, string p_pythonPath = NULL) :
m_id(0), m_fileName(p_fileName), m_pythonPath(p_pythonPath) {}
// 45=B8D8:0B>@ 7040G8
ulong Id() {
return m_id;
}
// A=>2=>9 <5B>4
void Process();
// 03@C7:0 ?0@0<5B@>2 7040G8 87 107K 40==KE
void Load(ulong p_id);
// 0?CA: 7040G8
void Start();
// 025@H5=85 7040G8
void Finish();
// 040G0 2K?>;=5=0?
bool IsDone();
};
//+------------------------------------------------------------------+
//| >;CG5=85 AB@>:8 8=8F80;870F88 87 ?0@0<5B@>2 7040G8 |
//+------------------------------------------------------------------+
void COptimizerTask::Parse() {
// >;CG05< B8? 7040G8 87 ?0@0<5B@>2 7040G8
ParseType();
// A;8 MB> 7040G0 =0 >?B8<870F8N A>25B=8:0
if(m_type == TASK_TYPE_EX5) {
// $>@<8@C5< AB@>:C ?0@0<5B@>2 4;O B5AB5@0
m_setting = StringFormat(
"[Tester]\r\n"
"Expert=%s\r\n"
"Symbol=%s\r\n"
"Period=%s\r\n"
"Optimization=%d\r\n"
"Model=1\r\n"
"FromDate=%s\r\n"
"ToDate=%s\r\n"
"ForwardMode=%d\r\n"
"%s"
"Deposit=%.2f\r\n"
"Currency=USD\r\n"
"ProfitInPips=0\r\n"
"Leverage=200\r\n"
"ExecutionMode=0\r\n"
"OptimizationCriterion=%d\r\n"
"[TesterInputs]\r\n"
"idTask_=%d\r\n"
"fileName_=%s\r\n"
"%s\r\n",
GetProgramPath(m_params.expert),
m_params.symbol,
m_params.period,
m_params.optimization,
m_params.from_date,
m_params.to_date,
m_params.forward_mode,
(m_params.forward_mode == 4 ?
StringFormat("ForwardDate=%s\r\n", m_params.forward_date) : ""),
m_params.deposit,
m_params.optimization_criterion,
m_params.id_task,
DB::FileName(),
m_params.tester_inputs
);
// A;8 MB> 7040G0 =0 70?CA: ?@>3@0<<K =0 Python
} else if (m_type == TASK_TYPE_PY) {
// $>@<8@C5< AB@>:C 70?CA:0 ?@>3@0<<K =0 Python A ?0@0<5B@0<8
m_setting = StringFormat("\"%s\" \"%s\" %I64u %s",
GetProgramPath(m_params.expert, false), // $09; A ?@>3@0<<>9 =0 Python
DB::FileName(true), // CBL : D09;C A 107>9 40==KE
m_id, // 45=B8D8:0B>@ 7040G8
m_params.tester_inputs // 0@0<B@K 70?CA:0
);
}
}
//+------------------------------------------------------------------+
//| >;CG5=85 B8?0 7040G8 87 ?0@0<5B@>2 7040G8 |
//+------------------------------------------------------------------+
void COptimizerTask::ParseType() {
string ext = StringSubstr(m_params.expert, StringLen(m_params.expert) - 3);
if(ext == ".py") {
m_type = TASK_TYPE_PY;
} else if (ext == "ex5") {
m_type = TASK_TYPE_EX5;
} else {
m_type = TASK_TYPE_UNKNOWN;
}
}
//+------------------------------------------------------------------+
//| >;CG5=85 ?>;=>3> 8;8 >B=>A8B5;L=>3> ?CB8 : 7040==><C D09;C |
//| 2 B5:CI59 ?0?:5 |
//+------------------------------------------------------------------+
string COptimizerTask::GetProgramPath(string name, bool rel = true) {
string path = MQLInfoString(MQL_PROGRAM_PATH);
string programName = MQLInfoString(MQL_PROGRAM_NAME) + ".ex5";
string terminalPath = TerminalInfoString(TERMINAL_DATA_PATH) + "\\MQL5\\Experts\\";
if(rel) {
path = StringSubstr(path,
StringLen(terminalPath),
StringLen(path) - (StringLen(terminalPath) + StringLen(programName)));
} else {
path = StringSubstr(path, 0, StringLen(path) - (0 + StringLen(programName)));
}
return path + name;
}
//+------------------------------------------------------------------+
//| >;CG5=85 >G5@54=>9 7040G8 >?B8<870F88 87 >G5@548 |
//+------------------------------------------------------------------+
void COptimizerTask::Load(ulong p_id) {
// 0?><8=05< 845=B8D8:0B>@ 7040G8
m_id = p_id;
// 0?@>A =0 ?>;CG5=85 7040G8 >?B8<870F88 87 >G5@548 ?> 845=B8D8:0B>@C
string query = StringFormat(
"SELECT s.expert,"
" s.optimization,"
" s.from_date,"
" s.to_date,"
" s.forward_mode,"
" s.forward_date,"
" s.deposit,"
" j.symbol,"
" j.period,"
" j.tester_inputs,"
" t.id_task,"
" t.optimization_criterion"
" FROM tasks t"
" JOIN"
" jobs j ON t.id_job = j.id_job"
" JOIN"
" stages s ON j.id_stage = s.id_stage"
" WHERE t.id_task=%I64u;", m_id);
// B:@K205< 107C 40==KE
if(DB::Connect(m_fileName)) {
// K?>;=O5< 70?@>A
int request = DatabasePrepare(DB::Id(), query);
// A;8 =5B >H81:8
if(request != INVALID_HANDLE) {
// '8B05< 40==K5 87 ?5@2>9 AB@>:8 @57C;LB0B0
if(DatabaseReadBind(request, m_params)) {
Parse();
} else {
// !>>1I05< >1 >H81:5 ?@8 =5>1E>48<>AB8
PrintFormat(__FUNCTION__" | ERROR: Reading row for request \n%s\nfailed with code %d",
query, GetLastError());
}
} else {
// !>>1I05< >1 >H81:5 ?@8 =5>1E>48<>AB8
PrintFormat(__FUNCTION__" | ERROR: request \n%s\nfailed with code %d", query, GetLastError());
}
// 0:@K205< 107C 40==KE
DB::Close();
}
}
//+------------------------------------------------------------------+
//| 0?CA: 7040G8 |
//+------------------------------------------------------------------+
void COptimizerTask::Start() {
PrintFormat(__FUNCTION__" | Task ID = %d\n%s", m_id, m_setting);
// A;8 MB> 7040G0 =0 >?B8<870F8N A>25B=8:0
if(m_type == TASK_TYPE_EX5) {
// 0?CA:05< =>2CN 7040GC >?B8<870F88 2 B5AB5@5
MTTESTER::CloseNotChart();
MTTESTER::SetSettings2(m_setting);
MTTESTER::ClickStart();
// 1=>2;O5< AB0BCA 7040G8 2 1075 40==KE
DB::Connect(m_fileName);
string query = StringFormat(
"UPDATE tasks SET "
" status='Process' "
" WHERE id_task=%d",
m_id);
DB::Execute(query);
DB::Close();
// A;8 MB> 7040G0 =0 70?CA: ?@>3@0<<K =0 Python
} else if (m_type == TASK_TYPE_PY) {
PrintFormat(__FUNCTION__" | SHELL EXEC: %s", m_pythonPath);
// K7K205< A8AB5<=CN DC=:F8N 70?CA:0 ?@>3@0<<K A ?0@0<5B@0<8
ShellExecuteW(NULL, NULL, m_pythonPath, m_setting, NULL, 1);
}
}
//+------------------------------------------------------------------+
//| 025@H5=85 7040G8 |
//+------------------------------------------------------------------+
void COptimizerTask::Finish() {
PrintFormat(__FUNCTION__" | Task ID = %d", m_id);
// 1=>2;O5< AB0BCA 7040G8 2 1075 40==KE
DB::Connect(m_fileName);
string query = StringFormat(
"UPDATE tasks SET "
" status='Done' "
" WHERE id_task=%d",
m_id);
DB::Execute(query);
DB::Close();
}
//+------------------------------------------------------------------+
//| 040G0 2K?>;=5=0? |
//+------------------------------------------------------------------+
bool COptimizerTask::IsDone() {
// A;8 =5B B5:CI59 7040G8, B> 2AQ 2K?>;=5=>
if(m_id == 0) {
return true;
}
// 57C;LB0B
bool res = false;
// A;8 MB> 7040G0 =0 >?B8<870F8N A>25B=8:0
if(m_type == TASK_TYPE_EX5) {
// @>25@O5<, 7025@H8; ;8 @01>BC B5AB5@ AB@0B5389
res = MTTESTER::IsReady();
// A;8 MB> 7040G0 =0 70?CA: ?@>3@0<<K =0 Python, B>
} else if(m_type == TASK_TYPE_PY) {
// 0?@>A =0 ?>;CG5=85 AB0BCA0 B5:CI59 7040G8
string query = StringFormat("SELECT status "
" FROM tasks"
" WHERE id_task=%I64u;", m_id);
// B:@K205< 107C 40==KE
if(DB::Connect(m_fileName)) {
// K?>;=O5< 70?@>A
int request = DatabasePrepare(DB::Id(), query);
// A;8 =5B >H81:8
if(request != INVALID_HANDLE) {
// !B@C:BC@0 40==KE 4;O GB5=8O >4=>9 AB@>:8 @57C;LB0B0 70?@>A0
struct Row {
string status;
} row;
// '8B05< 40==K5 87 ?5@2>9 AB@>:8 @57C;LB0B0
if(DatabaseReadBind(request, row)) {
// @>25@O5<, @025= ;8 AB0BCA Done
res = (row.status == "Done");
} else {
// !>>1I05< >1 >H81:5 ?@8 =5>1E>48<>AB8
PrintFormat(__FUNCTION__" | ERROR: Reading row for request \n%s\nfailed with code %d",
query, GetLastError());
}
} else {
// !>>1I05< >1 >H81:5 ?@8 =5>1E>48<>AB8
PrintFormat(__FUNCTION__" | ERROR: request \n%s\nfailed with code %d", query, GetLastError());
}
// 0:@K205< 107C 40==KE
DB::Close();
}
} else {
res = true;
}
return res;
}
//+------------------------------------------------------------------+