1196 linhas
37 KiB
MQL5
1196 linhas
37 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| Models.mqh |
|
|
//| Copyright 2026, MetaQuotes Ltd. |
|
|
//| www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#ifndef REQUEST_LATENCY_LAB_MODELS_MQH
|
|
#define REQUEST_LATENCY_LAB_MODELS_MQH
|
|
//+------------------------------------------------------------------+
|
|
//| Обязательная редакторская структура LatencySample (ТЗ §3.1). |
|
|
//| Имена, типы и порядок полей неизменны. |
|
|
//+------------------------------------------------------------------+
|
|
struct LatencySample
|
|
{
|
|
uint request_id; // request_id из MqlTradeResult (0, если has_request_id=0)
|
|
ulong sequence; // номер попытки в пределах session
|
|
ulong send_start_us; // T0 - непосредственно перед вызовом отправки
|
|
ulong send_return_us; // T1 - сразу после возврата торговой функции
|
|
ulong request_event_us; // T2 - вход в соответствующий TRADE_TRANSACTION_REQUEST
|
|
ulong order_event_us; // T3 - вход в первый связанный ORDER_ADD
|
|
ulong first_deal_us; // T4 - наименьшая метка среди уникальных торговых DEAL_ADD
|
|
ulong final_event_us; // T6 - конец первой успешной проверки исхода
|
|
uint retcode; // только код из соответствующего REQUEST
|
|
bool completed; // подтверждённость исхода на момент отчёта
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Роли, операции, режимы |
|
|
//+------------------------------------------------------------------+
|
|
enum ENUM_LAB_ROLE
|
|
{
|
|
LAB_ROLE_MAIN = 0, // основные 100 наблюдений
|
|
LAB_ROLE_WARMUP, // прогрев (10 на условие)
|
|
LAB_ROLE_CLEANUP, // служебное закрытие/удаление
|
|
LAB_ROLE_PILOT, // явный демо-пилот
|
|
LAB_ROLE_SYNTHETIC // синтетическая проверка
|
|
};
|
|
|
|
enum ENUM_LAB_OPERATION
|
|
{
|
|
LAB_OP_NONE = 0,
|
|
LAB_OP_MARKET_OPEN, // рыночная заявка
|
|
LAB_OP_PENDING_CREATE, // размещение отложенного ордера
|
|
LAB_OP_PENDING_DELETE, // удаление отложенного ордера (CLEANUP)
|
|
LAB_OP_POSITION_CLOSE // закрытие позиции (CLEANUP)
|
|
};
|
|
|
|
enum ENUM_LAB_SIDE
|
|
{
|
|
LAB_SIDE_NONE = 0,
|
|
LAB_SIDE_BUY,
|
|
LAB_SIDE_SELL
|
|
};
|
|
|
|
enum ENUM_LAB_MODE
|
|
{
|
|
LAB_MODE_SYNC = 0,
|
|
LAB_MODE_ASYNC
|
|
};
|
|
|
|
enum ENUM_LAB_LOGGING
|
|
{
|
|
LAB_LOG_MINIMAL = 0,
|
|
LAB_LOG_VERBOSE
|
|
};
|
|
|
|
enum ENUM_LAB_EXPERIMENT
|
|
{
|
|
LAB_EXP_E1 = 0,
|
|
LAB_EXP_E2,
|
|
LAB_EXP_E3,
|
|
LAB_EXP_E4,
|
|
LAB_EXP_E5
|
|
};
|
|
|
|
enum ENUM_LAB_ROW_KIND
|
|
{
|
|
LAB_ROW_SLOT = 0,
|
|
LAB_ROW_WAIT
|
|
};
|
|
|
|
enum ENUM_LAB_SLOT_STATUS
|
|
{
|
|
LAB_SLOT_PLANNED = 0,
|
|
LAB_SLOT_INTENT_SAVED,
|
|
LAB_SLOT_DISPATCHED,
|
|
LAB_SLOT_PRECHECK_REJECTED,
|
|
LAB_SLOT_CANCELED_BEFORE_DISPATCH,
|
|
LAB_SLOT_DISPATCH_UNCERTAIN,
|
|
LAB_SLOT_WAIT
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Корреляция, качество, применимость, исходы |
|
|
//+------------------------------------------------------------------+
|
|
enum ENUM_LAB_CORRELATION
|
|
{
|
|
LAB_CORR_UNRESOLVED = 0,
|
|
LAB_CORR_EXACT,
|
|
LAB_CORR_AMBIGUOUS,
|
|
LAB_CORR_FOREIGN,
|
|
LAB_CORR_CONFLICT
|
|
};
|
|
|
|
enum ENUM_LAB_APPLICABILITY
|
|
{
|
|
LAB_APP_APPLICABLE = 0,
|
|
LAB_APP_NOT_APPLICABLE,
|
|
LAB_APP_UNKNOWN
|
|
};
|
|
|
|
enum ENUM_LAB_FITNESS
|
|
{
|
|
LAB_FIT_CONFLICT = 0,
|
|
LAB_FIT_INTERRUPTED,
|
|
LAB_FIT_LATE,
|
|
LAB_FIT_MISSING,
|
|
LAB_FIT_VALID
|
|
};
|
|
|
|
enum ENUM_LAB_OUTCOME
|
|
{
|
|
LAB_OUT_UNKNOWN = 0,
|
|
LAB_OUT_FILLED,
|
|
LAB_OUT_PARTIAL_CANCELED,
|
|
LAB_OUT_PARTIAL_EXPIRED,
|
|
LAB_OUT_CANCELED_NO_FILL,
|
|
LAB_OUT_EXPIRED_NO_FILL,
|
|
LAB_OUT_REJECTED,
|
|
LAB_OUT_PENDING_PLACED,
|
|
LAB_OUT_PENDING_DELETED,
|
|
LAB_OUT_POSITION_CLOSED,
|
|
LAB_OUT_UNEXPECTED_ACTIVATION
|
|
};
|
|
|
|
enum ENUM_LAB_FINAL_SOURCE
|
|
{
|
|
LAB_FINAL_NONE = 0,
|
|
LAB_FINAL_SYNC_RETURN_REJECTION,
|
|
LAB_FINAL_REQUEST_REJECTION,
|
|
LAB_FINAL_CALLBACK_CHECK,
|
|
LAB_FINAL_TIMER_CHECK
|
|
};
|
|
|
|
enum ENUM_LAB_MARKET_REGIME
|
|
{
|
|
LAB_REGIME_QUIET = 0,
|
|
LAB_REGIME_FAST,
|
|
LAB_REGIME_INTERMEDIATE,
|
|
LAB_REGIME_UNKNOWN
|
|
};
|
|
|
|
enum ENUM_LAB_CHECK_STATUS
|
|
{
|
|
LAB_CHECK_NOT_RUN = 0,
|
|
LAB_CHECK_PASS,
|
|
LAB_CHECK_FAIL,
|
|
LAB_CHECK_NOT_APPLICABLE
|
|
};
|
|
|
|
enum ENUM_LAB_SEVERITY
|
|
{
|
|
LAB_SEV_INFO = 0,
|
|
LAB_SEV_WARNING,
|
|
LAB_SEV_BLOCKER
|
|
};
|
|
|
|
enum ENUM_LAB_COMPONENT
|
|
{
|
|
LAB_COMP_NONE = 0,
|
|
LAB_COMP_CONFIG,
|
|
LAB_COMP_PLANNER,
|
|
LAB_COMP_TRACKER,
|
|
LAB_COMP_JOURNAL,
|
|
LAB_COMP_READER,
|
|
LAB_COMP_COMPLETION,
|
|
LAB_COMP_MARKET,
|
|
LAB_COMP_STATS,
|
|
LAB_COMP_CSV,
|
|
LAB_COMP_REPORT,
|
|
LAB_COMP_PANEL,
|
|
LAB_COMP_CONTROLLER,
|
|
LAB_COMP_TRADE_TOOLS,
|
|
LAB_COMP_MODELS
|
|
};
|
|
|
|
enum ENUM_LAB_RECORD_KIND
|
|
{
|
|
LAB_KIND_RUN_START = 0,
|
|
LAB_KIND_RUN_STATE,
|
|
LAB_KIND_SLOT_STATUS,
|
|
LAB_KIND_PRECHECK,
|
|
LAB_KIND_DISPATCH_INTENT,
|
|
LAB_KIND_INTENT_SUPERSEDED,
|
|
LAB_KIND_SEND_START,
|
|
LAB_KIND_SEND_RETURN,
|
|
LAB_KIND_TRADE_TRANSACTION,
|
|
LAB_KIND_CORRELATION_LINK,
|
|
LAB_KIND_CORRELATION_CONFLICT,
|
|
LAB_KIND_HISTORY_SCAN,
|
|
LAB_KIND_CONFIRMATION_SNAPSHOT,
|
|
LAB_KIND_DEADLINE_EVALUATION,
|
|
LAB_KIND_COLLECTION_CLOSE,
|
|
LAB_KIND_CORRECTION,
|
|
LAB_KIND_TIMER,
|
|
LAB_KIND_WAIT,
|
|
LAB_KIND_LOG_EMITTED,
|
|
LAB_KIND_SAFETY_BLOCK,
|
|
LAB_KIND_INTERVENTION,
|
|
LAB_KIND_CHECKPOINT,
|
|
LAB_KIND_RUN_END
|
|
};
|
|
|
|
enum ENUM_LAB_METRIC
|
|
{
|
|
LAB_METRIC_CALL_DURATION = 0, // T1-T0
|
|
LAB_METRIC_REQUEST_DELAY, // T2-T0
|
|
LAB_METRIC_ORDER_DELAY, // T3-T0
|
|
LAB_METRIC_FIRST_DEAL_DELAY, // T4-T0
|
|
LAB_METRIC_LAST_DEAL_DELAY, // T5-T0 (только при полном покрытии)
|
|
LAB_METRIC_FINAL_STATE_DELAY, // T6-T0
|
|
LAB_METRIC_REMAINING_AFTER_RETURN, // T6-T1
|
|
LAB_METRIC_REQUEST_FIRST_DEAL_OFFSET // T2-T4, знаковая
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Маски наличия T0..T6 (бит 1<<index, включая T5). |
|
|
//+------------------------------------------------------------------+
|
|
enum ENUM_LAB_MASK
|
|
{
|
|
LAB_MASK_T0 = 1,
|
|
LAB_MASK_T1 = 2,
|
|
LAB_MASK_T2 = 4,
|
|
LAB_MASK_T3 = 8,
|
|
LAB_MASK_T4 = 16,
|
|
LAB_MASK_T5 = 32,
|
|
LAB_MASK_T6 = 64
|
|
};
|
|
|
|
enum ENUM_LAB_READ_STATUS
|
|
{
|
|
LAB_READ_UNKNOWN = 0,
|
|
LAB_READ_FOUND,
|
|
LAB_READ_ABSENT_CONFIRMED,
|
|
LAB_READ_FAILED
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Ошибка лаборатории (bool = технический успех метода). |
|
|
//+------------------------------------------------------------------+
|
|
struct LabError
|
|
{
|
|
ENUM_LAB_COMPONENT component;
|
|
int code; // код лаборатории; 0 = успех
|
|
string record_key; // session/sequence при наличии
|
|
int mql_error; // GetLastError() при наличии
|
|
string message;
|
|
ENUM_LAB_SEVERITY severity;
|
|
|
|
void Reset(void);
|
|
bool IsOk() const { return(code == 0); }
|
|
};
|
|
|
|
string LabResultString(const bool ok, const LabError &error);
|
|
string LabMetricName(const ENUM_LAB_METRIC metric);
|
|
string LabOutcomeName(const ENUM_LAB_OUTCOME outcome);
|
|
string LabFitnessName(const ENUM_LAB_FITNESS fitness);
|
|
string LabRegimeName(const ENUM_LAB_MARKET_REGIME regime);
|
|
string LabRoleName(const ENUM_LAB_ROLE role);
|
|
string LabOperationName(const ENUM_LAB_OPERATION op);
|
|
string LabCorrelationName(const ENUM_LAB_CORRELATION corr);
|
|
string LabExperimentName(const ENUM_LAB_EXPERIMENT exp);
|
|
//+------------------------------------------------------------------+
|
|
//| Реализации строковых справочников (символьные имена, ТЗ §4.2). |
|
|
//+------------------------------------------------------------------+
|
|
string LabResultString(const bool ok, const LabError &error)
|
|
{
|
|
if(ok)
|
|
return("ok");
|
|
string s = error.message;
|
|
if(StringLen(s) > 0)
|
|
s += " | ";
|
|
s += StringFormat("comp=%d code=%d mql=%d", (int)error.component, error.code, error.mql_error);
|
|
return(s);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Строковое имя метрики |
|
|
//+------------------------------------------------------------------+
|
|
string LabMetricName(const ENUM_LAB_METRIC metric)
|
|
{
|
|
switch(metric)
|
|
{
|
|
case LAB_METRIC_CALL_DURATION:
|
|
return("call_duration_us");
|
|
case LAB_METRIC_REQUEST_DELAY:
|
|
return("request_delay_us");
|
|
case LAB_METRIC_ORDER_DELAY:
|
|
return("order_delay_us");
|
|
case LAB_METRIC_FIRST_DEAL_DELAY:
|
|
return("first_deal_delay_us");
|
|
case LAB_METRIC_LAST_DEAL_DELAY:
|
|
return("last_deal_delay_us");
|
|
case LAB_METRIC_FINAL_STATE_DELAY:
|
|
return("final_state_delay_us");
|
|
case LAB_METRIC_REMAINING_AFTER_RETURN:
|
|
return("remaining_after_return_us");
|
|
case LAB_METRIC_REQUEST_FIRST_DEAL_OFFSET:
|
|
return("request_first_deal_offset_us");
|
|
}
|
|
return("unknown_metric");
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Строковое имя исхода |
|
|
//+------------------------------------------------------------------+
|
|
string LabOutcomeName(const ENUM_LAB_OUTCOME outcome)
|
|
{
|
|
switch(outcome)
|
|
{
|
|
case LAB_OUT_UNKNOWN:
|
|
return("UNKNOWN");
|
|
case LAB_OUT_FILLED:
|
|
return("FILLED");
|
|
case LAB_OUT_PARTIAL_CANCELED:
|
|
return("PARTIAL_CANCELED");
|
|
case LAB_OUT_PARTIAL_EXPIRED:
|
|
return("PARTIAL_EXPIRED");
|
|
case LAB_OUT_CANCELED_NO_FILL:
|
|
return("CANCELED_NO_FILL");
|
|
case LAB_OUT_EXPIRED_NO_FILL:
|
|
return("EXPIRED_NO_FILL");
|
|
case LAB_OUT_REJECTED:
|
|
return("REJECTED");
|
|
case LAB_OUT_PENDING_PLACED:
|
|
return("PENDING_PLACED");
|
|
case LAB_OUT_PENDING_DELETED:
|
|
return("PENDING_DELETED");
|
|
case LAB_OUT_POSITION_CLOSED:
|
|
return("POSITION_CLOSED");
|
|
case LAB_OUT_UNEXPECTED_ACTIVATION:
|
|
return("UNEXPECTED_ACTIVATION");
|
|
}
|
|
return("UNKNOWN");
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Строковое имя fitness-категории |
|
|
//+------------------------------------------------------------------+
|
|
string LabFitnessName(const ENUM_LAB_FITNESS fitness)
|
|
{
|
|
switch(fitness)
|
|
{
|
|
case LAB_FIT_CONFLICT:
|
|
return("CONFLICT");
|
|
case LAB_FIT_INTERRUPTED:
|
|
return("INTERRUPTED");
|
|
case LAB_FIT_LATE:
|
|
return("LATE");
|
|
case LAB_FIT_MISSING:
|
|
return("MISSING");
|
|
case LAB_FIT_VALID:
|
|
return("VALID");
|
|
}
|
|
return("UNKNOWN");
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Строковое имя статуса чтения |
|
|
//+------------------------------------------------------------------+
|
|
string LabReadStatusName(const ENUM_LAB_READ_STATUS st)
|
|
{
|
|
switch(st)
|
|
{
|
|
case LAB_READ_UNKNOWN:
|
|
return("UNKNOWN");
|
|
case LAB_READ_FOUND:
|
|
return("FOUND");
|
|
case LAB_READ_ABSENT_CONFIRMED:
|
|
return("ABSENT_CONFIRMED");
|
|
case LAB_READ_FAILED:
|
|
return("FAILED");
|
|
}
|
|
return("UNKNOWN");
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Строковое имя рыночного режима |
|
|
//+------------------------------------------------------------------+
|
|
string LabRegimeName(const ENUM_LAB_MARKET_REGIME regime)
|
|
{
|
|
switch(regime)
|
|
{
|
|
case LAB_REGIME_QUIET:
|
|
return("QUIET");
|
|
case LAB_REGIME_FAST:
|
|
return("FAST");
|
|
case LAB_REGIME_INTERMEDIATE:
|
|
return("INTERMEDIATE");
|
|
case LAB_REGIME_UNKNOWN:
|
|
return("UNKNOWN");
|
|
}
|
|
return("UNKNOWN");
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Строковое имя роли |
|
|
//+------------------------------------------------------------------+
|
|
string LabRoleName(const ENUM_LAB_ROLE role)
|
|
{
|
|
switch(role)
|
|
{
|
|
case LAB_ROLE_MAIN:
|
|
return("MAIN");
|
|
case LAB_ROLE_WARMUP:
|
|
return("WARMUP");
|
|
case LAB_ROLE_CLEANUP:
|
|
return("CLEANUP");
|
|
case LAB_ROLE_PILOT:
|
|
return("PILOT");
|
|
case LAB_ROLE_SYNTHETIC:
|
|
return("SYNTHETIC");
|
|
}
|
|
return("UNKNOWN");
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Строковое имя операции |
|
|
//+------------------------------------------------------------------+
|
|
string LabOperationName(const ENUM_LAB_OPERATION op)
|
|
{
|
|
switch(op)
|
|
{
|
|
case LAB_OP_NONE:
|
|
return("NONE");
|
|
case LAB_OP_MARKET_OPEN:
|
|
return("MARKET_OPEN");
|
|
case LAB_OP_PENDING_CREATE:
|
|
return("PENDING_CREATE");
|
|
case LAB_OP_PENDING_DELETE:
|
|
return("PENDING_DELETE");
|
|
case LAB_OP_POSITION_CLOSE:
|
|
return("POSITION_CLOSE");
|
|
}
|
|
return("NONE");
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Строковое имя корреляции |
|
|
//+------------------------------------------------------------------+
|
|
string LabCorrelationName(const ENUM_LAB_CORRELATION corr)
|
|
{
|
|
switch(corr)
|
|
{
|
|
case LAB_CORR_UNRESOLVED:
|
|
return("UNRESOLVED");
|
|
case LAB_CORR_EXACT:
|
|
return("EXACT");
|
|
case LAB_CORR_AMBIGUOUS:
|
|
return("AMBIGUOUS");
|
|
case LAB_CORR_FOREIGN:
|
|
return("FOREIGN");
|
|
case LAB_CORR_CONFLICT:
|
|
return("CONFLICT");
|
|
}
|
|
return("UNRESOLVED");
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Строковое имя эксперимента |
|
|
//+------------------------------------------------------------------+
|
|
string LabExperimentName(const ENUM_LAB_EXPERIMENT exp)
|
|
{
|
|
switch(exp)
|
|
{
|
|
case LAB_EXP_E1:
|
|
return("E1");
|
|
case LAB_EXP_E2:
|
|
return("E2");
|
|
case LAB_EXP_E3:
|
|
return("E3");
|
|
case LAB_EXP_E4:
|
|
return("E4");
|
|
case LAB_EXP_E5:
|
|
return("E5");
|
|
}
|
|
return("E?");
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Сопутствующие структуры |
|
|
//+------------------------------------------------------------------+
|
|
struct RequestKey
|
|
{
|
|
string session_id;
|
|
ulong sequence;
|
|
|
|
string ToString() const { return(session_id + "/" + IntegerToString(sequence)); }
|
|
void Zero() { session_id = ""; sequence = 0; }
|
|
};
|
|
|
|
struct SymbolRules
|
|
{
|
|
string symbol;
|
|
int digits;
|
|
double point;
|
|
double tick_size;
|
|
double volume_min;
|
|
double volume_max;
|
|
double volume_step;
|
|
long filling_mode;
|
|
long trade_mode;
|
|
double bid;
|
|
double ask;
|
|
|
|
bool IsValid() const { return(StringLen(symbol) > 0 && tick_size > 0.0 && volume_step > 0.0); }
|
|
};
|
|
|
|
struct RequestPlan
|
|
{
|
|
ulong slot_id;
|
|
ENUM_LAB_EXPERIMENT experiment_id;
|
|
uint series_id;
|
|
string condition_id; // "A" или "B"
|
|
uint block_id;
|
|
ENUM_LAB_ROLE role;
|
|
ENUM_LAB_OPERATION operation;
|
|
ENUM_LAB_SIDE side;
|
|
ENUM_LAB_MODE mode;
|
|
ENUM_LAB_LOGGING logging_mode;
|
|
ulong planned_order;
|
|
ulong sequence; // зарезервированный номер попытки
|
|
ulong parent_sequence; // для CLEANUP
|
|
string symbol;
|
|
double volume;
|
|
double request_price;
|
|
double distance_ticks; // D для PENDING_CREATE
|
|
ulong magic;
|
|
//--- S1 (audit-3): фактические сопутствующие данные запроса
|
|
int deviation_points; // slippage (из настроек)
|
|
string comment; // фактический comment запроса
|
|
long actual_type; // фактический ORDER_TYPE
|
|
long actual_filling; // фактический type_filling
|
|
bool actual_known; // R5-S2: факт заполнения actual_*
|
|
|
|
void Zero(void);
|
|
};
|
|
|
|
struct SendObservation
|
|
{
|
|
ulong t0_us; // T0
|
|
ulong t1_us; // T1
|
|
bool send_ok;
|
|
MqlTradeResult result;
|
|
int last_error;
|
|
bool result_known; // RETURN наблюдался
|
|
|
|
void Zero(void);
|
|
};
|
|
|
|
struct TransactionObservation
|
|
{
|
|
ulong entry_us; // метка входа в OnTradeTransaction
|
|
MqlTradeTransaction trans;
|
|
MqlTradeRequest request; // содержательно только для REQUEST
|
|
MqlTradeResult result; // содержательно только для REQUEST
|
|
bool has_request;
|
|
bool has_result;
|
|
ulong handler_exit_us;
|
|
ulong trade_event_id;
|
|
ulong target_sequence;
|
|
|
|
void Zero(void);
|
|
};
|
|
|
|
struct DealRecord
|
|
{
|
|
ulong deal_ticket;
|
|
ulong order_ticket;
|
|
ulong owner_sequence; // исполняющий запрос (не DELETE)
|
|
string symbol;
|
|
long deal_type; // ENUM_DEAL_TYPE
|
|
long entry; // ENUM_DEAL_ENTRY
|
|
long reason; // ENUM_DEAL_REASON
|
|
ulong magic;
|
|
ulong position_ticket;
|
|
ulong position_identifier;
|
|
bool has_callback;
|
|
ulong callback_first_us;
|
|
ulong callback_event_id;
|
|
double callback_volume;
|
|
double history_volume;
|
|
double history_price;
|
|
long deal_time_msc;
|
|
ulong history_read_event_id;
|
|
bool recovered;
|
|
uint correction_count;
|
|
bool deleted;
|
|
|
|
void Zero(void);
|
|
};
|
|
|
|
struct PositionFacts
|
|
{
|
|
ulong ticket;
|
|
ulong identifier;
|
|
long type;
|
|
double volume;
|
|
ulong magic;
|
|
string symbol;
|
|
bool read_status;
|
|
|
|
void Zero(void);
|
|
};
|
|
|
|
struct ConfirmationSnapshot
|
|
{
|
|
ulong sequence;
|
|
ulong check_start_us;
|
|
ulong check_end_us; // = T6 первой успешной проверки
|
|
ENUM_LAB_FINAL_SOURCE trigger;
|
|
ulong trigger_event_id;
|
|
int api_errors;
|
|
bool trading_state_known;
|
|
ulong order_ticket;
|
|
int active_select_status; // ENUM_LAB_READ_STATUS
|
|
int history_select_status; // ENUM_LAB_READ_STATUS
|
|
int active_select_error; // GetLastError() активного select (B4)
|
|
int history_order_error; // GetLastError() history select (B4)
|
|
bool history_scan_failed; // B6: HistorySelect/HistoryDealsTotal ошибка
|
|
uint reject_retcode; // B7: retcode sync-return/REQUEST для reject
|
|
long order_state_before;
|
|
long order_state_after;
|
|
double requested_volume_units;
|
|
double initial_volume_units;
|
|
double remaining_volume_units;
|
|
double executed_volume_units;
|
|
ulong deal_tickets[64];
|
|
double deal_volumes_units[64];
|
|
int deal_count;
|
|
int callback_ticket_count;
|
|
bool light_snapshot; // R6-B1: true = световая сверка (без тикетов)
|
|
bool coverage_complete;
|
|
double position_volume;
|
|
bool position_found;
|
|
long position_type;
|
|
ulong position_ticket;
|
|
ulong position_identifier;
|
|
ENUM_LAB_OPERATION expected_operation;
|
|
ENUM_LAB_OUTCOME previous_outcome;
|
|
bool confirmed;
|
|
ENUM_LAB_OUTCOME outcome;
|
|
string reason_code;
|
|
ulong evidence_event_ids[16];
|
|
int evidence_count;
|
|
PositionFacts position_facts_last;
|
|
//--- R4 (audit-4): фактические поля ордера из select (S2/S3)
|
|
string order_symbol; // фактический символ ордера
|
|
long order_type; // фактический ORDER_TYPE (ENUM_ORDER_TYPE)
|
|
ulong order_magic; // фактический magic ордера
|
|
double order_volume_lots; // фактический объём ордера (лоты)
|
|
double order_price; // фактическая цена ордера (ORDER_PRICE_OPEN)
|
|
//--- R4 (audit-4): ожидаемый контракт запроса для сверки (R4-S2)
|
|
string expected_symbol;
|
|
ulong expected_magic;
|
|
double expected_volume_lots;
|
|
double expected_price;
|
|
double price_tolerance; // допуск сравнения цены (доли тика)
|
|
long expected_order_type; // R5-B8: ожидаемый точный ORDER_TYPE
|
|
|
|
void Zero(void);
|
|
};
|
|
|
|
struct MetricObservation
|
|
{
|
|
ENUM_LAB_APPLICABILITY applicability;
|
|
ENUM_LAB_FITNESS category; // эффективная категория
|
|
string reason_codes;
|
|
ulong start_event_id;
|
|
ulong end_event_id;
|
|
ulong start_us;
|
|
ulong end_us;
|
|
long value_us; // значение метрики (знаковая для offset)
|
|
bool has_value;
|
|
ulong snapshot_event_id;
|
|
bool post_close_valid;
|
|
long post_close_value_us;
|
|
|
|
void Zero(void);
|
|
};
|
|
|
|
struct MarketWindow
|
|
{
|
|
string dataset_id;
|
|
string window_id;
|
|
string session_id;
|
|
ulong sequence;
|
|
string calibration_id;
|
|
string symbol;
|
|
long anchor_tick_msc;
|
|
long from_msc;
|
|
long to_msc;
|
|
ulong fetch_start_us;
|
|
ulong fetch_end_us;
|
|
ulong calculation_end_us;
|
|
ulong age_at_send_us;
|
|
int copy_last_error;
|
|
bool range_complete;
|
|
ulong n_returned;
|
|
ulong n_valid_info;
|
|
double mid_min;
|
|
double mid_max;
|
|
double tick_size;
|
|
double quote_frequency_hz;
|
|
double mid_range_ticks;
|
|
ENUM_LAB_MARKET_REGIME regime;
|
|
bool valid;
|
|
string quality_codes;
|
|
ulong ticks_checksum; // R8-S2: FNV-1a по (time_msc,bid,ask) валидных INFO-тиков
|
|
|
|
void Zero(void);
|
|
};
|
|
|
|
struct Calibration
|
|
{
|
|
string calibration_id;
|
|
string symbol;
|
|
long period_from_msc;
|
|
long period_to_msc;
|
|
string calendar_time_scale;
|
|
string trading_sessions;
|
|
int valid_window_count;
|
|
int invalid_window_count;
|
|
int trading_session_count; // S5: число отдельных торговых сессий
|
|
double frequency_p50;
|
|
double frequency_p90;
|
|
double range_p50;
|
|
double range_p90;
|
|
bool valid;
|
|
string quality_codes;
|
|
|
|
void Zero(void);
|
|
};
|
|
|
|
struct LabEvent
|
|
{
|
|
string session_id;
|
|
ulong event_sequence;
|
|
ENUM_LAB_RECORD_KIND kind;
|
|
ulong local_time_us;
|
|
ulong origin_sequence;
|
|
ulong target_sequence;
|
|
ulong ref_event_sequence;
|
|
string transaction_type;
|
|
uint request_id;
|
|
ulong order_ticket;
|
|
ulong deal_ticket;
|
|
ulong position_ticket;
|
|
ulong handler_enter_us;
|
|
ulong handler_exit_us;
|
|
string payload_json;
|
|
string quality_code;
|
|
|
|
void Zero(void);
|
|
};
|
|
|
|
struct RunManifest
|
|
{
|
|
string campaign_id;
|
|
string session_id;
|
|
ENUM_LAB_EXPERIMENT experiment_id;
|
|
uint series_id;
|
|
string configuration_id;
|
|
string symbol;
|
|
ulong magic;
|
|
string data_origin;
|
|
ulong seed;
|
|
string run_status;
|
|
string stop_reason;
|
|
ulong n_main_dispatched;
|
|
ulong n_warmup_dispatched;
|
|
ulong n_cleanup_dispatched;
|
|
ulong n_pilot_dispatched;
|
|
ulong n_dispatch_uncertain;
|
|
ulong records_attempted;
|
|
ulong records_accepted;
|
|
ulong records_persisted;
|
|
ulong records_lost;
|
|
string source_commit;
|
|
bool source_dirty;
|
|
string source_package_sha256;
|
|
|
|
void Zero(void);
|
|
};
|
|
|
|
struct CheckRecord
|
|
{
|
|
string check_id;
|
|
string case_key;
|
|
ENUM_LAB_CHECK_STATUS status;
|
|
ENUM_LAB_SEVERITY severity;
|
|
string expected;
|
|
string actual;
|
|
string reason_code;
|
|
string source_ref;
|
|
string evidence_path;
|
|
|
|
void Zero(void);
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Внешние определения методов структур (вынесены из тел). |
|
|
//+------------------------------------------------------------------+
|
|
void LabError::Reset(void)
|
|
{
|
|
component = LAB_COMP_NONE;
|
|
code = 0;
|
|
record_key = "";
|
|
mql_error = 0;
|
|
message = "";
|
|
severity = LAB_SEV_INFO;
|
|
}
|
|
void RequestPlan::Zero(void)
|
|
{
|
|
slot_id = 0;
|
|
experiment_id = LAB_EXP_E1;
|
|
series_id = 0;
|
|
condition_id = "";
|
|
block_id = 0;
|
|
role = LAB_ROLE_MAIN;
|
|
operation = LAB_OP_NONE;
|
|
side = LAB_SIDE_NONE;
|
|
mode = LAB_MODE_SYNC;
|
|
logging_mode = LAB_LOG_MINIMAL;
|
|
planned_order = 0;
|
|
sequence = 0;
|
|
parent_sequence = 0;
|
|
symbol = "";
|
|
volume = 0.0;
|
|
request_price = 0.0;
|
|
distance_ticks = 0.0;
|
|
magic = 0;
|
|
deviation_points = 0;
|
|
comment = "";
|
|
actual_type = 0;
|
|
actual_filling = 0;
|
|
actual_known = false;
|
|
}
|
|
void SendObservation::Zero(void)
|
|
{
|
|
t0_us = 0;
|
|
t1_us = 0;
|
|
send_ok = false;
|
|
ZeroMemory(result);
|
|
last_error = 0;
|
|
result_known = false;
|
|
}
|
|
void TransactionObservation::Zero(void)
|
|
{
|
|
entry_us = 0;
|
|
ZeroMemory(trans);
|
|
ZeroMemory(request);
|
|
ZeroMemory(result);
|
|
has_request = false;
|
|
has_result = false;
|
|
handler_exit_us = 0;
|
|
trade_event_id = 0;
|
|
target_sequence = 0;
|
|
}
|
|
void DealRecord::Zero(void)
|
|
{
|
|
deal_ticket = 0;
|
|
order_ticket = 0;
|
|
owner_sequence = 0;
|
|
symbol = "";
|
|
deal_type = 0;
|
|
entry = 0;
|
|
reason = 0;
|
|
magic = 0;
|
|
position_ticket = 0;
|
|
position_identifier = 0;
|
|
has_callback = false;
|
|
callback_first_us = 0;
|
|
callback_event_id = 0;
|
|
callback_volume = 0.0;
|
|
history_volume = 0.0;
|
|
history_price = 0.0;
|
|
deal_time_msc = 0;
|
|
history_read_event_id = 0;
|
|
recovered = false;
|
|
correction_count = 0;
|
|
deleted = false;
|
|
}
|
|
void PositionFacts::Zero(void)
|
|
{
|
|
ticket = 0;
|
|
identifier = 0;
|
|
type = 0;
|
|
volume = 0.0;
|
|
magic = 0;
|
|
symbol = "";
|
|
read_status = false;
|
|
}
|
|
void ConfirmationSnapshot::Zero(void)
|
|
{
|
|
sequence = 0;
|
|
check_start_us = 0;
|
|
check_end_us = 0;
|
|
trigger = LAB_FINAL_NONE;
|
|
trigger_event_id = 0;
|
|
api_errors = 0;
|
|
trading_state_known = false;
|
|
order_ticket = 0;
|
|
active_select_status = LAB_READ_UNKNOWN;
|
|
history_select_status = LAB_READ_UNKNOWN;
|
|
active_select_error = 0;
|
|
history_order_error = 0;
|
|
history_scan_failed = false;
|
|
reject_retcode = 0;
|
|
order_state_before = 0;
|
|
order_state_after = 0;
|
|
requested_volume_units = 0.0;
|
|
initial_volume_units = 0.0;
|
|
remaining_volume_units = 0.0;
|
|
executed_volume_units = 0.0;
|
|
ArrayInitialize(deal_tickets, 0);
|
|
ArrayInitialize(deal_volumes_units, 0.0);
|
|
deal_count = 0;
|
|
callback_ticket_count = 0;
|
|
light_snapshot = false;
|
|
coverage_complete = false;
|
|
position_volume = 0.0;
|
|
position_found = false;
|
|
position_type = 0;
|
|
position_ticket = 0;
|
|
position_identifier = 0;
|
|
expected_operation = LAB_OP_NONE;
|
|
previous_outcome = LAB_OUT_UNKNOWN;
|
|
confirmed = false;
|
|
outcome = LAB_OUT_UNKNOWN;
|
|
reason_code = "";
|
|
ArrayInitialize(evidence_event_ids, 0);
|
|
evidence_count = 0;
|
|
position_facts_last.Zero();
|
|
order_symbol = "";
|
|
order_type = 0;
|
|
order_magic = 0;
|
|
order_volume_lots = 0.0;
|
|
order_price = 0.0;
|
|
expected_symbol = "";
|
|
expected_magic = 0;
|
|
expected_volume_lots = 0.0;
|
|
expected_price = 0.0;
|
|
price_tolerance = 0.0;
|
|
expected_order_type = 0;
|
|
}
|
|
void MetricObservation::Zero(void)
|
|
{
|
|
applicability = LAB_APP_UNKNOWN;
|
|
category = LAB_FIT_MISSING;
|
|
reason_codes = "";
|
|
start_event_id = 0;
|
|
end_event_id = 0;
|
|
start_us = 0;
|
|
end_us = 0;
|
|
value_us = 0;
|
|
has_value = false;
|
|
snapshot_event_id = 0;
|
|
post_close_valid = false;
|
|
post_close_value_us = 0;
|
|
}
|
|
void MarketWindow::Zero(void)
|
|
{
|
|
dataset_id = "";
|
|
window_id = "";
|
|
session_id = "";
|
|
sequence = 0;
|
|
calibration_id = "";
|
|
symbol = "";
|
|
anchor_tick_msc = 0;
|
|
from_msc = 0;
|
|
to_msc = 0;
|
|
fetch_start_us = 0;
|
|
fetch_end_us = 0;
|
|
calculation_end_us = 0;
|
|
age_at_send_us = 0;
|
|
copy_last_error = 0;
|
|
range_complete = false;
|
|
n_returned = 0;
|
|
n_valid_info = 0;
|
|
mid_min = 0.0;
|
|
mid_max = 0.0;
|
|
tick_size = 0.0;
|
|
quote_frequency_hz = 0.0;
|
|
mid_range_ticks = 0.0;
|
|
regime = LAB_REGIME_UNKNOWN;
|
|
valid = false;
|
|
quality_codes = "";
|
|
ticks_checksum = 0; // R8-S2
|
|
}
|
|
void Calibration::Zero(void)
|
|
{
|
|
calibration_id = "";
|
|
symbol = "";
|
|
period_from_msc = 0;
|
|
period_to_msc = 0;
|
|
calendar_time_scale = "";
|
|
trading_sessions = "";
|
|
valid_window_count = 0;
|
|
invalid_window_count = 0;
|
|
trading_session_count = 0;
|
|
frequency_p50 = 0.0;
|
|
frequency_p90 = 0.0;
|
|
range_p50 = 0.0;
|
|
range_p90 = 0.0;
|
|
valid = false;
|
|
quality_codes = "";
|
|
}
|
|
void LabEvent::Zero(void)
|
|
{
|
|
session_id = "";
|
|
event_sequence = 0;
|
|
kind = LAB_KIND_RUN_START;
|
|
local_time_us = 0;
|
|
origin_sequence = 0;
|
|
target_sequence = 0;
|
|
ref_event_sequence = 0;
|
|
transaction_type = "";
|
|
request_id = 0;
|
|
order_ticket = 0;
|
|
deal_ticket = 0;
|
|
position_ticket = 0;
|
|
handler_enter_us = 0;
|
|
handler_exit_us = 0;
|
|
payload_json = "";
|
|
quality_code = "";
|
|
}
|
|
void RunManifest::Zero(void)
|
|
{
|
|
campaign_id = "";
|
|
session_id = "";
|
|
experiment_id = LAB_EXP_E1;
|
|
series_id = 0;
|
|
configuration_id = "";
|
|
symbol = "";
|
|
magic = 0;
|
|
data_origin = "SYNTHETIC";
|
|
seed = 0;
|
|
run_status = "NOT_RUN";
|
|
stop_reason = "";
|
|
n_main_dispatched = 0;
|
|
n_warmup_dispatched = 0;
|
|
n_cleanup_dispatched = 0;
|
|
n_pilot_dispatched = 0;
|
|
n_dispatch_uncertain = 0;
|
|
records_attempted = 0;
|
|
records_accepted = 0;
|
|
records_persisted = 0;
|
|
records_lost = 0;
|
|
source_commit = "";
|
|
source_dirty = false;
|
|
source_package_sha256 = "";
|
|
}
|
|
void CheckRecord::Zero(void)
|
|
{
|
|
check_id = "";
|
|
case_key = "";
|
|
status = LAB_CHECK_NOT_RUN;
|
|
severity = LAB_SEV_INFO;
|
|
expected = "";
|
|
actual = "";
|
|
reason_code = "";
|
|
source_ref = "";
|
|
evidence_path = "";
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Дополнительные строковые справочники. |
|
|
//+------------------------------------------------------------------+
|
|
string LabFinalSourceName(const ENUM_LAB_FINAL_SOURCE s)
|
|
{
|
|
switch(s)
|
|
{
|
|
case LAB_FINAL_NONE:
|
|
return("NONE");
|
|
case LAB_FINAL_SYNC_RETURN_REJECTION:
|
|
return("SYNC_RETURN_REJECTION");
|
|
case LAB_FINAL_REQUEST_REJECTION:
|
|
return("REQUEST_REJECTION");
|
|
case LAB_FINAL_CALLBACK_CHECK:
|
|
return("CALLBACK_CHECK");
|
|
case LAB_FINAL_TIMER_CHECK:
|
|
return("TIMER_CHECK");
|
|
}
|
|
return("NONE");
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Строковое имя вида записи |
|
|
//+------------------------------------------------------------------+
|
|
string LabKindName(const ENUM_LAB_RECORD_KIND k)
|
|
{
|
|
switch(k)
|
|
{
|
|
case LAB_KIND_RUN_START:
|
|
return("RUN_START");
|
|
case LAB_KIND_RUN_STATE:
|
|
return("RUN_STATE");
|
|
case LAB_KIND_SLOT_STATUS:
|
|
return("SLOT_STATUS");
|
|
case LAB_KIND_PRECHECK:
|
|
return("PRECHECK");
|
|
case LAB_KIND_DISPATCH_INTENT:
|
|
return("DISPATCH_INTENT");
|
|
case LAB_KIND_INTENT_SUPERSEDED:
|
|
return("INTENT_SUPERSEDED");
|
|
case LAB_KIND_SEND_START:
|
|
return("SEND_START");
|
|
case LAB_KIND_SEND_RETURN:
|
|
return("SEND_RETURN");
|
|
case LAB_KIND_TRADE_TRANSACTION:
|
|
return("TRADE_TRANSACTION");
|
|
case LAB_KIND_CORRELATION_LINK:
|
|
return("CORRELATION_LINK");
|
|
case LAB_KIND_CORRELATION_CONFLICT:
|
|
return("CORRELATION_CONFLICT");
|
|
case LAB_KIND_HISTORY_SCAN:
|
|
return("HISTORY_SCAN");
|
|
case LAB_KIND_CONFIRMATION_SNAPSHOT:
|
|
return("CONFIRMATION_SNAPSHOT");
|
|
case LAB_KIND_DEADLINE_EVALUATION:
|
|
return("DEADLINE_EVALUATION");
|
|
case LAB_KIND_COLLECTION_CLOSE:
|
|
return("COLLECTION_CLOSE");
|
|
case LAB_KIND_CORRECTION:
|
|
return("CORRECTION");
|
|
case LAB_KIND_TIMER:
|
|
return("TIMER");
|
|
case LAB_KIND_WAIT:
|
|
return("WAIT");
|
|
case LAB_KIND_LOG_EMITTED:
|
|
return("LOG_EMITTED");
|
|
case LAB_KIND_SAFETY_BLOCK:
|
|
return("SAFETY_BLOCK");
|
|
case LAB_KIND_INTERVENTION:
|
|
return("INTERVENTION");
|
|
case LAB_KIND_CHECKPOINT:
|
|
return("CHECKPOINT");
|
|
case LAB_KIND_RUN_END:
|
|
return("RUN_END");
|
|
}
|
|
return("UNKNOWN");
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Строковое имя статуса слота |
|
|
//+------------------------------------------------------------------+
|
|
string LabSlotStatusName(const ENUM_LAB_SLOT_STATUS s)
|
|
{
|
|
switch(s)
|
|
{
|
|
case LAB_SLOT_PLANNED:
|
|
return("PLANNED");
|
|
case LAB_SLOT_INTENT_SAVED:
|
|
return("INTENT_SAVED");
|
|
case LAB_SLOT_DISPATCHED:
|
|
return("DISPATCHED");
|
|
case LAB_SLOT_PRECHECK_REJECTED:
|
|
return("PRECHECK_REJECTED");
|
|
case LAB_SLOT_CANCELED_BEFORE_DISPATCH:
|
|
return("CANCELED_BEFORE_DISPATCH");
|
|
case LAB_SLOT_DISPATCH_UNCERTAIN:
|
|
return("DISPATCH_UNCERTAIN");
|
|
case LAB_SLOT_WAIT:
|
|
return("WAIT");
|
|
}
|
|
return("PLANNED");
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Строковое имя статуса проверки |
|
|
//+------------------------------------------------------------------+
|
|
string LabCheckStatusName(const ENUM_LAB_CHECK_STATUS s)
|
|
{
|
|
switch(s)
|
|
{
|
|
case LAB_CHECK_NOT_RUN:
|
|
return("NOT_RUN");
|
|
case LAB_CHECK_PASS:
|
|
return("PASS");
|
|
case LAB_CHECK_FAIL:
|
|
return("FAIL");
|
|
case LAB_CHECK_NOT_APPLICABLE:
|
|
return("NOT_APPLICABLE");
|
|
}
|
|
return("NOT_RUN");
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Строковое имя уровня важности |
|
|
//+------------------------------------------------------------------+
|
|
string LabSeverityName(const ENUM_LAB_SEVERITY s)
|
|
{
|
|
switch(s)
|
|
{
|
|
case LAB_SEV_INFO:
|
|
return("INFO");
|
|
case LAB_SEV_WARNING:
|
|
return("WARNING");
|
|
case LAB_SEV_BLOCKER:
|
|
return("BLOCKER");
|
|
}
|
|
return("INFO");
|
|
}
|
|
|
|
#endif // REQUEST_LATENCY_LAB_MODELS_MQH
|
|
//+------------------------------------------------------------------+
|