Warrior_EA/Signals/SignalHYBRID.mqh
AnimateDread 8c0186c850 refactor(signals): AI signal files are identity + topology, nothing else
Every AI signal repeated the same five-line InitIndicators override that
did nothing but call InitNeuralNetwork. The cause was an access mismatch,
not a design: CExpertSignalCustom declares InitIndicators public, the AI
base redeclared it PROTECTED, and each subclass had to redeclare it
public to be reachable by CExpert. Worse, the base's own override does a
different job entirely - it creates the OHLC/ZigZag feature indicators -
and InitNeuralNetwork called it back scope-qualified to stop the virtual
dispatch landing in the subclass. Two jobs, one virtual name, and a
recursion trap held off by a scope qualifier.

The feature-indicator step is now InitFeatureIndicators() (protected,
non-virtual, named for what it does) and the AI base carries the single
public InitIndicators override. CONV/HYBRID/LSTM/PAI/META drop their
copies and are now purely identity plus topology, which is the classic
signal file's shape.

Comment pass on ExpertSignalAIBase.mqh, -100 lines with every constant
and every measured number kept. Three claims in the tier block were
stale and inverted - it named CalibratedConfidenceMagnitude() as the
tiering input where the code deliberately uses the RAW magnitude, and it
described the signal DB as re-ranking each tier when ApplyPatternWeight
declines the DB from the end of era 1. Also dropped a paragraph whose
subject was a previous version of the comment, and moved two notes down
onto the constants they document (CONV_COMPRESSION_DIVISOR was 16 lines
and three unrelated defines away from its own text).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 08:57:54 -04:00

59 lines
No EOL
3.5 KiB
MQL5

//+------------------------------------------------------------------+
//| Warrior_EA |
//| AnimateDread |
//| |
//+------------------------------------------------------------------+
#include "..\Expert\ExpertSignalAIBase.mqh"
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of indicator 'CNN-LSTM AI' |
//| Type=SignalAdvanced |
//| Name=CNN-LSTM AI |
//| ShortName=HYB |
//| Class=CSignalHYBRID |
//| Page=signal_hybrid |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalHYBRID. |
//| Purpose: a single fused CNN-LSTM signal that stacks Conv+Pool |
//| layers before the LSTM layer, then the shared dense taper. |
//| The base AI voting path still applies, so this module trades as |
//| one coherent signal instead of three loosely synchronized ones. |
//+------------------------------------------------------------------+
class CSignalHYBRID : public CExpertSignalAIBase
{
protected:
virtual bool AddCustomLayers(CArrayObj *topology) override;
//--- AddCustomLayers below appends BOTH stages, conv first - so this topology's LSTM is fed the conv
//--- feature map rather than the raw input. Keep these in step with AddCustomLayers: they are what let
//--- the capacity budget size the recurrent block against its REAL fan-in (see LstmFanIn()).
virtual bool UsesConvStage(void) const override { return true; }
virtual bool UsesLstmStage(void) const override { return true; }
virtual ENUM_ACTIVATION HiddenLayerActivation(void) override { return TANH; }
public:
CSignalHYBRID(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalHYBRID::CSignalHYBRID(void)
{
//--- Display name follows the 2026-08-15 rename (AI_CONVLSTM: conv front-end + LSTM).
//--- The SHORT id stays "HYB" deliberately: it names the model folder
//--- (Neural Networks\State\HYB\) and changing it would orphan every model trained
//--- under the old path - a rename is not worth a forced retrain.
SetIdentity("ConvLSTM", "HYB");
}
//+------------------------------------------------------------------+
//| Conv + Pool front-end followed by an LSTM sequence layer. This |
//| matches the standalone CONV front-end exactly, then adds LSTM. |
//+------------------------------------------------------------------+
bool CSignalHYBRID::AddCustomLayers(CArrayObj *topology)
{
//--- "the standalone CONV front-end exactly, then adds LSTM" is now enforced by construction:
//--- both stages are the same code CSignalCONV and CSignalLSTM run.
return AddConvStage(topology) && AddLstmStage(topology);
}
//+------------------------------------------------------------------+