Vigiar
1
0
Derivar
Você já tinha feito uma derivação do repositório mql5-execution-microstructure-02-request-latency, anteriormente
0
mql5-execution-microstructu.../Include/RequestLatencyLab/Configuration.mqh

259 linhas
Sem EOL
10 KiB
MQL5

//+------------------------------------------------------------------+
//| Configuration.mqh |
//| Copyright 2026, MetaQuotes Ltd. |
//| www.mql5.com |
//+------------------------------------------------------------------+
#ifndef REQUEST_LATENCY_LAB_CONFIGURATION_MQH
#define REQUEST_LATENCY_LAB_CONFIGURATION_MQH
#include "..\..\Include\RequestLatencyLab\Models.mqh"
//+------------------------------------------------------------------+
//| Режимы работы советника (ТЗ §1). |
//+------------------------------------------------------------------+
enum ENUM_LAB_RUN_MODE
{
LAB_RUN_LOCAL_ONLY = 0, // по умолчанию; без торговли
LAB_RUN_PENDING_CREATE_DELETE,
LAB_RUN_MARKET_ORDER
};
//+------------------------------------------------------------------+
//| Настройки лаборатории (заполняются из input советника). |
//+------------------------------------------------------------------+
struct LabSettings
{
string campaign_id;
string session_prefix;
ENUM_LAB_EXPERIMENT experiment_id;
int series_id; // 1..5
string symbol;
ulong magic;
int deviation_points;
int pending_distance_ticks; // D
int count_per_condition; // 100
int warmup_per_condition; // 10
int outcome_timeout_ms; // 5000
int late_grace_ms; // 1000
int pause_ms; // 1000
int timer_requested_ms; // 20
int feature_window_sec; // 60
int feature_max_age_ms; // 1000
int quote_max_age_ms;
string calibration_id;
ulong seed;
int cleanup_max_attempts; // 1
int sample_capacity; // 2048
int event_capacity; // 65536
int error_reserve_capacity;
double volume_units_tolerance; // 1e-7
int address_read_budget;
int history_scan_budget;
int e3_campaign_limit_min; // 0=без лимита; иначе минуты
ENUM_LAB_RUN_MODE run_mode;
string data_origin; // DEMO/SYNTHETIC
string configuration_id;
void Zero(void);
};
//+------------------------------------------------------------------+
//| CConfiguration — проверка и фиксация конфигурации. |
//+------------------------------------------------------------------+
class CConfiguration
{
public:
//--- базовая проверка входных параметров
static bool Validate(const LabSettings &s, LabError &error);
//--- правила символа из терминала
static bool BuildSymbolRules(const string symbol, SymbolRules &rules, LabError &error);
//--- описание символа для манифеста
static string ManifestSymbolInfo(const SymbolRules &r)
{
return(StringFormat("%s|digits=%d|point=%.10g|tick_size=%.10g|vol_min=%.4g|vol_max=%.4g|vol_step=%.4g",
r.symbol, r.digits, r.point, r.tick_size,
r.volume_min, r.volume_max, r.volume_step));
}
//--- минимальный допустимый объём (ТЗ §2.4). Фиксируется до серии.
static double MinVolume(const SymbolRules &r) { return(r.volume_min); }
//--- детерминированный отпечаток конфигурации (без случайности и дат)
static string ConfigurationId(const LabSettings &s, const SymbolRules &rules);
};
//+------------------------------------------------------------------+
//| Внешние определения методов. |
//+------------------------------------------------------------------+
void LabSettings::Zero(void)
{
campaign_id = "";
session_prefix = "";
experiment_id = LAB_EXP_E1;
series_id = 1;
symbol = "";
magic = 0;
deviation_points = 0;
pending_distance_ticks = 0;
count_per_condition = 100;
warmup_per_condition = 10;
outcome_timeout_ms = 5000;
late_grace_ms = 1000;
pause_ms = 1000;
timer_requested_ms = 20;
feature_window_sec = 60;
feature_max_age_ms = 1000;
quote_max_age_ms = 500;
calibration_id = "";
seed = 1;
cleanup_max_attempts = 1;
sample_capacity = 2048;
event_capacity = 65536;
error_reserve_capacity = 4096;
volume_units_tolerance = 1e-7;
address_read_budget = 20000;
history_scan_budget = 100000;
e3_campaign_limit_min = 30;
run_mode = LAB_RUN_LOCAL_ONLY;
data_origin = "SYNTHETIC";
configuration_id = "";
}
bool CConfiguration::Validate(const LabSettings &s, LabError &error)
{
error.Reset();
error.component = LAB_COMP_CONFIG;
if(s.count_per_condition <= 0 || s.warmup_per_condition < 0)
{
error.code = 1;
error.severity = LAB_SEV_BLOCKER;
error.message = "count_per_condition must be >0";
return(false);
}
if(s.warmup_per_condition > 0 && s.warmup_per_condition >= s.count_per_condition)
{
error.code = 2;
error.severity = LAB_SEV_BLOCKER;
error.message = "warmup must be smaller than count_per_condition";
return(false);
}
if(s.series_id < 1 || s.series_id > 5)
{
error.code = 3;
error.severity = LAB_SEV_BLOCKER;
error.message = "series_id must be 1..5";
return(false);
}
if(s.outcome_timeout_ms <= 0 || s.late_grace_ms < 0)
{
error.code = 4;
error.severity = LAB_SEV_BLOCKER;
error.message = "timeouts must be positive";
return(false);
}
if(s.pause_ms < 0 || s.timer_requested_ms <= 0)
{
error.code = 5;
error.severity = LAB_SEV_BLOCKER;
error.message = "pause/timer must be valid";
return(false);
}
if(s.feature_window_sec <= 0 || s.feature_max_age_ms <= 0)
{
error.code = 6;
error.severity = LAB_SEV_BLOCKER;
error.message = "feature window must be positive";
return(false);
}
if(s.seed == 0 || s.seed >= 2147483646ul)
{
error.code = 7;
error.severity = LAB_SEV_BLOCKER;
error.message = "seed must be in [1,2147483646]";
return(false);
}
if(s.sample_capacity <= 0 || s.event_capacity <= 0)
{
error.code = 8;
error.severity = LAB_SEV_BLOCKER;
error.message = "capacities must be positive";
return(false);
}
if(s.volume_units_tolerance <= 0.0 || s.volume_units_tolerance >= 1e-3)
{
error.code = 9;
error.severity = LAB_SEV_BLOCKER;
error.message = "volume tolerance must be in (0,1e-3)";
return(false);
}
if(s.cleanup_max_attempts < 1 || s.cleanup_max_attempts > 10)
{
error.code = 10;
error.severity = LAB_SEV_BLOCKER;
error.message = "cleanup_max_attempts must be 1..10";
return(false);
}
if(s.e3_campaign_limit_min < 0 || s.e3_campaign_limit_min > 1440)
{
error.code = 11;
error.severity = LAB_SEV_BLOCKER;
error.message = "e3_campaign_limit_min must be 0..1440";
return(false);
}
//--- data_origin задаётся оператором в файле запуска
//--- data_origin устанавливается в FillSettings (не здесь)
//--- торговый режим требует data_origin оператора (проверка выше)
//--- data_origin=DEMO задаётся в настроечном файле запуска
return(true);
}
bool CConfiguration::BuildSymbolRules(const string symbol, SymbolRules &rules, LabError &error)
{
error.Reset();
error.component = LAB_COMP_CONFIG;
if(StringLen(symbol) == 0)
{
error.code = 20;
error.severity = LAB_SEV_BLOCKER;
error.message = "symbol not set";
return(false);
}
if(!SymbolSelect(symbol, true))
{
error.code = 21;
error.severity = LAB_SEV_BLOCKER;
error.message = "symbol unavailable in Market Watch";
return(false);
}
ZeroMemory(rules);
rules.symbol = symbol;
rules.digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
rules.point = SymbolInfoDouble(symbol, SYMBOL_POINT);
rules.tick_size = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
rules.volume_min = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
rules.volume_max = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
rules.volume_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
rules.filling_mode = SymbolInfoInteger(symbol, SYMBOL_FILLING_MODE);
rules.trade_mode = SymbolInfoInteger(symbol, SYMBOL_TRADE_MODE);
rules.bid = SymbolInfoDouble(symbol, SYMBOL_BID);
rules.ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
if(!rules.IsValid())
{
error.code = 22;
error.severity = LAB_SEV_BLOCKER;
error.message = "symbol rules invalid (tick size or volume step missing)";
return(false);
}
return(true);
}
string CConfiguration::ConfigurationId(const LabSettings &s, const SymbolRules &rules)
{
string id = StringFormat("%s|exp=%s|ser=%d|sym=%s|mag=%I64u|dev=%d|D=%d|n=%d|w=%d|t=%d|g=%d|pause=%d|timer=%d|win=%d|age=%d|quote=%d|cal=%s|seed=%I64u|cln=%d|e3=%d|cap=%d/%d|tol=%.10g|mode=%d",
s.campaign_id, LabExperimentName(s.experiment_id), s.series_id,
s.symbol, s.magic, s.deviation_points, s.pending_distance_ticks,
s.count_per_condition, s.warmup_per_condition,
s.outcome_timeout_ms, s.late_grace_ms, s.pause_ms, s.timer_requested_ms,
s.feature_window_sec, s.feature_max_age_ms, s.quote_max_age_ms,
s.calibration_id, s.seed, s.cleanup_max_attempts,
s.e3_campaign_limit_min,
s.sample_capacity, s.event_capacity, s.volume_units_tolerance,
(int)s.run_mode);
StringReplace(id, "|", "_");
StringReplace(id, "/", "_");
return(id);
}
#endif // REQUEST_LATENCY_LAB_CONFIGURATION_MQH
//+------------------------------------------------------------------+