Warrior_EA/Signals/SignalLSTM.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

54 lines
3 KiB
MQL5

//+------------------------------------------------------------------+
//| Warrior_EA |
//| AnimateDread |
//| |
//+------------------------------------------------------------------+
#include "..\Expert\ExpertSignalAIBase.mqh"
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of indicator 'LSTM AI' |
//| Type=SignalAdvanced |
//| Name=LSTM AI |
//| ShortName=LSTM |
//| Class=CSignalLSTM |
//| Page=signal_lstm |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalLSTM. |
//| Purpose: Class of generator of trade signals based on |
//| the 'LSTM AI' indicator. |
//| Is derived from the CExpertSignalAIBase class. |
//| Only the network topology differs from the other AI signals: an |
//| input layer feeds a single LSTM layer before the common tapering |
//| hidden-layer stack (see AddCustomLayers). |
//+------------------------------------------------------------------+
class CSignalLSTM : public CExpertSignalAIBase
{
protected:
virtual bool AddCustomLayers(CArrayObj *topology) override;
//--- keep in step with AddCustomLayers below - see the base declarations.
virtual bool UsesLstmStage(void) const override { return true; }
//--- keep the tapering Dense stack TANH-bounded, matching the LSTM layer's own bounded
//--- output, instead of the base class's default PRELU (see the base declaration's comment)
virtual ENUM_ACTIVATION HiddenLayerActivation(void) override { return TANH; }
public:
CSignalLSTM(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalLSTM::CSignalLSTM(void)
{
SetIdentity("LSTM", "LSTM");
}
//+------------------------------------------------------------------+
//| LSTM layer inserted between the input layer and the common |
//| tapering hidden-layer stack. |
//+------------------------------------------------------------------+
bool CSignalLSTM::AddCustomLayers(CArrayObj *topology)
{
return AddLstmStage(topology);
}
//+------------------------------------------------------------------+