Adwizard/Optimization/OptimizationProject.mqh

327 lines
27 KiB
MQL5
Raw Permalink Normal View History

2025-04-11 13:28:40 +03:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| OptimizationProject.mqh |
//| Copyright 2025, Yuriy Bykov |
//| https://www.mql5.com/ru/users/antekov |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Yuriy Bykov"
#property link "https://www.mql5.com/ru/articles/17328"
2025-04-11 15:16:52 +03:00
#property version "1.01"
2025-04-11 13:28:40 +03:00
2025-04-11 15:16:52 +03:00
#include "../Database/Database.mqh"
2025-04-11 13:28:40 +03:00
// @5420@8B5;L=>5 >1JO2;5=85 :;0AA0 ?@>5:B0 >?B8<870F88
class COptimizationProject;
#include "OptimizationTask.mqh"
#include "OptimizationJob.mqh"
#include "OptimizationStage.mqh"
// !>740=85 =>2>3> B8?0 - C:070B5;O =0 DC=:F8N 35=5@0F88 AB@>:8
// ?0@0<5B@>2 @01>BK >?B8<870F88 (job), ?@8=8<0NI59 2 :0G5AB25
// 0@3C<5=B0 C:070B5;L =0 >1J5:B ?@>5:B0 >?B8<870F88
typedef string (*TJobsTemplateFunc)(COptimizationProject*);
//+------------------------------------------------------------------+
//| ;0AA 4;O ?@>5:B0 >?B8<870F88 |
//+------------------------------------------------------------------+
class COptimizationProject {
public:
string m_fileName; // <O 107K 40==KE
// !2>9AB20, =0?@O<CN A>E@0=O5<K5 2 1075 40==KE
ulong id_project; // 45=B8D8:0B>@ ?@>5:B0
string name; // 0720=85
string version; // 5@A8O
string description; // ?8A0=85
string status; // !B0BCA
// 0AA82K 2A5E MB0?>2, @01>B 8 7040G ?@>5:B0
COptimizationStage* m_stages[]; // -B0?K ?@>5:B0
COptimizationJob* m_jobs[]; // 01>BK 2A5E MB0?>2 ?@>5:B0
COptimizationTask* m_tasks[]; // 040G8 2A5E @01>B MB0?>2 ?@>5:B0
// !2>9AB20 4;O B5:CI53> A>AB>O=8O ?@>F5AA0 A>740=8O ?@>5:B0
string m_symbol; // "5:CI89 A8<2>;
string m_timeframe; // "5:CI89 B09<D@59<
COptimizationStage* m_stage; // >A;54=89 A>740==K9 MB0? (B5:CI89 MB0?)
COptimizationJob* m_job; // >A;54=OO A>740==0O @01>B0 (B5:CI0O @01>B0)
COptimizationTask* m_task; // >A;54=OO A>740==0O 7040G0 (B5:CI0O 7040G0)
// 5B>4K
COptimizationProject(string p_fileName); // >=AB@C:B>@
~COptimizationProject(); // 5AB@:B>@
// !>740=85 =>2>3> ?@>5:B0 2 1075 40==KE
COptimizationProject* COptimizationProject::Create(string p_name,
string p_version = "", string p_description = "", string p_status = "Done");
void Insert(); // AB02:0 70?8A8 2 107C 40==KE
void Update(); // 1=>2;5=85 70?8A8 2 1075 40==KE
// >102;5=85 =>2>3> MB0?0 2 107C 40==KE
COptimizationProject* AddStage(COptimizationStage* parentStage, string stageName, string stageExpertName,
string stageSymbol, string stageTimeframe, int stageOptimization, int stageModel,
datetime stageFromDate, datetime stageToDate,
int stageForwardMode, datetime stageForwardDate,
int stageDeposit = 10000, string stageCurrency = "USD",
int stageProfitInPips = 0, int stageLeverage = 200,
int stageExecutionMode = 0, int stageOptimizationCriterion = 7,
string stageStatus = "Done");
// >102;5=85 =>2KE @01>B 2 107C 40==KE 4;O 7040==KE A8<2>;>2 8 B09<D@59<>2
COptimizationProject* AddJobs(string p_symbols, string p_timeframes, TJobsTemplateFunc p_templateFunc);
COptimizationProject* AddJobs(string &p_symbols[], string &p_timeframes[], TJobsTemplateFunc p_templateFunc);
// >102;5=85 =>2KE 7040G 2 107C 40==KE 4;O 7040==KE :@8B5@852 >?B8<870F88
COptimizationProject* AddTasks(string p_criterions);
COptimizationProject* AddTasks(string &p_criterions[]);
void Queue(); // >AB0=>2:0 ?@>5:B0 2 >G5@54L =0 2K?>;=5=585
// @5>1@07>20=85 AB@>:>2>3> =0720=8O 2 B09<D@59<
static ENUM_TIMEFRAMES StringToTimeframe(string s);
};
//+------------------------------------------------------------------+
//| >=AB@C:B>@ |
//+------------------------------------------------------------------+
COptimizationProject::COptimizationProject(string p_fileName) :
m_fileName(p_fileName), id_project(0) {
// >4:;NG05<AO : 1075 40==KE
if (DB::Connect(m_fileName)) {
// 0G8=05< B@0=70:F8N
DatabaseTransactionBegin(DB::Id());
}
}
//+------------------------------------------------------------------+
//| 5AB@C:B>@ |
//+------------------------------------------------------------------+
COptimizationProject::~COptimizationProject() {
// A;8 =5 2>7=8:;> >H81>:, B>
if(DB::Res()) {
// >4B25@6405< B@0=70:F8N
DatabaseTransactionCommit(DB::Id());
} else {
// =0G5 >B<5=O5< B@0=70:F8N
DatabaseTransactionRollback(DB::Id());
}
// 0:@K205< A>548=5=85 A 107>9 40==KE
DB::Close();
// #40;O5< A>740==K5 >1J5:BK 7040G, @01>B 8 MB0?>2
FOREACH(m_tasks) {
delete m_tasks[i];
}
FOREACH(m_jobs) {
delete m_jobs[i];
}
FOREACH(m_stages) {
delete m_stages[i];
}
}
//+------------------------------------------------------------------+
//| !>740=85 =>2>3> ?@>5:B0 2 1075 40==KE |
//+------------------------------------------------------------------+
COptimizationProject* COptimizationProject::Create(string p_name,
string p_version = "", string p_description = "", string p_status = "Done") {
// #AB0=02;8205< ?5@540==K5 7=0G5=8O A2>9AB2
name = p_name;
version = p_version;
description = p_description;
status = p_status;
// AB02;O5< 2 107C 40==KE
Insert();
return &this;
}
//+------------------------------------------------------------------+
//| AB02:0 70?8A8 2 107C 40==KE |
//+------------------------------------------------------------------+
void COptimizationProject::Insert() {
string query = StringFormat("INSERT INTO projects "
" VALUES (NULL,'%s','%s','%s',NULL,'%s');",
name, version, description, status);
id_project = DB::Insert(query);
PrintFormat(__FUNCTION__" | %s -> %I64u", query, id_project);
}
//+------------------------------------------------------------------+
//| 1=>2;5=85 70?8A8 2 1075 40==KE |
//+------------------------------------------------------------------+
void COptimizationProject::Update() {
string query = StringFormat("UPDATE projects "
" SET name='%s', version='%s',description='%s',status='%s' "
" WHERE id_project=%I64u;",
name, version, description, status, id_project);
DB::Execute(query);
PrintFormat(__FUNCTION__" | %s", query);
}
//+------------------------------------------------------------------+
//| >102;5=85 =>2>3> MB0?0 2 107C 40==KE |
//+------------------------------------------------------------------+
COptimizationProject* COptimizationProject::AddStage(COptimizationStage* p_parentStage, string p_name, string p_expertName,
string p_symbol, string p_timeframe, int p_optimization, int p_model,
datetime p_fromDate, datetime p_toDate,
int p_forwardMode, datetime p_forwardDate,
int p_deposit = 10000, string p_currency = "USD",
int p_profitInPips = 0, int p_leverage = 200,
int p_executionMode = 0, int p_optimizationCriterion = 7,
string p_status = "Done") {
// !>740Q< =>2K9 >1J5:B MB0?0
m_stage = new COptimizationStage(0, &this, p_parentStage, p_name, p_expertName,
p_symbol, p_timeframe, p_optimization, p_model,
p_fromDate, p_toDate,
p_forwardMode, p_forwardDate,
p_deposit, p_currency,
p_profitInPips, p_leverage,
p_executionMode, p_optimizationCriterion,
p_status);
// AB02;O5< 53> 2 107C 40==KE >?B8<870F88
m_stage.Insert();
// >102;O5< 53> 2 <0AA82 2A5E MB0?>2
APPEND(m_stages, m_stage);
return &this;
}
//+------------------------------------------------------------------+
//| >102;5=85 =>2KE @01>B 2 107C 40==KE 4;O 7040==KE |
//| A8<2>;>2 8 B09<D@59<>2 2 AB@>:0E |
//+------------------------------------------------------------------+
COptimizationProject* COptimizationProject::AddJobs(string p_symbols, string p_timeframes,
TJobsTemplateFunc p_templateFunc) {
// 0AA82 A8<2>;>2 4;O AB@0B5389
string symbols[];
StringReplace(p_symbols, ";", ",");
StringSplit(p_symbols, ',', symbols);
// 0AA82 B09<D@59<>2 4;O AB@0B5389
string timeframes[];
StringReplace(p_timeframes, ";", ",");
StringSplit(p_timeframes, ',', timeframes);
return AddJobs(symbols, timeframes, p_templateFunc);
}
//+------------------------------------------------------------------+
//| >102;5=85 =>2KE @01>B 2 107C 40==KE 4;O 7040==KE |
//| A8<2>;>2 8 B09<D@59<>2 2 <0AA820E |
//+------------------------------------------------------------------+
COptimizationProject* COptimizationProject::AddJobs(string &p_symbols[], string &p_timeframes[],
TJobsTemplateFunc p_templateFunc) {
// ;O :064>3> A8<2>;0
FOREACH_AS(p_symbols, m_symbol) {
// ;O :064>3> B09<D@59<0
FOREACH_AS(p_timeframes, m_timeframe) {
// >;CG05< ?0@0<5B@K 4;O @01>BK 4;O 40==>3> A8<2>;0 8 B09<D@59<0
string params = p_templateFunc(&this);
// !>740Q< =>2K9 >1J5:B @01>BK
m_job = new COptimizationJob(0, m_stage, m_symbol, m_timeframe, params);
// AB02;O5< 53> 2 107C 40==KE >?B8<870F88
m_job.Insert();
// >102;O5< 53> 2 <0AA82 2A5E @01>B
APPEND(m_jobs, m_job);
// >102;O5< 53> 2 <0AA82 @01>B B5:CI53> MB0?0
APPEND(m_stage.jobs, m_job);
}
}
return &this;
}
//+------------------------------------------------------------------+
//| >102;5=85 =>2KE 7040G 2 107C 40==KE 4;O 7040==KE |
//| :@8B5@852 >?B8<870F88 2 >4=>9 AB@>:5 |
//+------------------------------------------------------------------+
COptimizationProject* COptimizationProject::AddTasks(string p_criterions) {
// 0AA82 4;O :@8B5@852 >?B8<870F88
string criterions[];
StringReplace(p_criterions, ";", ",");
StringSplit(p_criterions, ',', criterions);
return AddTasks(criterions);
}
//+------------------------------------------------------------------+
//| >102;5=85 =>2KE 7040G 2 107C 40==KE 4;O 7040==KE |
//| :@8B5@852 >?B8<870F88 2 <0AA825 |
//+------------------------------------------------------------------+
COptimizationProject* COptimizationProject::AddTasks(string &p_criterions[]) {
// ;O :064>9 @01>BK B5:CI53> MB0?0
FOREACH_AS(m_stage.jobs, m_job) {
// ;O :064>3> :@8B5@8O >?B8<870F88
FOREACH(p_criterions) {
// !>740Q< =>2K9 >1J5:B 7040G8 4;O 40==>9 @01>BK
m_task = new COptimizationTask(0, m_job, (int) p_criterions[i]);
// AB02;O5< 53> 2 107C 40==KE >?B8<870F88
m_task.Insert();
// >102;O5< 53> 2 <0AA82 2A5E 7040G
APPEND(m_tasks, m_task);
// >102;O5< 53> 2 <0AA82 7040G B5:CI59 @01>BK
APPEND(m_job.tasks, m_task);
}
}
return &this;
}
//+------------------------------------------------------------------+
//| >AB0=>2:0 ?@>5:B0 2 >G5@54L =0 2K?>;=5=585 |
//+------------------------------------------------------------------+
void COptimizationProject::Queue() {
status = "Queued";
Update();
}
//+------------------------------------------------------------------+
//| @5>1@07>20=85 AB@>:>2>3> =0720=8O 2 B09<D@59< |
//+------------------------------------------------------------------+
static ENUM_TIMEFRAMES COptimizationProject::StringToTimeframe(string s) {
// A;8 2 AB@>:5 5ABL A8<2>; "_", B> >AB02;O5< B>;L:> A8<2>;K, 84CI85 ?>A;5 =53>
int pos = StringFind(s, "_");
if(pos != -1) {
s = StringSubstr(s, pos + 1);
}
// 5@52>48< 2 25@E=89 @538AB@
StringToUpper(s);
// 0AA82K A>>B25BAB2CNI8E 7=0G5=89 =0720=89 8 B09<D@59<>2
string keys[] = {"M1", "M2", "M3", "M4", "M5", "M6", "M10", "M12", "M15", "M20", "M30",
"H1", "H2", "H3", "H4", "H6", "H8", "H12", "D1", "W1", "MN1"
};
ENUM_TIMEFRAMES values[] = {PERIOD_M1, PERIOD_M2, PERIOD_M3, PERIOD_M4, PERIOD_M5, PERIOD_M6,
PERIOD_M10, PERIOD_M12, PERIOD_M15, PERIOD_M20, PERIOD_M30,
PERIOD_H1, PERIOD_H2, PERIOD_H3, PERIOD_H4, PERIOD_H6,
PERIOD_H8, PERIOD_H12, PERIOD_D1, PERIOD_W1, PERIOD_MN1
};
// I5< A>>B25BAB285 8 2>72@0I05<, 5A;8 =0H;8
FOREACH(keys) {
if(keys[i] == s) return values[i];
}
return PERIOD_CURRENT;
}
//+------------------------------------------------------------------+