//+------------------------------------------------------------------+ //| Inputs.mqh | //| AnimateDread | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "AnimateDread" #property link "https://www.mql5.com" #include "..\Enumerations\InputEnums.mqh" //--- Each `input string *_Settings` below is a GUI-only section divider: MetaTrader renders an input //--- string whose value equals its comment as a header. Never read by MQL5 code - that's expected, not //--- dead wiring. Sections are ordered most-used first: General, Money, Trade, Classic Signals, //--- Neural Network, AI Input Features, Filters, Trade Journal - then NN Optimizer / Performance LAST. //--- The Neural Network block sits directly ABOVE AI Input Features because that is the reading order a //--- user actually needs: choose the architecture, then choose what it sees. NN Optimizer / Performance //--- must remain the final divider in this file - the Adam/Sgd inputs are declared in AI\Network.mqh and //--- render immediately after it, so anything added below would land inside that group. //================================================================================================== // GENERAL //================================================================================================== input string Expert_Settings = "General"; // General input ulong Expert_MagicNumber = 2024; // Magic number (unique EA id) input bool Expert_EveryTick = false; // Calculate on every tick //--- NO LONGER AN INPUT (2026-08-01). The detailed panel/journal is a developer view: a buyer does not //--- care which plateau stage the ladder is on, and every row in the Inputs tab is a row they have to //--- read past to reach something that matters. Same reasoning that already applied to DebuggingMode //--- below, so the two now sit together. Flip to true and recompile to work on the EA. const bool VerboseMode = false; //--- DELIBERATELY NOT AN INPUT. Development diagnostics: dumps the training internals that used to sit on //--- the on-chart panel (plateau-ladder stage, eras-since-best, the deploy gate, selection internals) into //--- the Experts journal instead, where they cost the user nothing. This is a commercial product - the //--- default panel has to read like a product, not like a training console, so anything a buyer cannot act //--- on belongs in a log. Flip to true and recompile when diagnosing a training run. const bool DebuggingMode = false; //--- ALSO NOT AN INPUT, and for a stronger reason than DebuggingMode. Pins the dense-taper depth instead //--- of deriving it (ComputeHiddenLayerCount), purely so a depth comparison can still be run while //--- working on the EA. 0 = derived, which is the only value that should ever ship. A user who picks a //--- depth is contradicting the first-layer width and the taper the code derived around it - that //--- contradiction is exactly what the MLP_3L/MLP_4L presets used to allow. //--- NOTE the limitation: this is compile-time, and it feeds the weights-filename fingerprint only when //--- non-zero, so two forced depths get their own model files but cannot run SIMULTANEOUSLY from one //--- .ex5. Depth comparisons are sequential unless you deploy two separately-compiled builds. const int ForceHiddenLayers = 0; //================================================================================================== // MONEY MANAGEMENT //================================================================================================== input string MM_Settings = "Money Management"; // Money Management input MONEY_MANAGEMENT_STRATEGY MM_STRATEGY = FIXED_RISK; // MM strategy input MONEY_RISK_PERCENT_PRESET Money_Risk_Percent = RISK_PCT_1; // Risk % of balance per trade input double Money_FixLot_Lots = 0.01; // Fixed lot size [0.01-10] //================================================================================================== // TRADE MANAGEMENT (entry / stop / target / trailing / exit) //================================================================================================== input string Entry_Settings = "Trade Management"; // Trade Management input TRADING_DIRECTION tradingdirection = BOTH; // Trade direction //--- ENTRY / STOP / TARGET ARE NO LONGER INPUTS (2026-08-07). They were three enums the user had to pick, //--- and in the tester they were three more axes for a genetic optimization to overfit. The barrier //--- geometry is now MEASURED (ReportBarrierGeometryScan picks the SL:TP pairing that carries the most //--- entry-time information about its own outcome, and only adopts it when it clears a family-wise //--- significance gate - otherwise these defaults stand). Kept as named constants rather than deleted so //--- every existing reference still reads the same, and so the fallback is stated in one place. //--- //--- Entry is pinned to MARKET deliberately. The pending-order modes place the entry at a LEVEL while the //--- rest of the pipeline measures from the bar open, which is precisely the mismatch that manufactured //--- the +0.097 R "retail fade" result later retracted as a fill artifact - a pending entry cannot be //--- honestly simulated by this codebase's own fill model, so it is not offered. const ENTRY_MULTIPLIER Entry_Multiplier = MARKET; // Entry type/offset (fixed - see above) //--- STARTING geometry only. The scan may replace this pair at era 0 on a fresh model; a model that has //--- already been trained reads its pinned pair back out of the .cfg and never re-measures, so the labels //--- a run started with are the labels it finishes with. //--- //--- MIN REWARD:RISK IS GONE (2026-08-09). It was the last place a GUESS could override a MEASUREMENT. //--- The barrier geometry is derived from the instrument's own excursion distribution - stop at q75 of //--- adverse travel, target at q50 of favourable - and then a 1:2 floor was applied on top, raising the //--- target to whatever twice the stop happened to be. On SP500 H1 that turned a reachable target into //--- 6.66*ATR, which only 3.3% of bars reach inside the horizon: the label became "almost never a win", //--- and the model was trained to predict an event that essentially does not occur. //--- //--- The ratio never bought anything it was believed to buy. A reward:risk floor does not create //--- expectancy - it trades hit rate for payoff at a fixed break-even (see the barrier-geometry log //--- line, which prints that break-even next to the ranking precisely to make this visible), and this //--- project has already MEASURED that exit shape moves payoff without moving expectancy at all. What //--- it did buy was two outages: four consecutive Market validation rejections for "no trading //--- operations" when it rejected 100% of setups, and the label corruption above. //--- //--- Risk is controlled where risk is actually controlled - the per-trade account risk percentage and //--- CRiskBudget's daily/total drawdown enforcement - not by a ratio filter at the door. const STOP_LOSS_MODE SL_Mode = SL_ATR_x2; // Stop-loss mode (measured - see above) const TAKE_PROFIT_MODE TP_Mode = TP_ATR_x6; // Take-profit mode (measured - see above) input TRAILING_STRATEGY TrailingStrategy = TRAILING_STRATEGY_NONE; // Trailing stop input BARS_EXPIRATION Signal_Expiration = BARS_X3; // Pending order expiry (bars) input CONFIDENCE_SOURCE Confidence_Source = CONF_AI; // AI confidence source (SL/TP/trail/exit/MM) //--- UNIFIED conviction gates - ONE pair of thresholds governing BOTH engines, classic and AI. There //--- used to be a second, AI-only pair in the Neural Network section (Min AI confidence / Min AI exit //--- confidence) duplicating these: four inputs for what is really two decisions, where a trader could //--- set the vote gate and still be silently overruled by the AI floor (or the reverse). Merged here. //--- Everything is expressed on the same 0-100 conviction scale: a classic filter contributes its //--- pattern weight (10-100), an AI signal contributes its confidence tier (80-100), and //--- CExpertSignalCustom::Direction() averages the filters that voted before //--- CheckOpenPosition/CheckClosePosition threshold that average. //--- Open - aggregate conviction required to ENTER, and NOTHING else. It has exactly one meaning for //--- both engines: the averaged vote across the filters that voted must reach it. //--- It used to do two further jobs on the AI side - an entry floor on the winning softmax //--- probability, and the base the 4 AI confidence tiers were quartiled from - which put one //--- number on two incompatible scales. A 3-class argmax winner is arithmetically >= 1/3, so //--- as a floor every setting from 0 to 33 gated precisely nothing, while every setting above //--- that ALSO silently moved the tier boundaries. Both jobs are gone. The AI now expresses //--- confidence the way a classic signal does - as the WEIGHT of the vote it casts, 25/50/75/ //--- 100 across its four tiers, quartiled from the head's own structural floor (1/3 for the //--- 3-class softmax, 0.5 for the regression head - see CExpertSignalAIBase::ConfidenceTier). //--- So this input now reads, for the AI voting alone: 25 = trade any directional call, //--- 50 = tier 1 and up, 75 = tier 2 and up, 100 = only near-certain calls. A weak AI call is //--- no longer blocked inside the AI - it votes weakly and is filtered here, exactly like a //--- weight-10 classic confirmation. //--- NOTE in a hybrid setup this is an AVERAGE: a tier-3 AI vote of 100 alongside two //--- weight-10 classic confirmations averages to 40, not 100. Raising this input while several //--- low-weight classic signals are enabled suppresses strong AI calls by dilution - that is //--- inherent to averaging, and it is the same arithmetic the classic-only path has always had. //--- Close - OPPOSITE conviction required to EXIT. It drives BOTH exit routes, at the same conviction: //--- the averaged rule-based vote, and the AI early exit (how strongly the AI must have flipped //--- AGAINST an open position before that alone closes it). There is deliberately no separate //--- "Early AI exit" switch any more - it was a third input for what these two routes already //--- express, and it could be left off while Close was set, silently discarding the exit the //--- trader had just asked for. The two routes are NOT redundant with each other and both are //--- needed: the AI's normal vote is one-shot (LongCondition/ShortCondition consume the //--- m_lastNonNeutralSignal alternation gate when they fire) and is then AVERAGED with every //--- other filter, so an AI reversal that gets diluted below Close on the bar it happens is //--- consumed and never re-offered, leaving the position open indefinitely. The early-exit //--- route reads the AI's LIVE signed confidence every bar, undiluted, and so still fires. //--- Set Close = Disabled to switch off vote-driven exits entirely (SL/TP/trailing only) - //--- that turns off both routes at once, since 101 is unreachable on either scale. See //--- VOTE_CLOSE_PRESETS in Enumerations\InputEnums.mqh. //--- Close defaults ABOVE Open deliberately: a position is an existing commitment with real cost to //--- abandon, so reversing out of one should demand more conviction than opening it did, and a signal //--- hovering either side of the entry gate must not be able to churn a position open and shut. Both //--- were once hardcoded to 10/10 - one value for BOTH directions of the decision, pinned at the LOWEST //--- weight any pattern can carry - so with MA/RSI Pattern_0 (weight 10) firing on nearly every bar on //--- whichever side of the MA price sits, one cross flipped the average from +10 to -10 and closed the //--- position on the very next bar. The stock MQL5 wizard makes the same asymmetric choice, 50 to open //--- against 100 to close. input PERCENTAGE_PRESETS Min_Vote_Open = PCT_20; // Min vote to open - AI + classic input VOTE_CLOSE_PRESETS Min_Vote_Close = VOTE_CLOSE_DISABLED; // Min opposite vote to close - AI + classic //================================================================================================== // CLASSIC SIGNALS (rule-based MA/RSI votes - trade alongside or instead of the neural network) //================================================================================================== input string Classic_Settings = "Classic Signals"; // Classic Signals //--- EnableMA/EnableRSI default depends on the build (see AIType's declaration comment for the full //--- rationale): ON for a Market submission build (WARRIOR_MARKET_BUILD defined) so a fresh install //--- trades immediately with no AI warm-up, OFF for the private/live build, which runs AI-only by //--- default. Either way this is only a compile-time DEFAULT - still a normal input, changeable per-run //--- from the Inputs tab without recompiling. //--- PRIVATE-BUILD DEFAULTS CHANGED 2026-08-13 (user request, meta-pooling campaign): all four //--- classic families default ON in the private build - they are the META chart's candidate sources //--- for the on-chart ladder sweep (BuildCorpusBySweep), and the drop-on-chart workflow must need no //--- Inputs-tab edits. Market build unchanged: MA/RSI on (trades out of the box), MACD/Ichimoku off //--- (additive to the shipped strategy). #ifdef WARRIOR_MARKET_BUILD input bool EnableMA = true; // MA classic vote #else input bool EnableMA = true; // MA classic vote #endif #ifdef WARRIOR_MARKET_BUILD input bool EnableRSI = true; // RSI classic vote #else input bool EnableRSI = true; // RSI classic vote #endif #ifdef WARRIOR_MARKET_BUILD input bool EnableMACD = false; // MACD classic vote input bool EnableIchimoku = false; // Ichimoku classic vote #else input bool EnableMACD = true; // MACD classic vote input bool EnableIchimoku = true; // Ichimoku classic vote #endif //--- Indicator parameters below are SHARED: they define the classic votes above AND seed the matching AI //--- input features (AI Input Features section) as their starting period, which Auto-tune indicators then //--- searches from. Set once here, used by whichever consumer(s) are enabled. input MA_PERIOD_PRESETS PeriodMA = MA_PERIOD_50; // MA period input MA_TYPE_PRESETS MA_Type = MA_TYPE_SMA; // MA type (SMA/EMA/.../T3/Kalman) input RSI_PERIOD_PRESETS PeriodRSI = RSI_PERIOD_14; // RSI period //--- MACD AND ICHIMOKU PERIODS ARE NO LONGER INPUTS (2026-08-01). Six dropdowns, pinned here at the //--- textbook values every reference uses (12/26/9 and 9/26/52), for three reasons: //--- 1. They were six of the largest contributors to the Inputs tab, for indicators that both ship //--- DISABLED. Rows a user must scroll past to reach the AI settings are a real cost. //--- 2. As optimizer inputs they are an overfitting surface. A genetic sweep across 6 period //--- dimensions on one symbol's history will always find a combination that looks excellent and //--- generalizes to nothing - and it costs nothing to discover, which is what makes it dangerous. //--- 3. They are the SEED for the AI's own auto-tuner (AutoTuneIndicators), which searches from these //--- values against a held-out objective. That search is the supported way to move them: it is //--- validated, it is per-model, and it cannot silently overfit the way a raw optimizer pass can. //--- Left as named constants rather than deleted because they are still read in both roles (classic //--- vote periods AND auto-tune starting points), and because the classic textbook values are the //--- correct fixed answer for a vote that exists mainly to satisfy marketplace validation. const MACD_FAST_PRESETS MACD_PeriodFast = MACD_FAST_12; const MACD_SLOW_PRESETS MACD_PeriodSlow = MACD_SLOW_26; const MACD_SIGNAL_PRESETS MACD_PeriodSignal = MACD_SIGNAL_9; const ICHIMOKU_TENKAN_PRESETS Ichimoku_PeriodTenkan = ICHI_TENKAN_9; const ICHIMOKU_KIJUN_PRESETS Ichimoku_PeriodKijun = ICHI_KIJUN_26; const ICHIMOKU_SENKOU_PRESETS Ichimoku_PeriodSenkou = ICHI_SENKOU_52; //================================================================================================== // NEURAL NETWORK (training) //================================================================================================== input string NNetworks_Settings = "Neural Network"; // Neural Network //--- AIType default depends on the build, via the same WARRIOR_MARKET_BUILD compile-time flag that //--- strips the DLL import block for Market submissions (see Warrior_EA.mq5's top-of-file comment) - not //--- an input value itself (that can't be set programmatically), only which default the Inputs tab //--- starts on: //--- - WARRIOR_MARKET_BUILD defined (Market submission): OFF - a fresh install trades from Classic //--- Signals (MA/RSI) out of the box with no AI warm-up, satisfying MQL5's automated check for live //--- trade activity within its test window. //--- - Not defined (private/live build): MLP - this build runs AI-only from the start, with Classic //--- Signals defaulting off too (see EnableMA/EnableRSI), so no per-run manual input changes are //--- needed switching between preparing a submission and running the real thing. //--- Either way, still a normal input - freely changeable per-run from the Inputs tab. #ifdef WARRIOR_MARKET_BUILD input AI_CHOICE AIType = AI_NONE; // AI architecture preset (or Disabled) #else //--- META since 2026-08-13 (was HYBRID): the private build's active campaign is the meta-labeling //--- pool - drop a chart on any symbol and it sweeps candidates, labels, trains and exports with no //--- Inputs-tab edits. Direction models remain selectable per-run as always. input AI_CHOICE AIType = AI_META; // AI architecture preset (or Disabled) #endif //--- SGD or ADAM weight update (honored by PAI/CONV/LSTM/HYBRID). SGD rate/momentum are AI\Network.mqh inputs. //--- A third "DFA" option was briefly the default (2026-07-28) and has been removed - it was a //--- deterministic index-parity sign flip on the gradient, i.e. permanent gradient ASCENT on half of //--- every weight tensor, and its backward pass was structurally incompatible with the OpenCL/DirectML //--- neuron model. See ENUM_OPTIMIZATION's comment in AI\Network.mqh. input ENUM_OPTIMIZATION TrainingOptimizer = ADAM; // Weight optimizer //--- OUTPUT TYPE IS NO LONGER AN INPUT (2026-08-01). The regression head (1 tanh output) was an option //--- that never made sense for the question this system asks. Since the triple-barrier relabel the //--- target is explicitly an EVENT - "does a trade opened here reach its target before its stop" - and //--- the right output for an event is its probability, which is what the 3-class softmax head produces. //--- A regression head would have to predict a continuous quantity that the label does not even contain, //--- and every downstream consumer already speaks probability: the confidence tiers quartile the softmax //--- winner, dir-precision is a win rate over called bars, and the class priors calibrate a distribution. //--- The regression path is still IMPLEMENTED throughout (m_outputNeuronsCount == 1 branches, the 0.50 //--- magnitude cutoff in DoubleToSignal) and is left in place deliberately: it costs nothing dormant and //--- removing it would touch every scoring path at once for no gain. It is simply no longer selectable. const OUTPUT_NEURONS_COUNT OutputNeuronsCount = OUTPUT_CLASSIFICATION; //--- No "first layer neurons" input any more. Its only defensible value depends on two things the user //--- cannot see - the input-vector width after feature selection, and how much in-sample data the study //--- period yields - so it is derived at topology-build time instead. See //--- CExpertSignalAIBase::ComputeFirstLayerWidth(). The old default (500) was ~8 parameters per training //--- sample and expanded a 420-wide correlated input rather than compressing it. //--- No "LSTM hidden size" or "CONV filter count" inputs either, removed 2026-07-30 for exactly the //--- reason above: both defaulted to a fixed constant (32 units, 16 filters) chosen without reference to //--- the input they sit on, which is the one thing that decides whether either number is sane. //--- The conv layer is a per-bar projection (window = step = one bar's features), so 16 filters //--- COMPRESSED a 50-feature configuration but EXPANDED a minimal 4-feature one 4x - adding parameters //--- below every learnable layer without adding information. The LSTM block is worse: its weight count //--- is 4*H*(H+inputs+1), so 32 units against a 540-wide input is ~73k weights, more than double the //--- entire derived dense taper it feeds, and it was the one stage the capacity budget never covered. //--- Both are now derived from the per-bar feature count and the same one-weight-per-training-bar budget //--- the first layer uses. See ComputeConvFilterCount()/ComputeLstmHiddenSize(). //--- ConvPoolWindow / ConvPoolStep removed 2026-07-29. The pooling stage they configured reduced //--- across FILTER channels rather than across time - a consequence of the conv layer's position-major //--- output layout that no window/step pair can correct. See AddConvStage() in Expert\ExpertSignalAIBase.mqh. //--- No "min neurons" / "reduction per layer" inputs either. With the first layer's width derived //--- (ComputeFirstLayerWidth) the taper has no freedom left: it runs geometrically from that width down //--- to a final hidden layer sized off the output count, spread over the layer count the chosen AIType //--- implies. Keeping either knob would let the user contradict the derivation - and both were //--- calibrated for the old hand-picked 500-wide first layer, where they gave 500->150->45; against the //--- derived 64 they degenerate to 64->20->20. See BuildFreshTopology()'s taper block. //--- Batch normalization (Ioffe & Szegedy 2015) between every pair of dense layers, including just //--- before the classification head. ON by default: without it the only bounded stage in the whole //--- forward path was the sigmoid head, and the observed failure mode ordered exactly by depth - the //--- shallow perceptron held ~52% balanced accuracy while the deepest topology sat on the 33.3% //--- one-class floor. It also decouples WEIGHT_DECAY from the learned function, which is what stops //--- the slow monotonic decay of the per-bar logit spread that preceded every collapse. //--- Left as an input rather than hardcoded so the effect can be A/B'd without a recompile. It is part //--- of the weights-filename fingerprint, so flipping it starts a separate model rather than resuming //--- an incompatible one. See AI\NeuronBatchNorm.mqh. //--- NOT an input. Batch normalization is required, not optional: measured 2026-07-29 on identical //--- MLP_3L topologies it was worth +11.3 points of balanced accuracy (57.0% with, 45.7% without), //--- stable across 150+ and 200+ eras, and the no-BN control converged to ~5% IS and OOS accuracy //--- with no chart signals at all. A user cannot make a good decision here and can easily make a //--- ruinous one, so the choice is not offered. Kept as a named constant rather than deleted: the //--- topology builder, the weights fingerprint and the .cfg guard all read it, and a constant keeps //--- those paths (and the ability to flip it for a diagnostic rebuild) intact. const bool EnableBatchNorm = true; // AI: batch normalization //--- EMA window the running mean/variance are estimated over, in TRAINING SAMPLES (bars replayed), //--- not eras. Training here is pure online SGD - one update per sample - so there is no mini-batch to //--- average over and this stands in for the batch size. Long enough to be a stable estimate of the //--- feature distribution, short enough to track a genuine regime change. 1000 is ~3% of a typical //--- 36k-bar in-sample window. //--- Also not an input, for the same reason plus one more: this is a running-statistics window in //--- SAMPLES, and nothing on the Inputs tab tells a trader what a good value is. It only ever had //--- two meaningful settings - large enough to be a stable estimate, or <=1 which silently disables //--- the layer entirely. The first is the only correct one. const int BatchNormWindow = 1000; // AI: batch-norm window (samples) //--- No "training years" input either, removed 2026-07-30. There is no case for training on less data //--- than the broker actually provides: this is a weak signal at a ~6% directional base rate, every extra //--- year is more of the minority class, and the honest generalization read comes from the out-of-sample //--- holdout below rather than from withholding history. Training now starts at the earliest available //--- bar (floored by MinTrainYear, which exists to exclude a broker's dubious pre-history, not to size //--- the run). The topology's capacity budget reads the REAL bar count that yields - see //--- CExpertSignalAIBase::EstimatedInSampleBars(), and the note there on why that measurement is taken //--- exactly once and then pinned. input OOS_SPLIT_PRESET OOSSplit = OOS_30; // Out-of-sample holdout //--- There is deliberately NO "target accuracy" input. Training runs until it stops improving and then //--- deploys its own best model: after a stretch of eras with no new best it tries to escape the plateau //--- (learning-rate warm restart, then focal-gamma anneal), and if neither finds anything better it //--- finalises the best checkpoint it found. See the PLATEAU_* ladder in Expert\ExpertSignalAIBase.mqh. //--- An absolute target could only ever be wrong in one of two directions: set above what a given //--- symbol/timeframe can reach and the run never converges (it burns to the era cap and deploys the same //--- checkpoint hours later anyway); set below and it stops a run that was still getting better. //--- MinRecall stays, and is NOT a performance target - it is the anti-collapse floor that makes //--- auto-deploy safe. Buy, Sell AND Neutral must each be recognised this well on held-back data before a //--- checkpoint is eligible to ship, so a model that quietly gives up on one direction can never deploy. //--- It is an OOS CLASSIFICATION metric (3-class), NOT a trade win rate: random guessing is ~33%. //--- 2026-07-29: 60 -> 40. 60 was never demonstrated reachable on this data. The ONE successful //--- auto-deploy in the logs (Hybrid, SP500 H1, 28th 00:50, best balanced 66.0%) ran against a 40% //--- floor; every run since has been gated at 60 and none has come close - CONV/LSTM/Hybrid peaked at //--- 40/49/41% balanced and then decayed, so stage 3 refused to deploy and reset the ladder ~27 times, //--- turning a converged run into a 1000-era one-way trip. A floor above what the configuration can //--- reach is exactly the "absolute target set too high" failure the comment above warns about, just //--- expressed per-class. Raise it again only after a run actually clears it with headroom. //--- 2026-08-01: NO LONGER AN INPUT. This is a safety floor, not a preference, and the one direction a //--- user can move it is the harmful one - raising it past what the configuration reaches does not //--- produce a better model, it produces NO model (nothing clears the gate, stage 3 refuses to deploy, //--- and the run burns to the era cap). That failure was observed repeatedly at 60 and is the exact //--- catch-22 this floor was nearly deleted over. 40 is the value the only successful auto-deploy in the //--- project's history ran against. It also no longer decides what SHIPS - deployability moved to //--- directional precision with a derived coverage floor - so it now only drives the diagnostic recall //--- line, which makes exposing it even harder to justify. const PERCENTAGE_PRESETS MinRecall = PCT_40; //--- There are deliberately NO AI-only confidence inputs here any more. The AI entry floor and the AI //--- early-exit threshold are the SAME two numbers the classic votes use - Min vote to open / Min //--- opposite vote to close (Trade Management section) - so one pair of inputs governs both engines; //--- see their declaration comment for how the 0-100 scale maps onto AI softmax confidence and tiers. //================================================================================================== // CLASS IMBALANCE - ONE MECHANISM, ONE KNOB //================================================================================================== //--- The directional base rate here is ~3% Buy / ~3% Sell / ~94% Neutral (a ~31:1 imbalance), so the //--- loss needs SOME correction or the optimum is "always predict Neutral". This section used to offer //--- NINE inputs for that one job. They were consolidated on 2026-07-31 because, audited against the //--- code, five of them did not do what their names said at the shipped defaults: //--- AILogitPriorStrength DEAD - Inference.mqh's post-hoc prior early-returns when the adjusted //--- loss is on, because the offsets are already trained into the weights. //--- OversampleParity DEAD in training - Training.mqh gates the replay loop on //--- !useLogitAdjustedLoss (correctly: Buda et al. 2018 on why stacking //--- oversampling with an analytic correction double-counts the imbalance). //--- EnableMinorityReplay DEAD as replay; it survived ONLY as a focal-gamma damper (x0.125). //--- ConstrainReplay DEAD as a cap; it only chose between damper 0.125 and 0.25. //--- UseStaticPrior an exact duplicate of FreezePriorCalibration - the two were OR'd //--- together in the single place either was read. //--- Focal loss was the one real redundancy: it ran at gamma*0.125 alongside the adjusted loss, i.e. //--- two corrections on the SAME axis, which is what the codebase's own Buda et al. citation warns //--- against. Removed rather than re-tuned - the plateau ladder's escape is its learning-rate warm //--- restart, and the gamma anneal it also performed was only ever a monotone step toward zero. //--- //--- WHAT REMAINS is LOGIT-ADJUSTED LOSS (Menon et al. 2021, ICLR, "Long-tail learning via logit //--- adjustment"): add tau*log(prior_c) to each class logit inside the TRAINING gradient only. The //--- network learns to absorb the offset, so at inference its RAW argmax is already the //--- balanced-error-optimal decision - no second correction at read time, by construction. Minimizing //--- softmax cross-entropy on adjusted logits is consistent for BALANCED error, which is the metric //--- checkpoint selection already ranks on, so the loss and the deploy decision optimize the same //--- thing. It is the only one of the six with a consistency guarantee, which is why it is the one kept. //--- //--- tau: 100% = tau 1.0, the paper's default and the only value carrying the guarantee. 0 = OFF, which //--- is now the honest way to disable the correction entirely (it replaces the old EnableLogitAdjusted- //--- Loss boolean - a separate on/off switch beside a strength dial where 0 already means off is two //--- controls for one decision). NOTE the runtime auto-caps tau so the offsets cannot swamp the output //--- head's usable logit range; the startup line reports the capped value actually used. input LOGIT_PRIOR_STRENGTH_PRESETS LogitAdjustTau = LOGIT_PRIOR_100; // AI: class-imbalance correction (tau, 0=off) //--- Stop EMA-updating the measured class priors after the first real measurement. NOT AN INPUT as of //--- 2026-08-01: it answers a question a user has no way to evaluate ("should the correction track this //--- era's tally or the first one's"), and after the triple-barrier relabel the priors barely move //--- between eras anyway - the labels are near-balanced and stable, which is the whole point of the //--- relabel. Letting them track is the correct default; freezing exists for a symbol whose class //--- distribution genuinely shifts mid-run, which is a developer's diagnostic, not a product setting. const bool FreezePriorCalibration = false; //--- SWING CONFIRM BARS IS NO LONGER AN INPUT (2026-08-01), but the constant is still load-bearing and //--- must not be deleted. It stopped gating the LABELS with the triple-barrier relabel - that lookahead //--- is now the barrier horizon, which is measured (ComputeBarrierHorizonBars) rather than configured. //--- It still gates the swing-context INPUT FEATURES (EnableSwingContext, on by default, 9 features): //--- ZigZag revises its most recent legs, so a feature that read the raw current buffer would be reading //--- a value the live bar could not actually have had yet. That is straight lookahead into the feature //--- vector, so this embargo stays - it simply has no reason to be user-facing, because the correct //--- value is a property of the ZigZag indicator's own recalculation depth, not of anyone's preference. //--- Kept in the weights fingerprint at its shipped value, so pinning it re-keys nothing. const SWING_CONFIRMATION_PRESET SwingConfirmationBars = SC_100; //--- Continual learning: after the model is deployed, keep adapting it on a LIVE chart to newly-RESOLVED //--- market structure - the same supervised triple-barrier task it was trained on, waiting the full //--- barrier horizon so a bar whose outcome is not yet decided is never learned from. The deployed model //--- only moves toward the update while a rolling-accuracy guardrail holds; if accuracy decays the blend //--- FREEZES (live keeps trading the last-good shadow while the net recovers), so drift cannot reach the //--- account. No effect in the Strategy Tester/optimizer - the model is held fixed there by design. //--- ON BY DEFAULT AND NO LONGER AN INPUT (2026-08-01). Adapting to a changing market is not an optional //--- extra for a model that will be attached for months, it is the thing that keeps it from going stale, //--- and the guardrail above is what makes it safe to leave on. See the caveat in the release checklist: //--- this had never been forward-tested on a live feed at the time it was made default. const bool EnableOnlineLearning = true; //--- Default 6 -> 3 and NO LONGER AN INPUT (2026-08-01). Declustering existed because exact-pivot ZigZag //--- labels make a same-direction repeat provably redundant; barrier labels answer every bar //--- independently, so consecutive Buy setups inside a trend are real trades and suppressing them throws //--- signal away - which argued for 0. It is not 0 because on D1 and above a 6-bar window spans more than //--- a trading week, and two arrows a day apart on a weekly-scale move really are one event. 3 keeps the //--- immediate-neighbour duplicate off the chart on slow timeframes while leaving genuine consecutive //--- setups intact on fast ones. Display/emission only either way - the raw per-bar recall/precision //--- metrics are never declustered, so this cannot flatter a model's measured numbers. //--- 10 bars (2026-08-10, was 3). On H1 a 3-bar window collapsed only the tightest runs and left //--- visible clusters around every turn; 10 bars is a third of a session and closer to the spacing of //--- genuinely distinct setups on this timeframe. Applies to every topology - it is not per-network. const int SignalClusterWindow = 10; //--- EXCURSION-SIZE HEAD (Expert\AIBase\Excursion.mqh). A second small net that predicts how FAR price //--- travels within the horizon - never which way, which is measured-closed on three instruments. //--- STAGE 1 IS A MEASUREMENT: it trains beside the classifier and prints a Brier skill score against //--- the constant base rate a fixed ATR multiple already assumes. It places no orders and moves no //--- stops, so leaving it on costs only era time and leaving it off changes nothing else. //--- NOT in the weights fingerprint: it is a separate network with its own weights, so it cannot alter //--- the classifier's shape - the rule that keeps TRAIN_BATCH_SIZE out for the same reason. const bool UseExcursionHead = true; //--- Era cap. NOT AN INPUT as of 2026-08-01: it is a runaway backstop, not a training control. Training //--- decides its own ending (the plateau ladder deploys the best checkpoint once escalation stops finding //--- anything better), so in a healthy run this number is never reached and choosing it changes nothing; //--- in an unhealthy one the useful response is to read the era log, not to raise a cap. const MAX_ERAS_PRESET MaxErasPerRun = ME_1000; //================================================================================================== // AI INPUT FEATURES (the data the neural network sees each bar) //================================================================================================== input string AISignals = "AI Input Features"; // AI Input Features //--- ind_Periods IS NO LONGER AN INPUT (2026-08-11). The number of bars per input sequence is now //--- DERIVED - median confirmed swing leg over recent history, snapped to a coarse ladder and capped //--- (see DeriveHistoryBars) - then pinned in the model's .cfg and ADOPTED on every later load, the //--- same measure-once contract as the barrier geometry. Picking it by predictive skill instead was //--- ruled out by the 2026-08-06 lag profile (no information at any lag 0-20): a best-of-N window //--- scan would only ever mine noise. The ATR feature/barrier-unit lookback it also used to set is //--- deliberately DECOUPLED and pinned at the old default below: the ATR indicator is created before //--- the .cfg can be adopted, so deriving its period would let init ordering change the unit the //--- pinned SL/TP multiples are expressed in. #define ATR_FEATURE_PERIOD 20 input ENUM_APPLIED_VOLUME VolumeData = VOLUME_TICK; // Volume data type (tick / real) input bool EnableVolume = true; // Feature: volume input bool EnableTime = true; // Feature: time input bool EnableATR = true; // Feature: volatility (ATR) //--- MA/RSI as network input features, independent of the Classic Signals votes above (you can feed MA //--- to the model without it voting, or vice versa). Uses PeriodMA/MA_Type/PeriodRSI (Classic Signals) //--- as the starting period, then auto-tuned from there when Auto-tune indicators is on. input bool EnableMAFeature = true; // Feature: Moving Average input bool EnableRSIFeature = false; // Feature: RSI //--- MACD adds 3 inputs/bar (main, signal, histogram - all ATR-normalized); Ichimoku adds 8 (distances to //--- Tenkan/Kijun/both cloud edges, the TK spread, cloud thickness here and projected, and the Chikou //--- displacement). Widths are per BAR, so each is multiplied by Bars to analyse before it reaches the //--- first layer - Ichimoku at the default 20 bars is 160 extra inputs on its own. Worth it for the //--- multi-timescale structure nothing else in the vector carries, but enable deliberately, not by habit. input bool EnableMACDFeature = false; // Feature: MACD input bool EnableIchimokuFeature = false; // Feature: Ichimoku //--- Confirmed ZigZag swing direction/magnitude/age - lookahead-safe (repainting embargo applied, see //--- SWING_CONFIRMATION_BARS in Expert\ExpertSignalAIBase.mqh). input bool EnableSwingContext = true; // Feature: ZigZag swing context input bool EnableADCumulativeDelta = false; // Feature: Cumulative Delta input bool EnableADShorteningOfThrust = true; // Feature: Shortening of Thrust input bool EnableADWyckoffEventStream = true; // Feature: Wyckoff Events input bool EnableADWyckoffFailedStructure = true; // Feature: Wyckoff Failed Structure input bool EnableADWyckoffSignificantBarInversion = true; // Feature: Wyckoff Bar Inversion //================================================================================================== // AD / WYCKOFF INDICATOR PARAMETERS //================================================================================================== //--- ADDED 2026-08-08, because AutoTuneIndicators now defaults to false and these 33 values had NO input //--- of any kind - they were literals in CADIndicatorTuner's constructor. MA/RSI/MACD/Ichimoku have had //--- their periods exposed since the beginning; the order-flow and Wyckoff indicators, which contribute //--- 28 of the 64 features per bar on the AD configs, were operator-invisible. With the tuner on that was //--- survivable (it searched them); with it off they would be frozen at values nobody chose. //--- //--- SEEDS, exactly like PeriodMA/MA_Type. When AutoTuneIndicators is on, the search still starts here and //--- is still free to move each indicator's copy independently - collapsing the shared thresholds below //--- into one input each constrains only what the OPERATOR sets, never what the tuner may explore. //--- //--- CONSOLIDATED 33 -> 18 on purpose, following the imbalance-input precedent. volClimax/volHigh/ //--- rangeClimax/rangeSignificant/stVolRatio/atr were duplicated verbatim across CumulativeDelta, Wyckoff //--- Events, Failed Structure and Bar Inversion - the same four constants restated 3-4 times each. They //--- are one CONCEPT per row ("what counts as climactic volume", "what counts as a significant range"), //--- so they get one input per concept. Eighteen knobs an operator can reason about beats thirty-three //--- that invite inconsistent settings for the same idea. //--- //--- Every default below is byte-identical to the literal it replaces, so this ships as a pure no-op: //--- see the ADP token in ConfigFingerprint(), which is appended ONLY when something actually differs, //--- leaving every existing model's filename - and therefore its trained weights - untouched. #define WYK_VOL_CLIMAX_DEF 2.5 #define WYK_VOL_HIGH_DEF 1.5 #define WYK_RANGE_CLIMAX_DEF 1.8 #define WYK_RANGE_SIGNIF_DEF 1.2 #define WYK_ST_VOL_RATIO_DEF 0.6 #define WYK_ATR_MULT_DEF 0.5 #define ADCD_LOOKBACK_DEF 50 #define SOT_THRUST_LOOKBACK_DEF 30 #define SOT_MIN_IMPULSES_DEF 3 #define SOT_THRESHOLD_DEF 0.30 #define WES_LOOKBACK_DEF 50 #define WES_ZIGZAG_DEF 3 #define WES_TOUCH_ATR_DEF 0.5 #define WES_AR_MIN_ATR_DEF 1.0 #define WES_MAX_RANGE_BARS_DEF 200 #define WFS_LOOKBACK_DEF 50 #define WFS_ZIGZAG_STRENGTH_DEF 3 #define WSBI_LOOKBACK_DEF 50 input string ADParams = "AD / Wyckoff Parameters"; // AD / Wyckoff Parameters //--- Shared thresholds. Each is a multiple of that bar's own rolling average (volume) or ATR (range), so //--- they are scale-free and mean the same thing on any symbol. input double Wyk_VolClimaxMult = WYK_VOL_CLIMAX_DEF; // Climactic volume (x average) input double Wyk_VolHighMult = WYK_VOL_HIGH_DEF; // High volume (x average) input double Wyk_RangeClimaxMult = WYK_RANGE_CLIMAX_DEF; // Climactic range (x ATR) input double Wyk_RangeSignificantMult = WYK_RANGE_SIGNIF_DEF; // Significant range (x ATR) input double Wyk_ShortTermVolRatio = WYK_ST_VOL_RATIO_DEF; // Short-term volume ratio input double Wyk_AtrMult = WYK_ATR_MULT_DEF; // General ATR multiple //--- Per-indicator structure. Lookbacks are in BARS and set how far back each indicator searches for the //--- structure it names; they do not need to agree with each other or with HistoryBars. input int ADCD_Lookback = ADCD_LOOKBACK_DEF; // Cumulative Delta: lookback bars input int SOT_ThrustLookback = SOT_THRUST_LOOKBACK_DEF; // Shortening of Thrust: lookback bars input int SOT_MinImpulses = SOT_MIN_IMPULSES_DEF; // Shortening of Thrust: min impulses input double SOT_Threshold = SOT_THRESHOLD_DEF; // Shortening of Thrust: threshold input int WES_Lookback = WES_LOOKBACK_DEF; // Wyckoff Events: lookback bars input int WES_ZigZag = WES_ZIGZAG_DEF; // Wyckoff Events: ZigZag strength input double WES_TouchATR = WES_TOUCH_ATR_DEF; // Wyckoff Events: zone touch (x ATR) input double WES_ARMinATR = WES_AR_MIN_ATR_DEF; // Wyckoff Events: min AR size (x ATR) input int WES_MaxRangeBars = WES_MAX_RANGE_BARS_DEF; // Wyckoff Events: max range life (bars) input int WFS_Lookback = WFS_LOOKBACK_DEF; // Failed Structure: lookback bars input int WFS_ZigZagStrength = WFS_ZIGZAG_STRENGTH_DEF; // Failed Structure: ZigZag strength input int WSBI_Lookback = WSBI_LOOKBACK_DEF; // Bar Inversion: lookback bars //--- News LAST in this list on purpose: it is the only feature whose data comes from outside the price //--- series (the terminal's economic calendar), so it is the one a user is most likely to want to reason //--- about separately - and the only one with a companion setting. Proximity/impact only, never //--- actual-vs-forecast, which is not knowable ahead of the release. input bool EnableNews = false; // Feature: news proximity input NF_LOOKBACK_PRESETS NewsFeatureWindowMinutes = M60; // News feature window //--- Cross-asset, after News for the same reason: its data also comes from outside this symbol's own //--- series - in fact it is the ONLY feature here that does so without leaving the price domain. Every //--- other block above, News included, is either a transform of this one instrument's OHLCV or a //--- timing overlay on it. Measured end to end, that whole family sits at the noise floor //--- (research/test_classic.py), which is precisely why this exists. Builds a currency-strength panel //--- from the FX pairs in Market Watch and feeds the traded pair's base/quote strength plus the //--- divergence between the pair and its own two currencies. Needs >= 2 usable FX pairs in Market //--- Watch; degrades to a neutral 0-fill with one logged line if it cannot build, never blocks training. input bool EnableCrossAsset = true; // Feature: cross-asset currency strength //--- Spread: the only microstructure channel that is both FX-available and genuinely historical in //--- the Strategy Tester, so the only one a backtest can honestly validate. Encodes a volatility //--- REGIME (spread is near-fixed while ATR is not, so the ratio runs high exactly when realised //--- volatility is below its ATR estimate), which predicts whether ATR-scaled barriers get reached. //--- Unsigned, like volume - it informs Neutral-vs-directional and can never pick a side. input bool EnableSpreadFeature = true; // Feature: spread / volatility regime //--- Searches the per-bar parameters of every ENABLED input feature above (the order-flow/Wyckoff //--- MA/RSI feature periods) for the combination that trains best - see ADIndicatorTuner.mqh. //--- The TRIAL COUNT IS NO LONGER AN INPUT (2026-08-01). It was a number the user had no basis to pick: //--- the right budget depends on how many parameters are actually being searched and how wide each //--- one's range is, both of which the code knows at runtime and the user does not. Asking for it //--- guaranteed either a wasted search (too many trials on two narrow parameters) or a blind one (32 //--- trials against a space of millions). Now derived - see ComputeTuneTrialBudget(). //--- DEFAULT FLIPPED TO false 2026-08-08, and NOT because the search is broken - it is correct, and its //--- own Sidak family-wise gate is what proves it. The search is simply not worth its cost on data at //--- the MI noise floor, which is every instrument measured so far: //--- * It scored 324 candidates per model on SP500 H1 and reported no improvement on ALL FOUR //--- topologies (0.00236 -> 0.00236 on the three AD configs, 0.00370 -> 0.00370 on PAI), rejecting //--- its own winner at selection p=1.0000. That is the gate working, not failing. //--- * It cannot do better here by construction: it ranks candidates by MARGINAL mutual information, //--- and the headline MI reads 0.00370 nats against a shuffled-label null of 0.00379 +/- 0.00061 //--- (p=0.4975). Every candidate is a noise draw, so the maximum over N of them is noise too, and //--- the correction rejects it - more harshly the more candidates are tried. //--- * The cost is not marginal: 2674s (CONV), 3271s (LSTM), 3372s (HYB) - 45 to 56 minutes per model, //--- in ONE synchronous call with no yield, during which the chart is frozen and silent. It was also //--- the amplifier for the indicator-handle leak (fixed, see ReInitADIndicators): 324 iterations x 6 //--- re-creates orphaned gigabytes and MT5 removed CONV and LSTM for running out of memory. //--- Turn it ON deliberately, on an instrument whose per-feature MI actually clears its null, and expect //--- to wait. The EA's own report says it plainest: "no per-feature indicator retuning will help". //--- The input STAYS. The sweep is one function of twelve in AIBase\AutoTune.mqh - the other eleven are //--- the MI/lag/excursion/geometry diagnostics that produced every verdict this project relies on, and //--- they run on their own path regardless of this flag (see TuneIndicatorsAndTrain's else-branches). input bool AutoTuneIndicators = false; // Auto-tune indicator params (slow) //================================================================================================== // FILTERS //================================================================================================== input string SF_Settings = "Session Filter"; // Session Filter input bool EnableSessionFilter = false; // Signal: Session filter //--- All three ON by default. The filter is evaluated once per BAR (Expert_EveryTick=false ships as the //--- default), so on a slow timeframe there are very few evaluations per day and a single-session //--- default can starve the EA of entries entirely - on D1 there is exactly ONE evaluation, at the bar //--- open, and whether that instant falls inside a narrow session window depends purely on the broker's //--- server offset. Enabling all three spans 00:00-22:00 GMT so only genuinely dead hours are excluded; //--- narrow it deliberately per-chart rather than inheriting it as an accident of the default. input bool SF_trade_LondonSession = true; // Trade London session input bool SF_trade_TokyoSession = true; // Trade Tokyo session input bool SF_trade_NewYorkSession = true; // Trade New York session //--- Scheduled flat-close. Deliberately its OWN group rather than part of the Session Filter above: //--- CExpertCustom::OnTick() (Expert\ExpertCustom.mqh) evaluates this schedule unconditionally, so it //--- fires whether EnableSessionFilter is on or off - grouping it under the session filter implied a //--- coupling that has never existed in the code. Set Close-all day = Disabled to switch it off. input string CA_Settings = "Scheduled Close-All"; // Scheduled Close-All input CLOSE_DAY_OF_WEEK targetDayOfWeek = CLOSE_FRIDAY; // Close-all day input CLOSE_HOUR_OF_DAY targetHour = CH_23; // Close-all hour input CLOSE_MINUTE_OF_HOUR targetMinutes = CM_45; // Close-all minute //--- INTRADAY TIME FILTER REMOVED ENTIRELY 2026-08-01 (5 inputs, plus Signals\SignalITF.mqh). //--- Two of its five inputs were raw BITMASKS ("hours to avoid" as an integer), which is not a setting a //--- trader can reasonably compute - it is an implementation detail exposed as a control, and it shipped //--- disabled so essentially nobody ever got it right. More importantly the job is now covered three //--- times over by things that learn or are declarative: the Session Filter handles "when may I trade" //--- explicitly, the time-of-day/day-of-week features (EnableTime) let the NETWORK discover which hours //--- are good on this instrument instead of being told, and the trade journal ranks by time bucket. //--- A hand-specified hour mask is the least informed of the four and the hardest to use. input string NF_Settings = "News Filter"; // News Filter input bool EnableNewsFilter = true; // Signal: News filter input NF_LOOKBACK_PRESETS NF_LookMinutes = M60; // News avoid window (min) input NF_IMPACT_PRESETS NF_MinImpact = HOLIDAYS; // Min news impact to avoid //--- MARKET DEPTH FILTER REMOVED ENTIRELY 2026-08-01 (5 inputs, plus Signals\SignalMarketDepth.mqh). //--- It needs real level-2 DOM data, which this development broker does not provide and which most //--- retail MT5 brokers do not provide either - so the module has never been executed against real data //--- even once. Shipping four tuning dropdowns for an UNTESTED code path is worse than shipping nothing: //--- the only users who could enable it are the ones whose broker supplies a book, and they would be //--- the first people ever to run it, in live trading, with no validation behind it. If DOM support is //--- wanted later it should return as a feature fed to the network rather than as a rule-based veto with //--- its own hand-tuned thresholds - the imbalance is data, and data belongs in the input vector. input string RiskGuard_Settings = "Risk Guard"; // Risk Guard input bool EnableRiskGuard = true; // Signal: Risk Guard //--- FREE-ENTRY PERCENTAGES, replacing the RISK_LIMIT_PCT_PRESET dropdown these two used to be //--- (that enum is gone - see Enumerations\InputEnums.mqh). Every funded/prop programme sets its own //--- numbers and they are not always integers, so a fixed ladder of presets could not express them; //--- 4.5% or 3.75% were simply unreachable. Enter the limits from YOUR account agreement, and enter //--- them slightly TIGHTER than the contract if you want margin for slippage past a stop. //--- 0 disables a rule. Enforced live at quote frequency by Variables\RiskBudget.mqh - not once per //--- bar, which is all the old guard could manage. input double MaxDailyLossPct = 4.0; // Daily loss limit % (0 = off) input double MaxDrawdownPct = 8.0; // Max total drawdown % (0 = off) //--- TRUE: max drawdown is measured down from the highest equity ever reached (trailing DD, the //--- stricter and more common funded-account rule). FALSE: measured from the equity this EA first //--- saw on the account (static DD). Pick whichever your programme actually uses - a trailing rule //--- applied to a static challenge halts trading long before it has to. input bool MaxDrawdownIsTrailing = true; // Max DD trails the equity peak //--- Broker-server hour at which the firm's trading day (and therefore the daily loss allowance) //--- resets. Broker time here is NOT your local time; if the firm quotes the reset in another zone, //--- convert it. A misaligned window hands the allowance back hours early or late. input int RiskDayResetHour = 0; // Risk day reset hour (broker time, 0-23) //--- Ceiling on what ONE trade may risk, as a share of the allowance that is genuinely left after //--- subtracting every open position's remaining loss-to-stop. This is the fix for the real breach //--- mode: without it a trade at 3.2% into a 4% day still sized for a full risk unit and a routine //--- stop-out went through the limit. At the default 50% a full stop-out spends at most half of //--- what is left, so even a stop that slips to twice its distance lands inside the limit. input double RiskPerTradeOfBudget = 50.0; // Max % of remaining budget per trade //--- Blocking new entries cannot stop an ALREADY-OPEN position from running through the limit, which //--- is the way a hard daily loss rule is actually breached. Turn this on to close this EA's own //--- positions (matching symbol + magic) the moment a limit is hit. Default OFF because closing //--- positions is a materially bigger behaviour change than declining to open them - but leaving it //--- off means the limits above are advisory, not enforced. input bool RiskGuardFlatten = false; // Close own positions on breach //--- EXPECTANCY STOP. The daily and total limits bound how FAST the account can lose; neither notices //--- WHETHER it is losing. A negative-expectancy signal traded inside a 4%/8% envelope breaches no rule //--- and still arrives at zero - it just takes longer. This tests the realised mean result per trade //--- against zero and stops opening new positions once it is significantly below. //--- Significantly, not merely below: a run of losers is ordinary variance even for a profitable system, //--- so the test uses the standard error of the mean and a wide spread simply demands more trades before //--- it can fire. Measured in R (net profit over money risked), so symbols and lot sizes share one scale, //--- and net of swap and commission - when the directional edge is zero, cost IS the expectancy. //--- 0 trades = off. The halt is LATCHED and survives a restart; clearing it means deleting the risk //--- state file, deliberately, after looking at why. input int ExpectancyMinTrades = 40; // Halt if losing: min closed trades first (0 = off) input double ExpectancySigma = 2.0; // ...and mean must be this many std errors below zero //================================================================================================== // TRADE JOURNAL / PATTERN RANKING //================================================================================================== input string Journal_Settings = "Trade Journal / Ranking"; // Trade Journal / Ranking //--- Enables the per-pattern win-rate database: scales each signal's vote by its historical win rate, //--- records every trade, and powers the Export Trade Journal Report button (see the control panel). //--- Default TRUE since 2026-08-13 (user request): a META chart should journal + rank out of the box, //--- and the classic-only configuration benefits from ranked weights as soon as history accumulates. input bool UseDatabaseRanking = true; // Weight filters by DB win-rate //--- Row cap per pattern table (oldest row pruned past it). 1000 is plenty for live ranking; a //--- META-LABEL CORPUS BUILD (Meta_Labeling_Design.md, stage S1: a long backtest whose signal DB //--- becomes the training set) needs it raised so a 15-20 year run isn't pruned away - 20000 holds //--- ~3x the densest pattern's 20-year stretch count. A high cap costs nothing until rows exist. input int DB_MaxRowsPerTable = 1000; // Max rows kept per pattern table //--- META DATASET EXPORT (cross-sectional pooling, Meta_Labeling_Design.md). With AIType=META, the //--- chart writes its full training set - every resolved candidate's feature window + setup //--- descriptor + triple-barrier label - to Common\Files\Warrior_EA\MetaExport\_.f32 //--- (float32 rows; sidecar .meta.csv carries width/geometry/BE) once per attach, then trains as //--- normal. Pooled training across symbols happens OFFLINE on these files; the EA itself is //--- unchanged. Costs one pass-1-sized sweep (~a minute) at attach. Default ON in the private build //--- (the pooling campaign's drop-on-chart workflow); OFF for Market. #ifdef WARRIOR_MARKET_BUILD input bool Meta_ExportDataset = false; // META: export training dataset at attach #else input bool Meta_ExportDataset = true; // META: export training dataset at attach #endif //--- Header only. The AI\Network.mqh optimizer inputs (Adam*, Sgd*) are declared in that library //--- header; because this Inputs file is included FIRST (see Warrior_EA.mq5), those //--- render immediately AFTER this divider - grouping them here instead of leading the Inputs tab. input string NNPerf_Settings = "NN Optimizer / Performance"; // NN Optimizer / Performance