Warrior_EA/Signals/SignalHYBRID.mqh
AnimateDread 65c4b1dce7 fix(ensemble): per-member arrow namespaces; ConvLSTM rename; dialog in purge list
The ensemble chart UI had a shared-namespace defect that answered the user
question "what do the arrows represent?" with "a bug": all four members drew
arrows under the same WarSig_<bartime> object names, so the chart showed
whichever member rendered LAST, one member Neutral deleted another member Buy
at the same bar, each member init sweep wiped the arrows the previous member
had just restored, and SaveChartSignals - which rebuilds the sidecar by
SCANNING the chart - persisted every other member arrows into its own history
(the exact cross-model laundering its own header warns about, now happening
BETWEEN ensemble members).

Arrows are now namespaced per member (WarSig_PAI_, WarSig_CONV_, WarSig_LSTM_,
WarSig_HYB_): draw, delete, restore, prune, member init sweep, destructor
purge and the sidecar scan are all member-scoped, and the tooltip names the
model. Global purges keep matching the bare WarSig_ prefix, which covers all
member namespaces plus old-format leftovers from earlier builds.

Labels: the ensemble panel header no longer says "HYBRID ensemble" (HYBRID is
one member; the header is the ensemble) and the CONVLSTM member displays as
ConvLSTM instead of Hybrid. Its SHORT id stays HYB deliberately - it names the
model folder and changing it would orphan every model trained under that path.

Deinit: the alt-data mapping dialog namespace (WarriorAltMap_) joins
WarriorChartPrefixes, so both the OnInit purge and the deinit final sweep now
cover it - it was in neither list, so a dialog starved of its own Destroy()
left its controls on the chart permanently.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 18:26:55 -04:00

67 lines
No EOL
3.9 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);
virtual bool InitIndicators(CIndicators *indicators) override;
};
//+------------------------------------------------------------------+
//| 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");
}
//+------------------------------------------------------------------+
//| Create indicators and bootstrap/load the network. |
//+------------------------------------------------------------------+
bool CSignalHYBRID::InitIndicators(CIndicators *indicators)
{
return InitNeuralNetwork(indicators);
}
//+------------------------------------------------------------------+
//| 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);
}
//+------------------------------------------------------------------+