NN_in_Trading/Experts/D2Skill/Test.mq5

594 satır
31 KiloByte
MQL5
HamKalıcı BağlantıNormal GörünümGeçmiş

2026-08-20 19:42:54 +03:00
//+------------------------------------------------------------------+
//| Test.mq5 |
//+------------------------------------------------------------------+
#property copyright "Copyright DNG®"
#property link "https://www.mql5.com/ru/users/dng"
#property version "1.00"
#property strict
#include "Trajectory.mqh"
//---
input group "---- D2Skill OOS ----"
input ENUM_D2SKILL_STAGE InpD2SkillStage = D2Skill_D2_STAGE_AUGMENTED; //Lifecycle stage
input ENUM_D2SKILL_MODE InpD2SkillExecutionMode = D2_INFERENCE; //Bank execution mode
2026-08-22 20:08:02 +03:00
input ED2SkillRepresentation InpD2SkillRepresentation = D2SkillDirectionMagnitude; //Bank representation
input bool InpD2SkillResetBanksOnRepresentationMismatch =
false; //Reset incompatible banks
input bool InpD2SkillRecreateIncompatibleCheckpoint =
false; //Recreate incompatible policy checkpoint
2026-08-20 19:42:54 +03:00
datetime Start = 0;
datetime End = 0;
int Epochs = 0;
CNet Actor;
CBufferFloat State, TimeState, Account, Action;
double PreviousBalance = 0, PreviousEquity = 0;
bool D2SkillTestInitialized = false;
ulong OOSTransitions = 0, OOSExecutableActions = 0;
double OOSInitialBalance = 0;
datetime OOSStartTime = 0;
double OOSInitialEquity = 0, OOSPeakEquity = 0, OOSMaximumDrawdown = 0;
double OOSReward = 0;
ulong OOSTradeCount = 0;
ulong OOSGpuBoundaryLatencyTotal = 0, OOSGpuBoundaryLatencyMaximum = 0;
ulong OOSGpuBoundaryLatencySamples = 0;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool D2SkillWriteD2OOSHeader(const int handle)
{
if(handle == INVALID_HANDLE)
ReturnFalse;
if(FileWrite(handle,
"run_time", "symbol", "timeframe", "stage", "stage_name",
"mode", "mode_name", "execution_mode", "execution_mode_name", "utility_aware", "min_utility", "utility_scale",
"utility_source", "initial_balance", "final_balance", "initial_equity",
"final_equity", "reward_equity_delta", "pnl_balance_delta", "max_drawdown",
"max_drawdown_percent", "closed_trades", "transitions", "executable_actions",
"comparison_eligible", "task_diagnostics_valid", "task_diagnostics_error",
"task_retrievals", "task_no_skill", "task_retrieval_rate", "task_no_skill_rate",
"task_promotions", "task_replacements", "step_diagnostics_valid",
"step_diagnostics_error", "step_retrievals", "step_no_skill",
"step_retrieval_rate", "step_no_skill_rate", "step_promotions",
"step_replacements", "gpu_boundary_latency_us_avg", "gpu_boundary_latency_us_max",
"paired_terminal_updates", "task_selection_valid", "selected_task_slot",
"selected_task_score", "step_selection_valid", "selected_step_slot",
"selected_step_score") <= 0)
ReturnFalse;
return(true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
string D2SkillD2StageToString(const int stage)
{
if(stage == D2Skill_D2_STAGE_BASE)
return("base");
if(stage == D2Skill_D2_STAGE_FORMATION)
return("formation");
if(stage == D2Skill_D2_STAGE_HINDSIGHT)
return("hindsight");
if(stage == D2Skill_D2_STAGE_AUGMENTED)
return("augmented");
if(stage == D2Skill_D2_STAGE_ONLINE)
return("online");
return("unknown");
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
string D2SkillD2ModeToString(const ENUM_D2SKILL_BANK_MODE mode)
{
if(mode == D2Skill_D2_MODE_BASE)
return("base");
if(mode == D2Skill_D2_MODE_TASK)
return("task");
if(mode == D2Skill_D2_MODE_STEP)
return("step");
if(mode == D2Skill_D2_MODE_FULL)
return("full");
return("unknown");
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
string D2SkillD2ExecutionModeToString(const ENUM_D2SKILL_MODE mode)
{
switch(mode)
{
case D2_DISABLED:
return("disabled");
case D2_COLLECT:
return("collect");
case D2_EVALUATE:
return("evaluate");
case D2_INFERENCE:
return("inference");
case D2_ONLINE_CALIBRATION:
return("online_calibration");
}
return("unknown");
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
string D2SkillD2UtilitySource(void)
{
if(D2SkillD2UtilityMode == D2Skill_D2_UTILITY_PAIRED_HINDSIGHT)
return("paired_terminal");
return("disabled");
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool D2SkillReadD2Selection(const bool task_bank, int &selected_slot, float &selected_score)
{
selected_slot = -1;
selected_score = 0.0f;
CNeuronBaseOCL *layer = Actor.Layer(1);
if(!layer || layer.Type() != defNeuronD2Skill)
ReturnFalse;
CD2Skill *skill = (CD2Skill*)layer;
if(!skill || !skill.Ready())
ReturnFalse;
CD2SkillBank *bank = (task_bank ? skill.TaskBank() : skill.StepBank());
2026-08-26 18:00:29 +03:00
if(!bank)
ReturnFalse;
//--- BASE/disabled branches intentionally expose no device selection state.
//--- OOS renders this normal control flow as selection_unavailable / NA.
if(!bank.Enabled())
return(false);
if(!bank.SelectedSlot() || !bank.SelectedScore())
2026-08-20 19:42:54 +03:00
ReturnFalse;
if(!bank.SelectedSlot().BufferRead() || !bank.SelectedScore().BufferRead() ||
bank.SelectedSlot().Total() != 1 || bank.SelectedScore().Total() != 1)
ReturnFalse;
selected_slot = (int)bank.SelectedSlot()[0];
selected_score = bank.SelectedScore()[0];
return(selected_slot >= 0 && (uint)selected_slot < bank.Slots() &&
MathIsValidNumber(double(selected_score)) && selected_score > -1.0e30f);
}
//+------------------------------------------------------------------+
//| Reads diagnostic counters only at the OOS reporting boundary. |
//+------------------------------------------------------------------+
bool D2SkillReadD2OOSBankStats(const bool task_bank, ulong &retrievals,
ulong &no_skill, ulong &promotions,
ulong &replacements)
{
retrievals = 0;
no_skill = 0;
promotions = 0;
replacements = 0;
CNeuronBaseOCL *layer = Actor.Layer(1);
if(!layer || layer.Type() != defNeuronD2Skill)
ReturnFalse;
CD2Skill *skill = (CD2Skill*)layer;
if(!skill || !skill.Ready())
ReturnFalse;
CD2SkillBank *bank = (task_bank ? skill.TaskBank() : skill.StepBank());
2026-08-26 18:00:29 +03:00
//--- Base/disabled branches intentionally have no device diagnostics. Their
//--- counters remain zero and OOS reporting must not allocate scratch to read
//--- them.
if(!bank)
ReturnFalse;
if(!bank.Enabled())
return(true);
if(!bank.RefreshDiagnostics() || !bank.Diagnostics() ||
2026-08-20 19:42:54 +03:00
!bank.Diagnostics().BufferRead() || bank.Diagnostics().Total() != D2SKILL_DIAGNOSTICS)
ReturnFalse;
CBufferFloat *diagnostics = bank.Diagnostics();
retrievals = (ulong)MathMax(0.0, double(diagnostics[0]));
no_skill = (ulong)MathMax(0.0, double(diagnostics[1]));
promotions = (ulong)MathMax(0.0, double(diagnostics[4]));
replacements = (ulong)MathMax(0.0, double(diagnostics[7]));
return(true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
string D2SkillD2OOSCounterText(const bool valid, const ulong value)
{
return(valid ? StringFormat("%I64u", value) : "NA");
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
string D2SkillD2OOSRateText(const bool valid, const ulong numerator, const ulong denominator)
{
if(!valid)
return("NA");
return(StringFormat("%.8f", (denominator > 0 ? double(numerator) / denominator : 0.0)));
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
string D2SkillD2OOSReadError(const bool valid)
{
return(valid ? "none" : "bank_or_diagnostics_unavailable");
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool D2SkillWriteD2OOSBankConfiguration(const int handle, const string prefix,
CD2SkillBank *bank)
{
if(handle == INVALID_HANDLE)
ReturnFalse;
if(!bank)
{
FileWrite(handle, prefix + "_configuration_valid=false");
FileWrite(handle, prefix + "_configuration_error=bank_unavailable");
ReturnFalse;
}
FileWrite(handle, prefix + "_configuration_valid=true");
FileWrite(handle, StringFormat("%s_slots=%u", prefix, bank.Slots()));
FileWrite(handle, StringFormat("%s_dimension=%u", prefix, bank.Dimension()));
FileWrite(handle, StringFormat("%s_representation=%d", prefix, bank.Representation()));
FileWrite(handle, StringFormat("%s_alpha=%f", prefix, bank.Alpha()));
FileWrite(handle, StringFormat("%s_utility_aware=%s", prefix,
(bank.UtilityAware() ? "true" : "false")));
FileWrite(handle, StringFormat("%s_min_utility=%f", prefix, bank.MinUtility()));
FileWrite(handle, StringFormat("%s_max_correction=%f", prefix, bank.MaxCorrection()));
FileWrite(handle, StringFormat("%s_beta_correction=%f", prefix, bank.BetaCorrection()));
FileWrite(handle, StringFormat("%s_beta_direction=%f", prefix, bank.BetaDirection()));
FileWrite(handle, StringFormat("%s_beta_magnitude=%f", prefix, bank.BetaMagnitude()));
//--- The following values are the fixed D2SkillEnableD2Banks reconstruction
//--- contract; the Bank API intentionally has no duplicate read-only getters.
FileWrite(handle, prefix + "_top_k=1");
FileWrite(handle, prefix + "_similarity_threshold=0.65");
FileWrite(handle, prefix + "_direction_threshold=0.00");
FileWrite(handle, prefix + "_utility_weight=0.05");
FileWrite(handle, prefix + "_beta_key=0.05");
FileWrite(handle, prefix + "_beta_utility=0.05");
FileWrite(handle, prefix + "_min_confirmations=3");
FileWrite(handle, prefix + "_protection_age=32");
FileWrite(handle, prefix + "_inactivity_age=256");
return(true);
}
//+------------------------------------------------------------------+
//| Counts closed position exits in the exact tested symbol window. |
//+------------------------------------------------------------------+
ulong D2SkillOOSClosedTrades(void)
{
if(OOSStartTime <= 0 || !HistorySelect(OOSStartTime, TimeCurrent()))
return(0);
ulong trades = 0;
const uint total = HistoryDealsTotal();
for(uint index = 0; index < total; index++)
{
const ulong deal = HistoryDealGetTicket(index);
if(deal == 0 || HistoryDealGetString(deal, DEAL_SYMBOL) != _Symbol)
continue;
const ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(deal, DEAL_ENTRY);
if(entry == DEAL_ENTRY_OUT || entry == DEAL_ENTRY_OUT_BY || entry == DEAL_ENTRY_INOUT)
trades++;
}
return(trades);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool D2SkillAppendOOSResultRow(const double final_balance, const double final_equity)
{
const int handle = FileOpen(D2Skill_OOS_FILE,
FILE_WRITE | FILE_READ | FILE_CSV | FILE_ANSI | FILE_COMMON, ',');
if(handle == INVALID_HANDLE)
ReturnFalse;
const bool need_header = (FileSize(handle) <= 0);
FileSeek(handle, 0, SEEK_END);
if(need_header && !D2SkillWriteD2OOSHeader(handle))
{
FileClose(handle);
ReturnFalse;
}
int task_slot = -1, step_slot = -1;
float task_score = 0.0f;
float step_score = 0.0f;
const bool task_selection_valid = D2SkillReadD2Selection(true, task_slot, task_score);
const bool step_selection_valid = D2SkillReadD2Selection(false, step_slot, step_score);
ulong task_retrievals = 0, task_no_skill = 0, task_promotions = 0, task_replacements = 0;
ulong step_retrievals = 0, step_no_skill = 0, step_promotions = 0, step_replacements = 0;
const bool task_diagnostics_valid = D2SkillReadD2OOSBankStats(true, task_retrievals, task_no_skill,
task_promotions, task_replacements);
const bool step_diagnostics_valid = D2SkillReadD2OOSBankStats(false, step_retrievals, step_no_skill,
step_promotions, step_replacements);
const ulong task_total = task_retrievals + task_no_skill;
const ulong step_total = step_retrievals + step_no_skill;
if(!task_diagnostics_valid || !step_diagnostics_valid)
PrintFormat("D2Skill D2 OOS diagnostics unavailable: task=%s step=%s",
D2SkillD2OOSReadError(task_diagnostics_valid),
D2SkillD2OOSReadError(step_diagnostics_valid));
if(!task_selection_valid || !step_selection_valid)
PrintFormat("D2Skill D2 OOS selection unavailable: task=%s step=%s",
(task_selection_valid ? "none" : "selection_unavailable"),
(step_selection_valid ? "none" : "selection_unavailable"));
const double drawdown_percent = (OOSPeakEquity > 0.0 ?
100.0 * OOSMaximumDrawdown / OOSPeakEquity : 0.0);
const double average_latency = (OOSGpuBoundaryLatencySamples > 0 ?
double(OOSGpuBoundaryLatencyTotal) / OOSGpuBoundaryLatencySamples : 0.0);
FileWrite(handle,
TimeToString(TimeCurrent(), TIME_DATE | TIME_MINUTES | TIME_SECONDS),
_Symbol,
EnumToString((ENUM_TIMEFRAMES)Period()),
D2SkillD2Stage,
D2SkillD2StageToString(D2SkillD2Stage),
D2SkillD2Mode,
D2SkillD2ModeToString(D2SkillD2Mode),
D2SkillD2ExecutionMode,
D2SkillD2ExecutionModeToString(D2SkillD2ExecutionMode),
(D2SkillD2UtilityAware ? "true" : "false"),
D2SkillD2MinUtility,
D2SkillD2UtilityScale,
D2SkillD2UtilitySource(),
OOSInitialBalance,
final_balance,
OOSInitialEquity,
final_equity,
OOSReward,
(final_balance - OOSInitialBalance),
OOSMaximumDrawdown,
drawdown_percent,
OOSTradeCount,
OOSTransitions,
OOSExecutableActions,
(OOSExecutableActions > 0 ? "true" : "false"),
(task_diagnostics_valid ? "true" : "false"),
D2SkillD2OOSReadError(task_diagnostics_valid),
D2SkillD2OOSCounterText(task_diagnostics_valid, task_retrievals),
D2SkillD2OOSCounterText(task_diagnostics_valid, task_no_skill),
D2SkillD2OOSRateText(task_diagnostics_valid, task_retrievals, task_total),
D2SkillD2OOSRateText(task_diagnostics_valid, task_no_skill, task_total),
D2SkillD2OOSCounterText(task_diagnostics_valid, task_promotions),
D2SkillD2OOSCounterText(task_diagnostics_valid, task_replacements),
(step_diagnostics_valid ? "true" : "false"),
D2SkillD2OOSReadError(step_diagnostics_valid),
D2SkillD2OOSCounterText(step_diagnostics_valid, step_retrievals),
D2SkillD2OOSCounterText(step_diagnostics_valid, step_no_skill),
D2SkillD2OOSRateText(step_diagnostics_valid, step_retrievals, step_total),
D2SkillD2OOSRateText(step_diagnostics_valid, step_no_skill, step_total),
D2SkillD2OOSCounterText(step_diagnostics_valid, step_promotions),
D2SkillD2OOSCounterText(step_diagnostics_valid, step_replacements),
average_latency,
OOSGpuBoundaryLatencyMaximum,
D2SkillD2PairedUtilityUpdates,
(task_selection_valid ? "true" : "false"),
(task_selection_valid ? IntegerToString(task_slot) : "NA"),
(task_selection_valid ? DoubleToString(task_score, 8) : "NA"),
(step_selection_valid ? "true" : "false"),
(step_selection_valid ? IntegerToString(step_slot) : "NA"),
(step_selection_valid ? DoubleToString(step_score, 8) : "NA"));
FileClose(handle);
Print("D2Skill D2 OOS table: row appended to ", D2Skill_OOS_FILE);
return(true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool D2SkillWriteD2OOSManifest(const double final_balance, const double final_equity)
{
const int handle = FileOpen(D2Skill_OOS_MANIFEST_FILE, FILE_WRITE | FILE_TXT | FILE_ANSI | FILE_COMMON);
if(handle == INVALID_HANDLE)
ReturnFalse;
FileWrite(handle, "format=D2Skill_D2_OOS");
FileWrite(handle, StringFormat("run_time=%s", TimeToString(TimeCurrent(), TIME_DATE | TIME_MINUTES | TIME_SECONDS)));
FileWrite(handle, StringFormat("symbol=%s", _Symbol));
FileWrite(handle, StringFormat("timeframe=%s", EnumToString((ENUM_TIMEFRAMES)Period())));
FileWrite(handle, StringFormat("stage=%d", D2SkillD2Stage));
FileWrite(handle, StringFormat("stage_name=%s", D2SkillD2StageToString(D2SkillD2Stage)));
FileWrite(handle, StringFormat("mode=%d", D2SkillD2Mode));
FileWrite(handle, StringFormat("mode_name=%s", D2SkillD2ModeToString(D2SkillD2Mode)));
FileWrite(handle, StringFormat("execution_mode=%d", D2SkillD2ExecutionMode));
FileWrite(handle, StringFormat("execution_mode_name=%s",
D2SkillD2ExecutionModeToString(D2SkillD2ExecutionMode)));
FileWrite(handle, StringFormat("utility_aware=%s", (D2SkillD2UtilityAware ? "true" : "false")));
FileWrite(handle, StringFormat("min_utility=%f", D2SkillD2MinUtility));
FileWrite(handle, StringFormat("utility_scale=%f", D2SkillD2UtilityScale));
FileWrite(handle, StringFormat("utility_source=%s", D2SkillD2UtilitySource()));
FileWrite(handle, StringFormat("initial_balance=%f", OOSInitialBalance));
FileWrite(handle, StringFormat("final_balance=%f", final_balance));
FileWrite(handle, StringFormat("pnl=%f", final_balance - OOSInitialBalance));
FileWrite(handle, "reward_definition=equity_delta_accumulated_after_each_executed_transition");
FileWrite(handle, StringFormat("initial_equity=%f", OOSInitialEquity));
FileWrite(handle, StringFormat("final_equity=%f", final_equity));
FileWrite(handle, StringFormat("reward=%f", OOSReward));
FileWrite(handle, StringFormat("max_drawdown=%f", OOSMaximumDrawdown));
FileWrite(handle, StringFormat("max_drawdown_percent=%f",
(OOSPeakEquity > 0.0 ? 100.0 * OOSMaximumDrawdown / OOSPeakEquity : 0.0)));
FileWrite(handle, StringFormat("closed_trades=%I64u", OOSTradeCount));
FileWrite(handle, StringFormat("oos_transitions=%I64u", OOSTransitions));
FileWrite(handle, StringFormat("executable_actions=%I64u", OOSExecutableActions));
FileWrite(handle, StringFormat("comparison_eligible=%s",
(OOSExecutableActions > 0 ? "true" : "false")));
ulong task_retrievals = 0, task_no_skill = 0, task_promotions = 0, task_replacements = 0;
ulong step_retrievals = 0, step_no_skill = 0, step_promotions = 0, step_replacements = 0;
const bool task_diagnostics_valid = D2SkillReadD2OOSBankStats(true, task_retrievals, task_no_skill,
task_promotions, task_replacements);
const bool step_diagnostics_valid = D2SkillReadD2OOSBankStats(false, step_retrievals, step_no_skill,
step_promotions, step_replacements);
const ulong task_total = task_retrievals + task_no_skill;
const ulong step_total = step_retrievals + step_no_skill;
FileWrite(handle, StringFormat("task_diagnostics_valid=%s", (task_diagnostics_valid ? "true" : "false")));
FileWrite(handle, "task_diagnostics_error=" + D2SkillD2OOSReadError(task_diagnostics_valid));
FileWrite(handle, "task_retrievals=" + D2SkillD2OOSCounterText(task_diagnostics_valid, task_retrievals));
FileWrite(handle, "task_no_skill=" + D2SkillD2OOSCounterText(task_diagnostics_valid, task_no_skill));
FileWrite(handle, "task_retrieval_rate=" + D2SkillD2OOSRateText(task_diagnostics_valid, task_retrievals, task_total));
FileWrite(handle, "task_no_skill_rate=" + D2SkillD2OOSRateText(task_diagnostics_valid, task_no_skill, task_total));
FileWrite(handle, "task_promotions=" + D2SkillD2OOSCounterText(task_diagnostics_valid, task_promotions));
FileWrite(handle, "task_replacements=" + D2SkillD2OOSCounterText(task_diagnostics_valid, task_replacements));
FileWrite(handle, StringFormat("step_diagnostics_valid=%s", (step_diagnostics_valid ? "true" : "false")));
FileWrite(handle, "step_diagnostics_error=" + D2SkillD2OOSReadError(step_diagnostics_valid));
FileWrite(handle, "step_retrievals=" + D2SkillD2OOSCounterText(step_diagnostics_valid, step_retrievals));
FileWrite(handle, "step_no_skill=" + D2SkillD2OOSCounterText(step_diagnostics_valid, step_no_skill));
FileWrite(handle, "step_retrieval_rate=" + D2SkillD2OOSRateText(step_diagnostics_valid, step_retrievals, step_total));
FileWrite(handle, "step_no_skill_rate=" + D2SkillD2OOSRateText(step_diagnostics_valid, step_no_skill, step_total));
FileWrite(handle, "step_promotions=" + D2SkillD2OOSCounterText(step_diagnostics_valid, step_promotions));
FileWrite(handle, "step_replacements=" + D2SkillD2OOSCounterText(step_diagnostics_valid, step_replacements));
FileWrite(handle, "gpu_latency_definition=host_elapsed_us_Actor_feedForward_plus_ReadAction");
FileWrite(handle, StringFormat("gpu_boundary_latency_us_avg=%f",
(OOSGpuBoundaryLatencySamples > 0 ?
double(OOSGpuBoundaryLatencyTotal) / OOSGpuBoundaryLatencySamples : 0.0)));
FileWrite(handle, StringFormat("gpu_boundary_latency_us_max=%I64u", OOSGpuBoundaryLatencyMaximum));
FileWrite(handle, StringFormat("paired_utility_updates=%I64u", D2SkillD2PairedUtilityUpdates));
FileWrite(handle, StringFormat("forecast_signature=%I64u", D2SkillLastSignature));
FileWrite(handle, StringFormat("actor_file=%s", D2Skill_ACTOR_FILE));
FileWrite(handle, StringFormat("actor_hash_fnv64=%I64u",
D2SkillHashFile(ulong(1469598103934665603), D2Skill_ACTOR_FILE)));
FileWrite(handle, StringFormat("actor_critic_manifest=%s", D2Skill_AC_MANIFEST_FILE));
CNeuronBaseOCL *layer = Actor.Layer(1);
CD2Skill *skill = (layer && layer.Type() == defNeuronD2Skill ? (CD2Skill*)layer : NULL);
if(!skill || !skill.Ready())
{
D2SkillWriteD2OOSBankConfiguration(handle, "task", NULL);
D2SkillWriteD2OOSBankConfiguration(handle, "step", NULL);
}
else
{
D2SkillWriteD2OOSBankConfiguration(handle, "task", skill.TaskBank());
D2SkillWriteD2OOSBankConfiguration(handle, "step", skill.StepBank());
}
FileClose(handle);
Print("D2Skill D2 OOS manifest: ", D2Skill_OOS_MANIFEST_FILE);
return(true);
}
//+------------------------------------------------------------------+
//| Function OnInit. |
//+------------------------------------------------------------------+
int OnInit(void)
{
//--- Exact Forecast and six-artifact AC manifest/hash validation happens
//--- before loading/binding the Actor and before any possible policy forward.
D2SkillTestInitialized = false;
if(!D2SkillConfigureRuntime(InpD2SkillStage, InpD2SkillMode,
InpD2SkillExecutionMode, InpD2SkillUtilityAware,
2026-08-22 20:08:02 +03:00
InpD2SkillMinUtility, InpD2SkillUtilityScale,
false, false, InpD2SkillRepresentation,
InpD2SkillResetBanksOnRepresentationMismatch,
InpD2SkillRecreateIncompatibleCheckpoint))
2026-08-20 19:42:54 +03:00
{ Print("D2Skill test init: runtime configuration=FAIL"); return INIT_FAILED; }
if(!D2SkillInitIndicators())
{ Print("D2Skill test init: indicators=FAIL"); return INIT_FAILED; }
if(!Trade.SetTypeFillingBySymbol(Symb.Name()))
{ Print("D2Skill test init: trade filling=FAIL"); return INIT_FAILED; }
if(!D2SkillLoadForecastInference())
{ Print("D2Skill test init: forecast=FAIL"); return INIT_FAILED; }
if(!D2SkillLoadInferenceActor(Actor))
{ Print("D2Skill test init: actor checkpoint=FAIL"); return INIT_FAILED; }
if(!D2SkillVerifyFrozenForecastExact())
{ Print("D2Skill test init: frozen forecast=FAIL"); return INIT_FAILED; }
PreviousBalance = AccountInfoDouble(ACCOUNT_BALANCE);
PreviousEquity = AccountInfoDouble(ACCOUNT_EQUITY);
OOSInitialBalance = PreviousBalance;
OOSStartTime = TimeCurrent();
OOSInitialEquity = PreviousEquity;
OOSPeakEquity = PreviousEquity;
OOSMaximumDrawdown = 0;
OOSReward = 0;
OOSTradeCount = 0;
OOSTransitions = 0;
OOSExecutableActions = 0;
OOSGpuBoundaryLatencyTotal = 0;
OOSGpuBoundaryLatencyMaximum = 0;
OOSGpuBoundaryLatencySamples = 0;
D2SkillTestInitialized = true;
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Function OnDeinit. |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(!D2SkillTestInitialized)
{
D2SkillForecast = NULL;
return;
}
const double final_balance = AccountInfoDouble(ACCOUNT_BALANCE);
const double final_equity = AccountInfoDouble(ACCOUNT_EQUITY);
//--- Inference is pure: neither policy nor Forecast artifacts are saved.
if(D2SkillTestInitialized && D2SkillForecast != NULL && !D2SkillVerifyFrozenForecastExact())
PrintFormat("%s -> %d forecast mutation", __FUNCTION__, __LINE__);
if(D2SkillTestInitialized)
PrintFormat("D2Skill OOS summary: transitions=%I64u executable_actions=%I64u initial_balance=%.2f final_balance=%.2f",
OOSTransitions, OOSExecutableActions, OOSInitialBalance,
final_balance);
OOSTradeCount = D2SkillOOSClosedTrades();
const double drawdown_percent = (OOSPeakEquity > 0.0 ?
100.0 * OOSMaximumDrawdown / OOSPeakEquity : 0.0);
const double average_latency = (OOSGpuBoundaryLatencySamples > 0 ?
double(OOSGpuBoundaryLatencyTotal) / OOSGpuBoundaryLatencySamples : 0.0);
Print("D2 OOS_TABLE stage mode execution_mode utility_aware min_utility utility_scale transitions executable_actions initial_balance final_balance pnl");
PrintFormat("D2 OOS_TABLE_ROW stage=%d(%s) mode=%d(%s) execution=%d(%s) aware=%s min_utility=%.6f utility_scale=%.6f utility_source=%s reward=%.2f pnl=%.2f drawdown=%.2f drawdown_percent=%.6f closed_trades=%I64u gpu_boundary_latency_us_avg=%.3f gpu_boundary_latency_us_max=%I64u paired_terminal_updates=%I64u transitions=%I64u executable=%I64u initial_balance=%.2f final_balance=%.2f",
D2SkillD2Stage, D2SkillD2StageToString(D2SkillD2Stage),
D2SkillD2Mode, D2SkillD2ModeToString(D2SkillD2Mode),
D2SkillD2ExecutionMode, D2SkillD2ExecutionModeToString(D2SkillD2ExecutionMode),
(D2SkillD2UtilityAware ? "true" : "false"),
D2SkillD2MinUtility,
D2SkillD2UtilityScale, D2SkillD2UtilitySource(),
OOSReward, final_balance - OOSInitialBalance, OOSMaximumDrawdown,
drawdown_percent, OOSTradeCount, average_latency,
OOSGpuBoundaryLatencyMaximum,
D2SkillD2PairedUtilityUpdates,
OOSTransitions, OOSExecutableActions, OOSInitialBalance,
final_balance);
if(OOSExecutableActions == 0)
Print("D2Skill D2 OOS REJECT: executable_actions=0; Base/Task/Step/Full comparison is ineligible");
if(!D2SkillAppendOOSResultRow(final_balance, final_equity))
Print("D2Skill D2 OOS table: append failed");
if(!D2SkillWriteD2OOSManifest(final_balance, final_equity))
Print("D2Skill D2 OOS manifest: write failed");
D2SkillForecast = NULL;
}
//+------------------------------------------------------------------+
//| Function OnTick. |
//+------------------------------------------------------------------+
void OnTick(void)
{
if(!IsNewBar())
return;
if(!D2SkillRefreshLiveMarket(GetPointer(State), GetPointer(TimeState)) ||
!D2SkillMarket.Clear() ||
!D2SkillForwardForecastState(GetPointer(State)))
{ PrintFormat("%s -> %d market/forecast", __FUNCTION__, __LINE__); return; }
double buy_value = 0, sell_value = 0;
if(!D2SkillBuildLiveAccount(PreviousBalance, PreviousEquity, Rates[0].time,
GetPointer(Account), buy_value, sell_value))
{ PrintFormat("%s -> %d account", __FUNCTION__, __LINE__); return; }
const ulong forward_started = GetMicrosecondCount();
if(!Actor.feedForward(GetPointer(Account), 1, false, GetPointer(D2SkillMarket), -1) ||
!ReadAction(Actor, GetPointer(Action)))
{ PrintFormat("%s -> %d actor/read", __FUNCTION__, __LINE__); return; }
const ulong forward_elapsed = GetMicrosecondCount() - forward_started;
OOSGpuBoundaryLatencyTotal += forward_elapsed;
if(forward_elapsed > OOSGpuBoundaryLatencyMaximum)
OOSGpuBoundaryLatencyMaximum = forward_elapsed;
OOSGpuBoundaryLatencySamples++;
if(!D2SkillExecuteAction(GetPointer(Action), buy_value, sell_value))
{ PrintFormat("%s -> %d actor/execute", __FUNCTION__, __LINE__); return; }
OOSTransitions++;
if(IsExecutableOrder(double(Action[0]), double(Action[1]), double(Action[2])) ||
IsExecutableOrder(double(Action[3]), double(Action[4]), double(Action[5])))
OOSExecutableActions++;
const double current_equity = AccountInfoDouble(ACCOUNT_EQUITY);
OOSReward += current_equity - PreviousEquity;
if(current_equity > OOSPeakEquity)
OOSPeakEquity = current_equity;
else
if(OOSPeakEquity - current_equity > OOSMaximumDrawdown)
OOSMaximumDrawdown = OOSPeakEquity - current_equity;
PreviousBalance = AccountInfoDouble(ACCOUNT_BALANCE);
PreviousEquity = current_equity;
}
//+------------------------------------------------------------------+