DRY - topology construction
---------------------------
CSignalCONV and CSignalHYBRID each built the Conv+Pool front-end from scratch;
CSignalLSTM and CSignalHYBRID each built the LSTM stage from scratch. The
duplicates had already drifted: HYBRID guarded the LSTM step with
MathMax(1, historyBars/2), CSignalLSTM divided unguarded, so a historyBars of 1
gave two different steps for what is documented as the same layer.
Extracted AddConvPoolStage() and AddLstmStage() onto CExpertSignalAIBase. The
three overrides are now compositions:
CONV = AddConvPoolStage
LSTM = AddLstmStage
HYBRID = AddConvPoolStage && AddLstmStage
HYBRID's "matches the standalone CONV front-end exactly, then adds LSTM" is
enforced by construction instead of by comment. Took the guarded step for both.
Also fixed a descriptor leak the duplicates shared: on a failed topology.Add()
the CLayerDescription was neither owned by the array nor deleted.
Dead code
---------
- CNet::SaveCheckpoint / CNet::LoadCheckpoint (123 lines). Superseded by the
in-memory CaptureWeights/RestoreWeights pair; Network.mqh:1312 already said so
("This replaces the file-based SaveCheckpoint/LoadCheckpoint"). Zero call
sites - every remaining mention was a comment. The five comments that
referenced them have been reworded rather than left dangling.
- CExpertSignalCustom::CheckForDuplicateTrade / FindLastTradeIndex /
UpdateTradeStatusAndExit: declared, never defined anywhere, never called.
They only made it look as though duplicate-trade detection existed.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
In AI/Network.mqh, return early from InitDirectML during
tester/optimization/forward runs to prevent agent-side file-lock
failures caused by rapid stop/restart cycles accessing DLL imports.
In Expert/ExpertSignalAIBase.mqh, add MathIsValidNumber checks in
CalibratedConfidenceMagnitude and SignaledConfidence to safely handle
NaN values, and refactor ShutdownChartCleanup to accept a preserve
flag, avoiding unnecessary chart purges during tester runs for faster
shutdowns. Also add m_purgeChartOnDestruct member.
In AI/NeuronDirectML.mqh, clean up a minor comment formatting issue.
Introduce a global boolean `g_signalsVisible` to control whether signal
objects are displayed across all timeframes or hidden entirely. When
enabled, chart arrows and restore objects are set to `OBJ_ALL_PERIODS`;
otherwise they use `OBJ_NO_PERIODS`, allowing signals to be shown or
hidden at runtime without losing saved state.
Add `ShouldTraceTradeRejections()` helper that returns true only when
running in the Strategy Tester, optimization, or forward testing modes.
Use it to print diagnostic messages when trades are rejected due to a
prohibition signal or when `OpenLongParams`/`OpenShortParams` fail to
produce valid stop/take-profit levels. This provides targeted debugging
output without cluttering live trading logs.
Add freeze-level checks, no-change modification skipping, entry price routing, and per-tick/memory budget monitoring. Override trade actions (Open, Close, Reverse, TrailingStop, TrailingOrder) to validate at the final gate before sending orders.
Add MACD_FAST, MACD_SLOW, MACD_SIGNAL presets and Ichimoku Tenkan, Kijun, Senkou presets to InputEnums.mqh. All combinations are designed to satisfy the respective indicator's validation rules (fast < slow for MACD, Tenkan < Kijun < Senkou B for Ichimoku), eliminating init errors and allowing the auto-tuner to perturb settings independently.
Introduce VOTE_CLOSE_PRESETS enum with a Disabled option (value 101) that bypasses vote-driven position closing via arithmetic thresholding, removing the need for a separate boolean flag. This ensures positions exit only via stop-loss, take-profit, or trailing when disabled.
Add BeginVote/RevokeVote lifecycle hooks to ExpertSignalCustom and ExpertSignalAIBase.
Snapshot m_lastNonNeutralSignal before condition evaluation in Direction(), and restore
the snapshot if the vote is later discarded (e.g., Hybrid quorum shortfall).
Previously, a discarded vote still consumed the alternation gate, which could
permanently gate out valid signals until the opposite direction appeared.
:106 — window key changed from the 0-59 sec field to a full datetime. Fixing #1 alone would have replaced "always 0" with "cumulative average of every bar since startup", since the window still never rolled over.
:746 — restored result /= number. number was being counted and then never used, leaving a raw sum where the base class averages. MA's 60 + RSI's 100 = 160 tripped the ±100 range check and got zeroed — it discarded precisely the strongest agreed setups.
The previous TP calculation used ATR from entry, decoupled from the swing-anchored SL distance. This caused the Min_Risk_Reward_Ratio rejection filter to always fail because reward < 2*risk with default settings, preventing any trades. Now TP is a multiple of the actual trade risk (entry-to-stop distance), restoring coupling and ensuring the default RR filter is satisfiable. Also enforce minimum SL distance before TP calculation to maintain correct risk-ratio.
Replace single `m_pattern_0` weight with four confidence-tier weights (`m_pattern_0` through `m_pattern_3`) so that `UpdateSignalsWeights()` blends across multiple patterns like classic indicators. Previously, a single pattern caused the same win rate to be written to both the pattern weight and module weight, resulting in a quadratic derating (e.g., 70% win rate scored as 49 instead of 70). The new tiers bucket confidence into four equal bands between the minimum AI confidence and 1.0, with defaults 80/87/93/100. Added `ConfidenceTier()` and `PatternWeightForTier()` helpers, and changed default pattern count from 1 to 4.
- Added optional `weighScale` parameter (default -1.0) to `CNeuronBase::Init` and `CLayer::CreateElement`.
- Updated `CNeuronPool::Init` to use LeCun-uniform scaling (1/sqrt(window+1)) for its base initialization.
- Updated `CNet::CNet` to use He-scaled initialization (sqrt(2/neurons)) for dense layers.
- These changes enable more flexible and statistically sound weight initialization, matching the rationale used in OCL-based implementations, leading to better training stability and convergence.
Replace old ATR_MULTIPLIER, THRESHOLDS_PRESET enums with new
STOP_LOSS_MODE, TAKE_PROFIT_MODE, AI_EXIT_MODE enums that support
ATR-based, intelligent confidence-scaled, and swing-anchored modes.
Also fix LSTM signal identity string.
Optimize() scaled lot size off account trade-history streaks with no Magic-number
filter (picked up other EAs'/manual trades) and an unconfigurable m_factor stuck at
1.0 (Factor() was never wired from an input), so a 3-trade streak could triple lot
size or send it negative. It was also entirely disconnected from what the AI model
actually knows about the current setup.
Replaced both AdjustRiskAmount()'s linear confidence-only scale and Optimize()'s
streak multiplier with one edge-based model: p from the empirically calibrated
AI/DB confidence magnitude, b from the trade's real reward:risk ratio (newly
bridged from OpenParams() via g_TradeRewardRiskRatio), quarter-Kelly applied and
clamped so risk% can only ever scale down from its configured ceiling, never above it.
Replace the hardcoded `MAX_CLASS_SAMPLE_WEIGHT` (3.0) with a tunable member variable `m_maxClassSampleWeight`, controlled by the new `CLASS_SAMPLE_WEIGHT_PRESET` input enum. This allows adjusting the ceiling on rare-class sample weights to prevent the previously observed anti-correlated Buy/Sell recall whipsaw (where a high multiplier caused one era's gradients to overwrite another class's separability). Default is CSW_15 (1.5x), which is gentler than the old 3.0x; lower values down to 1.0x disable rebalancing to train on raw label distribution, while higher values (up to 3.0x) converge faster but risk instability. This tuning can now be done without recompiling.
- Define MAX_WEIGHT constant (1.0e6) for weight limits in clusters
- Remove redundant barrier from FeedForward kernel (prevents sync issues)
- Port FeedForwardProof and CalcInputGradientProof kernels for max-pooling (no weights, sliding max)
- Port FeedForwardConv kernel for convolution layers (shared weights, multiple output channels)
- Remove unused code and refactor signal condition logic (CSignalPAI)