refactor(ExpertSignalAIBase): extract AutoTune param state into CADIndicatorTuner
CExpertSignalAIBase (4,326 lines, one class) carried 5 struct
definitions, 10 member fields, and 3 methods (Flatten/Unflatten/
PerturbRandom) purely for the AutoTuneIndicators search-space state -
entirely self-contained (never touches Net, Train()'s resumable state
machine, or anything else in the class). Extracted into a new
Expert/ADIndicatorTuner.mqh (CADIndicatorTuner), held as a single
m_indicatorTuner member.
TuneIndicatorsAndTrain() itself - the outer loop that actually
orchestrates Train()/Net/checkpointing around this tuner - turned out
to be exactly as tightly coupled to Train()'s resumable state machine
as Train() itself, so per the same caution already applied to Train()
in this refactor pass, it stays in CExpertSignalAIBase rather than
being pulled into the collaborator; it now calls the tuner's public
Flatten()/Unflatten()/PerturbRandom()/SaveAsBest()/RestoreBest()
instead of manipulating the structs inline.
All internal field-access renames (m_adCumDeltaParams.lookback ->
m_indicatorTuner.adCumDelta.lookback, etc., ~40 sites across the 5
InitAD*() indicator-setup methods) verified against a full grep sweep
- no leftover references to the old field/method names. Compiled
clean (MetaEditor, 0 errors/0 warnings).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:22:09 -04:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| ADIndicatorTuner.mqh |
|
|
|
|
|
//| AnimateDread |
|
|
|
|
|
//| https://www.mql5.com |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
#include "..\Variables\IndicatorTuneRanges.mqh"
|
2026-07-26 18:33:12 -04:00
|
|
|
//--- flat count of AutoTuneIndicators-tunable params across all 5 AD indicators plus the MA/RSI/MACD/
|
|
|
|
|
//--- Ichimoku feature periods, used to persist/restore the "winning" values in the .nnw file. ATR and
|
|
|
|
|
//--- Volume are intentionally NOT included: ATR's only tunable knob is m_periods, the shared bar lookback
|
2026-07-22 22:51:04 -04:00
|
|
|
//--- (ind_Periods); Volume's applied-price type (tick vs real) is kept as a plain manual input
|
|
|
|
|
//--- (VolumeData) since not every symbol has real volume available.
|
2026-07-26 18:33:12 -04:00
|
|
|
//--- NOTE changing this value invalidates every persisted tuner block - Unflatten() below refuses a
|
|
|
|
|
//--- size-mismatched array and falls back to the constructor defaults, so any model trained before the
|
|
|
|
|
//--- change loses its previously-tuned indicator params (it says so in the log). That is the accepted
|
|
|
|
|
//--- cost of adding a tunable; the network weights themselves are unaffected.
|
|
|
|
|
#define AD_TUNE_PARAM_COUNT 39
|
refactor(ExpertSignalAIBase): extract AutoTune param state into CADIndicatorTuner
CExpertSignalAIBase (4,326 lines, one class) carried 5 struct
definitions, 10 member fields, and 3 methods (Flatten/Unflatten/
PerturbRandom) purely for the AutoTuneIndicators search-space state -
entirely self-contained (never touches Net, Train()'s resumable state
machine, or anything else in the class). Extracted into a new
Expert/ADIndicatorTuner.mqh (CADIndicatorTuner), held as a single
m_indicatorTuner member.
TuneIndicatorsAndTrain() itself - the outer loop that actually
orchestrates Train()/Net/checkpointing around this tuner - turned out
to be exactly as tightly coupled to Train()'s resumable state machine
as Train() itself, so per the same caution already applied to Train()
in this refactor pass, it stays in CExpertSignalAIBase rather than
being pulled into the collaborator; it now calls the tuner's public
Flatten()/Unflatten()/PerturbRandom()/SaveAsBest()/RestoreBest()
instead of manipulating the structs inline.
All internal field-access renames (m_adCumDeltaParams.lookback ->
m_indicatorTuner.adCumDelta.lookback, etc., ~40 sites across the 5
InitAD*() indicator-setup methods) verified against a full grep sweep
- no leftover references to the old field/method names. Compiled
clean (MetaEditor, 0 errors/0 warnings).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:22:09 -04:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Currently-active tunable input values for each AD indicator (AutoTuneIndicators search space).
|
|
|
|
|
//| InpContextMode/InpSessionType/InpSessionCount are session choices, not accuracy knobs, and are
|
|
|
|
|
//| hardcoded to the indicators' own defaults in CExpertSignalAIBase::InitAD*() rather than
|
|
|
|
|
//| stored/tuned here.
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
struct SADCumulativeDeltaParams
|
|
|
|
|
{
|
|
|
|
|
int lookback;
|
|
|
|
|
double volClimax, volHigh, rangeClimax, rangeSignificant, stVolRatio, atrMult;
|
|
|
|
|
};
|
|
|
|
|
struct SADShorteningOfThrustParams
|
|
|
|
|
{
|
|
|
|
|
int thrustLookback, minImpulses;
|
|
|
|
|
double sotThreshold;
|
|
|
|
|
};
|
|
|
|
|
struct SADWyckoffEventStreamParams
|
|
|
|
|
{
|
|
|
|
|
int lookback, zigzag;
|
|
|
|
|
double volClimax, volHigh, rangeClimax, rangeSignificant, stVolRatio, atr;
|
|
|
|
|
};
|
|
|
|
|
struct SADWyckoffFailedStructureParams
|
|
|
|
|
{
|
|
|
|
|
int lookback, zigzagStrength;
|
|
|
|
|
double volClimax, volHigh, rangeClimax, rangeSignificant, stVolRatio, atrMult;
|
|
|
|
|
};
|
|
|
|
|
struct SADWyckoffSignificantBarInversionParams
|
|
|
|
|
{
|
|
|
|
|
int lookback;
|
|
|
|
|
double rangeSignificant, volumeHigh, atr;
|
|
|
|
|
};
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Class CADIndicatorTuner. |
|
|
|
|
|
//| Owns the AutoTuneIndicators search-space state (current + best-known tunable values for all 5 |
|
|
|
|
|
//| AD indicators) and its own mutation logic (random perturbation, flatten/unflatten for .nnw |
|
|
|
|
|
//| persistence, win/loss bookkeeping) - extracted out of CExpertSignalAIBase (SOLID cleanup) since |
|
|
|
|
|
//| this state and behavior is entirely self-contained: it never touches Net, Train()'s state |
|
|
|
|
|
//| machine, or anything else in CExpertSignalAIBase. CExpertSignalAIBase::TuneIndicatorsAndTrain() |
|
|
|
|
|
//| (which DOES orchestrate Train()/Net/checkpointing around this tuner) stays put - that outer loop |
|
|
|
|
|
//| is exactly as tightly coupled to Train()'s resumable state machine as Train() itself, so it's |
|
|
|
|
|
//| deliberately NOT pulled in here; see this file's declaration comment in ExpertSignalAIBase.mqh |
|
|
|
|
|
//| for the full rationale. |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
class CADIndicatorTuner
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
SADCumulativeDeltaParams adCumDelta;
|
|
|
|
|
SADShorteningOfThrustParams adSOT;
|
|
|
|
|
SADWyckoffEventStreamParams adWES;
|
|
|
|
|
SADWyckoffFailedStructureParams adWFS;
|
|
|
|
|
SADWyckoffSignificantBarInversionParams adWSBI;
|
2026-07-22 22:51:04 -04:00
|
|
|
//--- AI-feature MA/RSI periods (see CExpertSignalAIBase::InitMA()/InitRSI()) - searched the same
|
|
|
|
|
//--- way as the AD indicators above, snapped to MA_PERIOD_PRESETS/RSI_PERIOD_PRESETS so a search
|
|
|
|
|
//--- never lands on a non-standard period. Starts from the Classic Signals PeriodMA/PeriodRSI
|
|
|
|
|
//--- input value; only ever diverges from it once AutoTuneIndicators actually runs a trial. The
|
|
|
|
|
//--- Classic Signals MA/RSI vote itself keeps using the literal input, untouched by this search -
|
|
|
|
|
//--- it needs no training/warm-up, so there's nothing for a tuning trial to validate it against.
|
|
|
|
|
int maPeriod;
|
feat: add unified MA type support to indicator tuner
Add `MA_TYPE_PRESETS` enum covering advanced (ALMA, DEMA, ZLEMA, T3, Kalman) and standard (SMA, EMA, SMMA, LWMA) moving averages. Integrate `maType` and `bestMaType` into `CADIndicatorTuner` struct, update flatten/unflatten routines, and bump `AD_TUNE_PARAM_COUNT` to 33. This allows the auto-tuner to search over MA type alongside period, improving feature discovery.
2026-07-23 15:02:09 -04:00
|
|
|
//--- unified MA TYPE (MA_TYPE_PRESETS 0..8), searched alongside maPeriod when the MA feature is on.
|
|
|
|
|
//--- Starts from the MA_Type input; only diverges once a tuning trial runs. Feeds InitMA()'s CiCustom.
|
|
|
|
|
int maType;
|
2026-07-22 22:51:04 -04:00
|
|
|
int rsiPeriod;
|
2026-07-26 18:33:12 -04:00
|
|
|
//--- MACD feature periods (see CExpertSignalAIBase::InitMACDFeature()) - snapped to
|
|
|
|
|
//--- MACD_*_PRESETS, whose preset sets are built so every fast/slow pair stays legal no matter which
|
|
|
|
|
//--- one a trial perturbs (see InputEnums.mqh). Same "the classic vote keeps the raw input" split as
|
|
|
|
|
//--- maPeriod/rsiPeriod above: Signals\SignalMACD.mqh is untouched by this search.
|
|
|
|
|
int macdFast;
|
|
|
|
|
int macdSlow;
|
|
|
|
|
int macdSignal;
|
|
|
|
|
//--- Ichimoku feature periods (see CExpertSignalAIBase::InitIchimoku()) - snapped to ICHIMOKU_*
|
|
|
|
|
//--- presets, likewise mutually-legal in any combination. Signals\SignalIchimoku.mqh is untouched.
|
|
|
|
|
int ichiTenkan;
|
|
|
|
|
int ichiKijun;
|
|
|
|
|
int ichiSenkou;
|
refactor(ExpertSignalAIBase): extract AutoTune param state into CADIndicatorTuner
CExpertSignalAIBase (4,326 lines, one class) carried 5 struct
definitions, 10 member fields, and 3 methods (Flatten/Unflatten/
PerturbRandom) purely for the AutoTuneIndicators search-space state -
entirely self-contained (never touches Net, Train()'s resumable state
machine, or anything else in the class). Extracted into a new
Expert/ADIndicatorTuner.mqh (CADIndicatorTuner), held as a single
m_indicatorTuner member.
TuneIndicatorsAndTrain() itself - the outer loop that actually
orchestrates Train()/Net/checkpointing around this tuner - turned out
to be exactly as tightly coupled to Train()'s resumable state machine
as Train() itself, so per the same caution already applied to Train()
in this refactor pass, it stays in CExpertSignalAIBase rather than
being pulled into the collaborator; it now calls the tuner's public
Flatten()/Unflatten()/PerturbRandom()/SaveAsBest()/RestoreBest()
instead of manipulating the structs inline.
All internal field-access renames (m_adCumDeltaParams.lookback ->
m_indicatorTuner.adCumDelta.lookback, etc., ~40 sites across the 5
InitAD*() indicator-setup methods) verified against a full grep sweep
- no leftover references to the old field/method names. Compiled
clean (MetaEditor, 0 errors/0 warnings).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:22:09 -04:00
|
|
|
//--- best-known copies of the above, kept during TuneIndicatorsAndTrain() so a losing trial can
|
|
|
|
|
//--- restore rather than drift from a bad candidate - see SaveAsBest()/RestoreBest().
|
|
|
|
|
SADCumulativeDeltaParams bestAdCumDelta;
|
|
|
|
|
SADShorteningOfThrustParams bestAdSOT;
|
|
|
|
|
SADWyckoffEventStreamParams bestAdWES;
|
|
|
|
|
SADWyckoffFailedStructureParams bestAdWFS;
|
|
|
|
|
SADWyckoffSignificantBarInversionParams bestAdWSBI;
|
2026-07-22 22:51:04 -04:00
|
|
|
int bestMaPeriod;
|
feat: add unified MA type support to indicator tuner
Add `MA_TYPE_PRESETS` enum covering advanced (ALMA, DEMA, ZLEMA, T3, Kalman) and standard (SMA, EMA, SMMA, LWMA) moving averages. Integrate `maType` and `bestMaType` into `CADIndicatorTuner` struct, update flatten/unflatten routines, and bump `AD_TUNE_PARAM_COUNT` to 33. This allows the auto-tuner to search over MA type alongside period, improving feature discovery.
2026-07-23 15:02:09 -04:00
|
|
|
int bestMaType;
|
2026-07-22 22:51:04 -04:00
|
|
|
int bestRsiPeriod;
|
2026-07-26 18:33:12 -04:00
|
|
|
int bestMacdFast;
|
|
|
|
|
int bestMacdSlow;
|
|
|
|
|
int bestMacdSignal;
|
|
|
|
|
int bestIchiTenkan;
|
|
|
|
|
int bestIchiKijun;
|
|
|
|
|
int bestIchiSenkou;
|
refactor(ExpertSignalAIBase): extract AutoTune param state into CADIndicatorTuner
CExpertSignalAIBase (4,326 lines, one class) carried 5 struct
definitions, 10 member fields, and 3 methods (Flatten/Unflatten/
PerturbRandom) purely for the AutoTuneIndicators search-space state -
entirely self-contained (never touches Net, Train()'s resumable state
machine, or anything else in the class). Extracted into a new
Expert/ADIndicatorTuner.mqh (CADIndicatorTuner), held as a single
m_indicatorTuner member.
TuneIndicatorsAndTrain() itself - the outer loop that actually
orchestrates Train()/Net/checkpointing around this tuner - turned out
to be exactly as tightly coupled to Train()'s resumable state machine
as Train() itself, so per the same caution already applied to Train()
in this refactor pass, it stays in CExpertSignalAIBase rather than
being pulled into the collaborator; it now calls the tuner's public
Flatten()/Unflatten()/PerturbRandom()/SaveAsBest()/RestoreBest()
instead of manipulating the structs inline.
All internal field-access renames (m_adCumDeltaParams.lookback ->
m_indicatorTuner.adCumDelta.lookback, etc., ~40 sites across the 5
InitAD*() indicator-setup methods) verified against a full grep sweep
- no leftover references to the old field/method names. Compiled
clean (MetaEditor, 0 errors/0 warnings).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:22:09 -04:00
|
|
|
CADIndicatorTuner(void);
|
|
|
|
|
//--- flattens/restores the tunable param structs to/from a fixed-size array so they can be
|
|
|
|
|
//--- persisted alongside the network weights (see AI/Network.mqh Save()/Load())
|
|
|
|
|
void Flatten(double &arr[]);
|
|
|
|
|
void Unflatten(const double &arr[]);
|
2026-07-26 18:33:12 -04:00
|
|
|
//--- randomly perturbs one tunable param of one enabled AD indicator (or the MA/RSI/MACD/Ichimoku
|
|
|
|
|
//--- periods), within IndicatorTuneRanges.mqh bounds / the logical period presets. The use* args
|
|
|
|
|
//--- mirror CExpertSignalAIBase's m_useADCumulativeDelta/etc. (and m_useMA/m_useRSI/m_useMACD/
|
|
|
|
|
//--- m_useIchimoku) enable flags - no-op if all nine are false.
|
|
|
|
|
void PerturbRandom(bool useCumDelta, bool useSOT, bool useWES, bool useWFS, bool useWSBI, bool useMA, bool useRSI, bool useMACD, bool useIchimoku);
|
refactor(ExpertSignalAIBase): extract AutoTune param state into CADIndicatorTuner
CExpertSignalAIBase (4,326 lines, one class) carried 5 struct
definitions, 10 member fields, and 3 methods (Flatten/Unflatten/
PerturbRandom) purely for the AutoTuneIndicators search-space state -
entirely self-contained (never touches Net, Train()'s resumable state
machine, or anything else in the class). Extracted into a new
Expert/ADIndicatorTuner.mqh (CADIndicatorTuner), held as a single
m_indicatorTuner member.
TuneIndicatorsAndTrain() itself - the outer loop that actually
orchestrates Train()/Net/checkpointing around this tuner - turned out
to be exactly as tightly coupled to Train()'s resumable state machine
as Train() itself, so per the same caution already applied to Train()
in this refactor pass, it stays in CExpertSignalAIBase rather than
being pulled into the collaborator; it now calls the tuner's public
Flatten()/Unflatten()/PerturbRandom()/SaveAsBest()/RestoreBest()
instead of manipulating the structs inline.
All internal field-access renames (m_adCumDeltaParams.lookback ->
m_indicatorTuner.adCumDelta.lookback, etc., ~40 sites across the 5
InitAD*() indicator-setup methods) verified against a full grep sweep
- no leftover references to the old field/method names. Compiled
clean (MetaEditor, 0 errors/0 warnings).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:22:09 -04:00
|
|
|
//--- snapshots current -> best (a winning trial) / restores best -> current (undoing a losing trial)
|
|
|
|
|
void SaveAsBest(void);
|
|
|
|
|
void RestoreBest(void);
|
|
|
|
|
};
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Defaults mirror each CustomIndicators\AD*.mq5 input's own default. |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
CADIndicatorTuner::CADIndicatorTuner(void)
|
|
|
|
|
{
|
|
|
|
|
adCumDelta.lookback = 50;
|
|
|
|
|
adCumDelta.volClimax = 2.5;
|
|
|
|
|
adCumDelta.volHigh = 1.5;
|
|
|
|
|
adCumDelta.rangeClimax = 1.8;
|
|
|
|
|
adCumDelta.rangeSignificant = 1.2;
|
|
|
|
|
adCumDelta.stVolRatio = 0.6;
|
|
|
|
|
adCumDelta.atrMult = 0.5;
|
|
|
|
|
adSOT.thrustLookback = 30;
|
|
|
|
|
adSOT.minImpulses = 3;
|
|
|
|
|
adSOT.sotThreshold = 0.30;
|
|
|
|
|
adWES.lookback = 50;
|
|
|
|
|
adWES.zigzag = 3;
|
|
|
|
|
adWES.volClimax = 2.5;
|
|
|
|
|
adWES.volHigh = 1.5;
|
|
|
|
|
adWES.rangeClimax = 1.8;
|
|
|
|
|
adWES.rangeSignificant = 1.2;
|
|
|
|
|
adWES.stVolRatio = 0.6;
|
|
|
|
|
adWES.atr = 0.5;
|
|
|
|
|
adWFS.lookback = 50;
|
|
|
|
|
adWFS.zigzagStrength = 3;
|
|
|
|
|
adWFS.volClimax = 2.5;
|
|
|
|
|
adWFS.volHigh = 1.5;
|
|
|
|
|
adWFS.rangeClimax = 1.8;
|
|
|
|
|
adWFS.rangeSignificant = 1.2;
|
|
|
|
|
adWFS.stVolRatio = 0.6;
|
|
|
|
|
adWFS.atrMult = 0.5;
|
|
|
|
|
adWSBI.lookback = 50;
|
|
|
|
|
adWSBI.rangeSignificant = 1.2;
|
|
|
|
|
adWSBI.volumeHigh = 1.5;
|
|
|
|
|
adWSBI.atr = 0.5;
|
2026-07-22 22:51:04 -04:00
|
|
|
maPeriod = PeriodMA;
|
feat: add unified MA type support to indicator tuner
Add `MA_TYPE_PRESETS` enum covering advanced (ALMA, DEMA, ZLEMA, T3, Kalman) and standard (SMA, EMA, SMMA, LWMA) moving averages. Integrate `maType` and `bestMaType` into `CADIndicatorTuner` struct, update flatten/unflatten routines, and bump `AD_TUNE_PARAM_COUNT` to 33. This allows the auto-tuner to search over MA type alongside period, improving feature discovery.
2026-07-23 15:02:09 -04:00
|
|
|
maType = MA_Type;
|
2026-07-22 22:51:04 -04:00
|
|
|
rsiPeriod = PeriodRSI;
|
2026-07-26 18:33:12 -04:00
|
|
|
macdFast = MACD_PeriodFast;
|
|
|
|
|
macdSlow = MACD_PeriodSlow;
|
|
|
|
|
macdSignal = MACD_PeriodSignal;
|
|
|
|
|
ichiTenkan = Ichimoku_PeriodTenkan;
|
|
|
|
|
ichiKijun = Ichimoku_PeriodKijun;
|
|
|
|
|
ichiSenkou = Ichimoku_PeriodSenkou;
|
refactor(ExpertSignalAIBase): extract AutoTune param state into CADIndicatorTuner
CExpertSignalAIBase (4,326 lines, one class) carried 5 struct
definitions, 10 member fields, and 3 methods (Flatten/Unflatten/
PerturbRandom) purely for the AutoTuneIndicators search-space state -
entirely self-contained (never touches Net, Train()'s resumable state
machine, or anything else in the class). Extracted into a new
Expert/ADIndicatorTuner.mqh (CADIndicatorTuner), held as a single
m_indicatorTuner member.
TuneIndicatorsAndTrain() itself - the outer loop that actually
orchestrates Train()/Net/checkpointing around this tuner - turned out
to be exactly as tightly coupled to Train()'s resumable state machine
as Train() itself, so per the same caution already applied to Train()
in this refactor pass, it stays in CExpertSignalAIBase rather than
being pulled into the collaborator; it now calls the tuner's public
Flatten()/Unflatten()/PerturbRandom()/SaveAsBest()/RestoreBest()
instead of manipulating the structs inline.
All internal field-access renames (m_adCumDeltaParams.lookback ->
m_indicatorTuner.adCumDelta.lookback, etc., ~40 sites across the 5
InitAD*() indicator-setup methods) verified against a full grep sweep
- no leftover references to the old field/method names. Compiled
clean (MetaEditor, 0 errors/0 warnings).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:22:09 -04:00
|
|
|
SaveAsBest();
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CADIndicatorTuner::Flatten(double &arr[])
|
|
|
|
|
{
|
|
|
|
|
ArrayResize(arr, AD_TUNE_PARAM_COUNT);
|
|
|
|
|
int i = 0;
|
|
|
|
|
arr[i++] = adCumDelta.lookback;
|
|
|
|
|
arr[i++] = adCumDelta.volClimax;
|
|
|
|
|
arr[i++] = adCumDelta.volHigh;
|
|
|
|
|
arr[i++] = adCumDelta.rangeClimax;
|
|
|
|
|
arr[i++] = adCumDelta.rangeSignificant;
|
|
|
|
|
arr[i++] = adCumDelta.stVolRatio;
|
|
|
|
|
arr[i++] = adCumDelta.atrMult;
|
|
|
|
|
arr[i++] = adSOT.thrustLookback;
|
|
|
|
|
arr[i++] = adSOT.minImpulses;
|
|
|
|
|
arr[i++] = adSOT.sotThreshold;
|
|
|
|
|
arr[i++] = adWES.lookback;
|
|
|
|
|
arr[i++] = adWES.zigzag;
|
|
|
|
|
arr[i++] = adWES.volClimax;
|
|
|
|
|
arr[i++] = adWES.volHigh;
|
|
|
|
|
arr[i++] = adWES.rangeClimax;
|
|
|
|
|
arr[i++] = adWES.rangeSignificant;
|
|
|
|
|
arr[i++] = adWES.stVolRatio;
|
|
|
|
|
arr[i++] = adWES.atr;
|
|
|
|
|
arr[i++] = adWFS.lookback;
|
|
|
|
|
arr[i++] = adWFS.zigzagStrength;
|
|
|
|
|
arr[i++] = adWFS.volClimax;
|
|
|
|
|
arr[i++] = adWFS.volHigh;
|
|
|
|
|
arr[i++] = adWFS.rangeClimax;
|
|
|
|
|
arr[i++] = adWFS.rangeSignificant;
|
|
|
|
|
arr[i++] = adWFS.stVolRatio;
|
|
|
|
|
arr[i++] = adWFS.atrMult;
|
|
|
|
|
arr[i++] = adWSBI.lookback;
|
|
|
|
|
arr[i++] = adWSBI.rangeSignificant;
|
|
|
|
|
arr[i++] = adWSBI.volumeHigh;
|
|
|
|
|
arr[i++] = adWSBI.atr;
|
2026-07-22 22:51:04 -04:00
|
|
|
arr[i++] = maPeriod;
|
feat: add unified MA type support to indicator tuner
Add `MA_TYPE_PRESETS` enum covering advanced (ALMA, DEMA, ZLEMA, T3, Kalman) and standard (SMA, EMA, SMMA, LWMA) moving averages. Integrate `maType` and `bestMaType` into `CADIndicatorTuner` struct, update flatten/unflatten routines, and bump `AD_TUNE_PARAM_COUNT` to 33. This allows the auto-tuner to search over MA type alongside period, improving feature discovery.
2026-07-23 15:02:09 -04:00
|
|
|
arr[i++] = maType;
|
2026-07-22 22:51:04 -04:00
|
|
|
arr[i++] = rsiPeriod;
|
2026-07-26 18:33:12 -04:00
|
|
|
arr[i++] = macdFast;
|
|
|
|
|
arr[i++] = macdSlow;
|
|
|
|
|
arr[i++] = macdSignal;
|
|
|
|
|
arr[i++] = ichiTenkan;
|
|
|
|
|
arr[i++] = ichiKijun;
|
|
|
|
|
arr[i++] = ichiSenkou;
|
refactor(ExpertSignalAIBase): extract AutoTune param state into CADIndicatorTuner
CExpertSignalAIBase (4,326 lines, one class) carried 5 struct
definitions, 10 member fields, and 3 methods (Flatten/Unflatten/
PerturbRandom) purely for the AutoTuneIndicators search-space state -
entirely self-contained (never touches Net, Train()'s resumable state
machine, or anything else in the class). Extracted into a new
Expert/ADIndicatorTuner.mqh (CADIndicatorTuner), held as a single
m_indicatorTuner member.
TuneIndicatorsAndTrain() itself - the outer loop that actually
orchestrates Train()/Net/checkpointing around this tuner - turned out
to be exactly as tightly coupled to Train()'s resumable state machine
as Train() itself, so per the same caution already applied to Train()
in this refactor pass, it stays in CExpertSignalAIBase rather than
being pulled into the collaborator; it now calls the tuner's public
Flatten()/Unflatten()/PerturbRandom()/SaveAsBest()/RestoreBest()
instead of manipulating the structs inline.
All internal field-access renames (m_adCumDeltaParams.lookback ->
m_indicatorTuner.adCumDelta.lookback, etc., ~40 sites across the 5
InitAD*() indicator-setup methods) verified against a full grep sweep
- no leftover references to the old field/method names. Compiled
clean (MetaEditor, 0 errors/0 warnings).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:22:09 -04:00
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Reverse of Flatten(); ints are rounded on the way back in since |
|
|
|
|
|
//| everything is carried as double in the flat array. |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CADIndicatorTuner::Unflatten(const double &arr[])
|
|
|
|
|
{
|
|
|
|
|
if(ArraySize(arr) != AD_TUNE_PARAM_COUNT)
|
2026-07-26 12:12:14 -04:00
|
|
|
{
|
|
|
|
|
// A size mismatch means AD_TUNE_PARAM_COUNT changed since this array was persisted (e.g. after
|
|
|
|
|
// a version upgrade) - silently keeping the constructor defaults instead of the loaded values
|
|
|
|
|
// used to discard a previously-tuned indicator's best parameters with zero trace in the log.
|
|
|
|
|
Print(__FUNCTION__ + ": persisted tuner param array size (" + IntegerToString(ArraySize(arr)) +
|
|
|
|
|
") does not match AD_TUNE_PARAM_COUNT (" + IntegerToString(AD_TUNE_PARAM_COUNT) +
|
|
|
|
|
") - discarding it and keeping constructor defaults. This model's previously-tuned indicator parameters are lost.");
|
refactor(ExpertSignalAIBase): extract AutoTune param state into CADIndicatorTuner
CExpertSignalAIBase (4,326 lines, one class) carried 5 struct
definitions, 10 member fields, and 3 methods (Flatten/Unflatten/
PerturbRandom) purely for the AutoTuneIndicators search-space state -
entirely self-contained (never touches Net, Train()'s resumable state
machine, or anything else in the class). Extracted into a new
Expert/ADIndicatorTuner.mqh (CADIndicatorTuner), held as a single
m_indicatorTuner member.
TuneIndicatorsAndTrain() itself - the outer loop that actually
orchestrates Train()/Net/checkpointing around this tuner - turned out
to be exactly as tightly coupled to Train()'s resumable state machine
as Train() itself, so per the same caution already applied to Train()
in this refactor pass, it stays in CExpertSignalAIBase rather than
being pulled into the collaborator; it now calls the tuner's public
Flatten()/Unflatten()/PerturbRandom()/SaveAsBest()/RestoreBest()
instead of manipulating the structs inline.
All internal field-access renames (m_adCumDeltaParams.lookback ->
m_indicatorTuner.adCumDelta.lookback, etc., ~40 sites across the 5
InitAD*() indicator-setup methods) verified against a full grep sweep
- no leftover references to the old field/method names. Compiled
clean (MetaEditor, 0 errors/0 warnings).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:22:09 -04:00
|
|
|
return;
|
2026-07-26 12:12:14 -04:00
|
|
|
}
|
refactor(ExpertSignalAIBase): extract AutoTune param state into CADIndicatorTuner
CExpertSignalAIBase (4,326 lines, one class) carried 5 struct
definitions, 10 member fields, and 3 methods (Flatten/Unflatten/
PerturbRandom) purely for the AutoTuneIndicators search-space state -
entirely self-contained (never touches Net, Train()'s resumable state
machine, or anything else in the class). Extracted into a new
Expert/ADIndicatorTuner.mqh (CADIndicatorTuner), held as a single
m_indicatorTuner member.
TuneIndicatorsAndTrain() itself - the outer loop that actually
orchestrates Train()/Net/checkpointing around this tuner - turned out
to be exactly as tightly coupled to Train()'s resumable state machine
as Train() itself, so per the same caution already applied to Train()
in this refactor pass, it stays in CExpertSignalAIBase rather than
being pulled into the collaborator; it now calls the tuner's public
Flatten()/Unflatten()/PerturbRandom()/SaveAsBest()/RestoreBest()
instead of manipulating the structs inline.
All internal field-access renames (m_adCumDeltaParams.lookback ->
m_indicatorTuner.adCumDelta.lookback, etc., ~40 sites across the 5
InitAD*() indicator-setup methods) verified against a full grep sweep
- no leftover references to the old field/method names. Compiled
clean (MetaEditor, 0 errors/0 warnings).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:22:09 -04:00
|
|
|
int i = 0;
|
|
|
|
|
adCumDelta.lookback = (int)MathRound(arr[i++]);
|
|
|
|
|
adCumDelta.volClimax = arr[i++];
|
|
|
|
|
adCumDelta.volHigh = arr[i++];
|
|
|
|
|
adCumDelta.rangeClimax = arr[i++];
|
|
|
|
|
adCumDelta.rangeSignificant = arr[i++];
|
|
|
|
|
adCumDelta.stVolRatio = arr[i++];
|
|
|
|
|
adCumDelta.atrMult = arr[i++];
|
|
|
|
|
adSOT.thrustLookback = (int)MathRound(arr[i++]);
|
|
|
|
|
adSOT.minImpulses = (int)MathRound(arr[i++]);
|
|
|
|
|
adSOT.sotThreshold = arr[i++];
|
|
|
|
|
adWES.lookback = (int)MathRound(arr[i++]);
|
|
|
|
|
adWES.zigzag = (int)MathRound(arr[i++]);
|
|
|
|
|
adWES.volClimax = arr[i++];
|
|
|
|
|
adWES.volHigh = arr[i++];
|
|
|
|
|
adWES.rangeClimax = arr[i++];
|
|
|
|
|
adWES.rangeSignificant = arr[i++];
|
|
|
|
|
adWES.stVolRatio = arr[i++];
|
|
|
|
|
adWES.atr = arr[i++];
|
|
|
|
|
adWFS.lookback = (int)MathRound(arr[i++]);
|
|
|
|
|
adWFS.zigzagStrength = (int)MathRound(arr[i++]);
|
|
|
|
|
adWFS.volClimax = arr[i++];
|
|
|
|
|
adWFS.volHigh = arr[i++];
|
|
|
|
|
adWFS.rangeClimax = arr[i++];
|
|
|
|
|
adWFS.rangeSignificant = arr[i++];
|
|
|
|
|
adWFS.stVolRatio = arr[i++];
|
|
|
|
|
adWFS.atrMult = arr[i++];
|
|
|
|
|
adWSBI.lookback = (int)MathRound(arr[i++]);
|
|
|
|
|
adWSBI.rangeSignificant = arr[i++];
|
|
|
|
|
adWSBI.volumeHigh = arr[i++];
|
|
|
|
|
adWSBI.atr = arr[i++];
|
2026-07-22 22:51:04 -04:00
|
|
|
maPeriod = (int)MathRound(arr[i++]);
|
feat: add unified MA type support to indicator tuner
Add `MA_TYPE_PRESETS` enum covering advanced (ALMA, DEMA, ZLEMA, T3, Kalman) and standard (SMA, EMA, SMMA, LWMA) moving averages. Integrate `maType` and `bestMaType` into `CADIndicatorTuner` struct, update flatten/unflatten routines, and bump `AD_TUNE_PARAM_COUNT` to 33. This allows the auto-tuner to search over MA type alongside period, improving feature discovery.
2026-07-23 15:02:09 -04:00
|
|
|
maType = (int)MathRound(arr[i++]);
|
2026-07-22 22:51:04 -04:00
|
|
|
rsiPeriod = (int)MathRound(arr[i++]);
|
2026-07-26 18:33:12 -04:00
|
|
|
macdFast = (int)MathRound(arr[i++]);
|
|
|
|
|
macdSlow = (int)MathRound(arr[i++]);
|
|
|
|
|
macdSignal = (int)MathRound(arr[i++]);
|
|
|
|
|
ichiTenkan = (int)MathRound(arr[i++]);
|
|
|
|
|
ichiKijun = (int)MathRound(arr[i++]);
|
|
|
|
|
ichiSenkou = (int)MathRound(arr[i++]);
|
refactor(ExpertSignalAIBase): extract AutoTune param state into CADIndicatorTuner
CExpertSignalAIBase (4,326 lines, one class) carried 5 struct
definitions, 10 member fields, and 3 methods (Flatten/Unflatten/
PerturbRandom) purely for the AutoTuneIndicators search-space state -
entirely self-contained (never touches Net, Train()'s resumable state
machine, or anything else in the class). Extracted into a new
Expert/ADIndicatorTuner.mqh (CADIndicatorTuner), held as a single
m_indicatorTuner member.
TuneIndicatorsAndTrain() itself - the outer loop that actually
orchestrates Train()/Net/checkpointing around this tuner - turned out
to be exactly as tightly coupled to Train()'s resumable state machine
as Train() itself, so per the same caution already applied to Train()
in this refactor pass, it stays in CExpertSignalAIBase rather than
being pulled into the collaborator; it now calls the tuner's public
Flatten()/Unflatten()/PerturbRandom()/SaveAsBest()/RestoreBest()
instead of manipulating the structs inline.
All internal field-access renames (m_adCumDeltaParams.lookback ->
m_indicatorTuner.adCumDelta.lookback, etc., ~40 sites across the 5
InitAD*() indicator-setup methods) verified against a full grep sweep
- no leftover references to the old field/method names. Compiled
clean (MetaEditor, 0 errors/0 warnings).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:22:09 -04:00
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Randomly perturbs one tunable param of one randomly-chosen |
|
|
|
|
|
//| *enabled* AD indicator, within IndicatorTuneRanges.mqh bounds. |
|
|
|
|
|
//| No-op if no AD indicator is enabled. |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-07-26 18:33:12 -04:00
|
|
|
void CADIndicatorTuner::PerturbRandom(bool useCumDelta, bool useSOT, bool useWES, bool useWFS, bool useWSBI, bool useMA, bool useRSI, bool useMACD, bool useIchimoku)
|
refactor(ExpertSignalAIBase): extract AutoTune param state into CADIndicatorTuner
CExpertSignalAIBase (4,326 lines, one class) carried 5 struct
definitions, 10 member fields, and 3 methods (Flatten/Unflatten/
PerturbRandom) purely for the AutoTuneIndicators search-space state -
entirely self-contained (never touches Net, Train()'s resumable state
machine, or anything else in the class). Extracted into a new
Expert/ADIndicatorTuner.mqh (CADIndicatorTuner), held as a single
m_indicatorTuner member.
TuneIndicatorsAndTrain() itself - the outer loop that actually
orchestrates Train()/Net/checkpointing around this tuner - turned out
to be exactly as tightly coupled to Train()'s resumable state machine
as Train() itself, so per the same caution already applied to Train()
in this refactor pass, it stays in CExpertSignalAIBase rather than
being pulled into the collaborator; it now calls the tuner's public
Flatten()/Unflatten()/PerturbRandom()/SaveAsBest()/RestoreBest()
instead of manipulating the structs inline.
All internal field-access renames (m_adCumDeltaParams.lookback ->
m_indicatorTuner.adCumDelta.lookback, etc., ~40 sites across the 5
InitAD*() indicator-setup methods) verified against a full grep sweep
- no leftover references to the old field/method names. Compiled
clean (MetaEditor, 0 errors/0 warnings).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:22:09 -04:00
|
|
|
{
|
2026-07-26 18:33:12 -04:00
|
|
|
int enabled[9], n = 0;
|
refactor(ExpertSignalAIBase): extract AutoTune param state into CADIndicatorTuner
CExpertSignalAIBase (4,326 lines, one class) carried 5 struct
definitions, 10 member fields, and 3 methods (Flatten/Unflatten/
PerturbRandom) purely for the AutoTuneIndicators search-space state -
entirely self-contained (never touches Net, Train()'s resumable state
machine, or anything else in the class). Extracted into a new
Expert/ADIndicatorTuner.mqh (CADIndicatorTuner), held as a single
m_indicatorTuner member.
TuneIndicatorsAndTrain() itself - the outer loop that actually
orchestrates Train()/Net/checkpointing around this tuner - turned out
to be exactly as tightly coupled to Train()'s resumable state machine
as Train() itself, so per the same caution already applied to Train()
in this refactor pass, it stays in CExpertSignalAIBase rather than
being pulled into the collaborator; it now calls the tuner's public
Flatten()/Unflatten()/PerturbRandom()/SaveAsBest()/RestoreBest()
instead of manipulating the structs inline.
All internal field-access renames (m_adCumDeltaParams.lookback ->
m_indicatorTuner.adCumDelta.lookback, etc., ~40 sites across the 5
InitAD*() indicator-setup methods) verified against a full grep sweep
- no leftover references to the old field/method names. Compiled
clean (MetaEditor, 0 errors/0 warnings).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:22:09 -04:00
|
|
|
if(useCumDelta)
|
|
|
|
|
enabled[n++] = 0;
|
|
|
|
|
if(useSOT)
|
|
|
|
|
enabled[n++] = 1;
|
|
|
|
|
if(useWES)
|
|
|
|
|
enabled[n++] = 2;
|
|
|
|
|
if(useWFS)
|
|
|
|
|
enabled[n++] = 3;
|
|
|
|
|
if(useWSBI)
|
|
|
|
|
enabled[n++] = 4;
|
2026-07-22 22:51:04 -04:00
|
|
|
if(useMA)
|
|
|
|
|
enabled[n++] = 5;
|
|
|
|
|
if(useRSI)
|
|
|
|
|
enabled[n++] = 6;
|
2026-07-26 18:33:12 -04:00
|
|
|
if(useMACD)
|
|
|
|
|
enabled[n++] = 7;
|
|
|
|
|
if(useIchimoku)
|
|
|
|
|
enabled[n++] = 8;
|
refactor(ExpertSignalAIBase): extract AutoTune param state into CADIndicatorTuner
CExpertSignalAIBase (4,326 lines, one class) carried 5 struct
definitions, 10 member fields, and 3 methods (Flatten/Unflatten/
PerturbRandom) purely for the AutoTuneIndicators search-space state -
entirely self-contained (never touches Net, Train()'s resumable state
machine, or anything else in the class). Extracted into a new
Expert/ADIndicatorTuner.mqh (CADIndicatorTuner), held as a single
m_indicatorTuner member.
TuneIndicatorsAndTrain() itself - the outer loop that actually
orchestrates Train()/Net/checkpointing around this tuner - turned out
to be exactly as tightly coupled to Train()'s resumable state machine
as Train() itself, so per the same caution already applied to Train()
in this refactor pass, it stays in CExpertSignalAIBase rather than
being pulled into the collaborator; it now calls the tuner's public
Flatten()/Unflatten()/PerturbRandom()/SaveAsBest()/RestoreBest()
instead of manipulating the structs inline.
All internal field-access renames (m_adCumDeltaParams.lookback ->
m_indicatorTuner.adCumDelta.lookback, etc., ~40 sites across the 5
InitAD*() indicator-setup methods) verified against a full grep sweep
- no leftover references to the old field/method names. Compiled
clean (MetaEditor, 0 errors/0 warnings).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:22:09 -04:00
|
|
|
if(n == 0)
|
|
|
|
|
return;
|
|
|
|
|
switch(enabled[MathRand() % n])
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
{
|
|
|
|
|
switch(MathRand() % 7)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
adCumDelta.lookback = ADCUMDELTA_LOOKBACK_MIN + MathRand() % (ADCUMDELTA_LOOKBACK_MAX - ADCUMDELTA_LOOKBACK_MIN + 1);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
adCumDelta.volClimax = ADCUMDELTA_VOLCLIMAX_MIN + (MathRand() / 32767.0) * (ADCUMDELTA_VOLCLIMAX_MAX - ADCUMDELTA_VOLCLIMAX_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
adCumDelta.volHigh = ADCUMDELTA_VOLHIGH_MIN + (MathRand() / 32767.0) * (ADCUMDELTA_VOLHIGH_MAX - ADCUMDELTA_VOLHIGH_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
adCumDelta.rangeClimax = ADCUMDELTA_RANGECLIMAX_MIN + (MathRand() / 32767.0) * (ADCUMDELTA_RANGECLIMAX_MAX - ADCUMDELTA_RANGECLIMAX_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
adCumDelta.rangeSignificant = ADCUMDELTA_RANGESIGNIF_MIN + (MathRand() / 32767.0) * (ADCUMDELTA_RANGESIGNIF_MAX - ADCUMDELTA_RANGESIGNIF_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
adCumDelta.stVolRatio = ADCUMDELTA_STVOLRATIO_MIN + (MathRand() / 32767.0) * (ADCUMDELTA_STVOLRATIO_MAX - ADCUMDELTA_STVOLRATIO_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 6:
|
|
|
|
|
adCumDelta.atrMult = ADCUMDELTA_ATRMULT_MIN + (MathRand() / 32767.0) * (ADCUMDELTA_ATRMULT_MAX - ADCUMDELTA_ATRMULT_MIN);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 1:
|
|
|
|
|
{
|
|
|
|
|
switch(MathRand() % 3)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
adSOT.thrustLookback = ADSOT_LOOKBACK_MIN + MathRand() % (ADSOT_LOOKBACK_MAX - ADSOT_LOOKBACK_MIN + 1);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
adSOT.minImpulses = ADSOT_MININPULSES_MIN + MathRand() % (ADSOT_MININPULSES_MAX - ADSOT_MININPULSES_MIN + 1);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
adSOT.sotThreshold = ADSOT_THRESHOLD_MIN + (MathRand() / 32767.0) * (ADSOT_THRESHOLD_MAX - ADSOT_THRESHOLD_MIN);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 2:
|
|
|
|
|
{
|
|
|
|
|
switch(MathRand() % 8)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
adWES.lookback = ADWES_LOOKBACK_MIN + MathRand() % (ADWES_LOOKBACK_MAX - ADWES_LOOKBACK_MIN + 1);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
adWES.zigzag = ADWES_ZIGZAG_MIN + MathRand() % (ADWES_ZIGZAG_MAX - ADWES_ZIGZAG_MIN + 1);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
adWES.volClimax = ADWES_VOLCLIMAX_MIN + (MathRand() / 32767.0) * (ADWES_VOLCLIMAX_MAX - ADWES_VOLCLIMAX_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
adWES.volHigh = ADWES_VOLHIGH_MIN + (MathRand() / 32767.0) * (ADWES_VOLHIGH_MAX - ADWES_VOLHIGH_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
adWES.rangeClimax = ADWES_RANGECLIMAX_MIN + (MathRand() / 32767.0) * (ADWES_RANGECLIMAX_MAX - ADWES_RANGECLIMAX_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
adWES.rangeSignificant = ADWES_RANGESIGNIF_MIN + (MathRand() / 32767.0) * (ADWES_RANGESIGNIF_MAX - ADWES_RANGESIGNIF_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 6:
|
|
|
|
|
adWES.stVolRatio = ADWES_STVOLRATIO_MIN + (MathRand() / 32767.0) * (ADWES_STVOLRATIO_MAX - ADWES_STVOLRATIO_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 7:
|
|
|
|
|
adWES.atr = ADWES_ATR_MIN + (MathRand() / 32767.0) * (ADWES_ATR_MAX - ADWES_ATR_MIN);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 3:
|
|
|
|
|
{
|
|
|
|
|
switch(MathRand() % 8)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
adWFS.lookback = ADWFS_LOOKBACK_MIN + MathRand() % (ADWFS_LOOKBACK_MAX - ADWFS_LOOKBACK_MIN + 1);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
adWFS.zigzagStrength = ADWFS_ZIGZAGSTRENGTH_MIN + MathRand() % (ADWFS_ZIGZAGSTRENGTH_MAX - ADWFS_ZIGZAGSTRENGTH_MIN + 1);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
adWFS.volClimax = ADWFS_VOLCLIMAX_MIN + (MathRand() / 32767.0) * (ADWFS_VOLCLIMAX_MAX - ADWFS_VOLCLIMAX_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
adWFS.volHigh = ADWFS_VOLHIGH_MIN + (MathRand() / 32767.0) * (ADWFS_VOLHIGH_MAX - ADWFS_VOLHIGH_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
adWFS.rangeClimax = ADWFS_RANGECLIMAX_MIN + (MathRand() / 32767.0) * (ADWFS_RANGECLIMAX_MAX - ADWFS_RANGECLIMAX_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
adWFS.rangeSignificant = ADWFS_RANGESIGNIF_MIN + (MathRand() / 32767.0) * (ADWFS_RANGESIGNIF_MAX - ADWFS_RANGESIGNIF_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 6:
|
|
|
|
|
adWFS.stVolRatio = ADWFS_STVOLRATIO_MIN + (MathRand() / 32767.0) * (ADWFS_STVOLRATIO_MAX - ADWFS_STVOLRATIO_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 7:
|
|
|
|
|
adWFS.atrMult = ADWFS_ATRMULT_MIN + (MathRand() / 32767.0) * (ADWFS_ATRMULT_MAX - ADWFS_ATRMULT_MIN);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 4:
|
|
|
|
|
{
|
|
|
|
|
switch(MathRand() % 4)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
adWSBI.lookback = ADWSBI_LOOKBACK_MIN + MathRand() % (ADWSBI_LOOKBACK_MAX - ADWSBI_LOOKBACK_MIN + 1);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
adWSBI.rangeSignificant = ADWSBI_RANGESIGNIF_MIN + (MathRand() / 32767.0) * (ADWSBI_RANGESIGNIF_MAX - ADWSBI_RANGESIGNIF_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
adWSBI.volumeHigh = ADWSBI_VOLHIGH_MIN + (MathRand() / 32767.0) * (ADWSBI_VOLHIGH_MAX - ADWSBI_VOLHIGH_MIN);
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
adWSBI.atr = ADWSBI_ATR_MIN + (MathRand() / 32767.0) * (ADWSBI_ATR_MAX - ADWSBI_ATR_MIN);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-07-22 22:51:04 -04:00
|
|
|
case 5:
|
|
|
|
|
{
|
feat: add unified MA type support to indicator tuner
Add `MA_TYPE_PRESETS` enum covering advanced (ALMA, DEMA, ZLEMA, T3, Kalman) and standard (SMA, EMA, SMMA, LWMA) moving averages. Integrate `maType` and `bestMaType` into `CADIndicatorTuner` struct, update flatten/unflatten routines, and bump `AD_TUNE_PARAM_COUNT` to 33. This allows the auto-tuner to search over MA type alongside period, improving feature discovery.
2026-07-23 15:02:09 -04:00
|
|
|
//--- the MA feature has TWO tunables now (period + type); pick one at random to perturb
|
|
|
|
|
if(MathRand() % 2 == 0)
|
|
|
|
|
{
|
|
|
|
|
//--- snapped to MA_PERIOD_PRESETS (InputEnums.mqh) so a search never lands on a non-standard period
|
|
|
|
|
int maChoices[] = {MA_PERIOD_5, MA_PERIOD_8, MA_PERIOD_9, MA_PERIOD_10, MA_PERIOD_13, MA_PERIOD_20, MA_PERIOD_21, MA_PERIOD_50, MA_PERIOD_100, MA_PERIOD_200};
|
|
|
|
|
maPeriod = maChoices[MathRand() % ArraySize(maChoices)];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//--- unified MA type 0..8 (MA_TYPE_PRESETS): SMA/EMA/SMMA/LWMA/ALMA/DEMA/ZLEMA/T3/Kalman
|
|
|
|
|
int maTypeChoices[] = {MA_TYPE_SMA, MA_TYPE_EMA, MA_TYPE_SMMA, MA_TYPE_LWMA, MA_TYPE_ALMA, MA_TYPE_DEMA, MA_TYPE_ZLEMA, MA_TYPE_T3, MA_TYPE_KALMAN};
|
|
|
|
|
maType = maTypeChoices[MathRand() % ArraySize(maTypeChoices)];
|
|
|
|
|
}
|
2026-07-22 22:51:04 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 6:
|
|
|
|
|
{
|
|
|
|
|
//--- snapped to RSI_PERIOD_PRESETS (InputEnums.mqh)
|
|
|
|
|
int rsiChoices[] = {RSI_PERIOD_2, RSI_PERIOD_5, RSI_PERIOD_7, RSI_PERIOD_9, RSI_PERIOD_14, RSI_PERIOD_21, RSI_PERIOD_25};
|
|
|
|
|
rsiPeriod = rsiChoices[MathRand() % ArraySize(rsiChoices)];
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-07-26 18:33:12 -04:00
|
|
|
case 7:
|
|
|
|
|
{
|
|
|
|
|
//--- the MACD feature has THREE tunables (fast/slow/signal); pick one at random. No cross-check
|
|
|
|
|
//--- against the others is needed - the MACD_*_PRESETS sets never overlap, so any fast is always
|
|
|
|
|
//--- below any slow (see InputEnums.mqh).
|
|
|
|
|
switch(MathRand() % 3)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
{
|
|
|
|
|
int fastChoices[] = {MACD_FAST_5, MACD_FAST_8, MACD_FAST_12, MACD_FAST_15};
|
|
|
|
|
macdFast = fastChoices[MathRand() % ArraySize(fastChoices)];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 1:
|
|
|
|
|
{
|
|
|
|
|
int slowChoices[] = {MACD_SLOW_17, MACD_SLOW_21, MACD_SLOW_26, MACD_SLOW_34, MACD_SLOW_50};
|
|
|
|
|
macdSlow = slowChoices[MathRand() % ArraySize(slowChoices)];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 2:
|
|
|
|
|
{
|
|
|
|
|
int signalChoices[] = {MACD_SIGNAL_5, MACD_SIGNAL_7, MACD_SIGNAL_9, MACD_SIGNAL_12};
|
|
|
|
|
macdSignal = signalChoices[MathRand() % ArraySize(signalChoices)];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 8:
|
|
|
|
|
{
|
|
|
|
|
//--- the Ichimoku feature has THREE tunables (Tenkan/Kijun/Senkou B); pick one at random. Same
|
|
|
|
|
//--- non-overlapping-presets guarantee as MACD above keeps Tenkan < Kijun < Senkou B holding
|
|
|
|
|
//--- whichever single one this trial moves.
|
|
|
|
|
switch(MathRand() % 3)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
{
|
|
|
|
|
int tenkanChoices[] = {ICHI_TENKAN_7, ICHI_TENKAN_9, ICHI_TENKAN_12, ICHI_TENKAN_20};
|
|
|
|
|
ichiTenkan = tenkanChoices[MathRand() % ArraySize(tenkanChoices)];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 1:
|
|
|
|
|
{
|
|
|
|
|
int kijunChoices[] = {ICHI_KIJUN_22, ICHI_KIJUN_26, ICHI_KIJUN_30, ICHI_KIJUN_40};
|
|
|
|
|
ichiKijun = kijunChoices[MathRand() % ArraySize(kijunChoices)];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 2:
|
|
|
|
|
{
|
|
|
|
|
int senkouChoices[] = {ICHI_SENKOU_44, ICHI_SENKOU_52, ICHI_SENKOU_60, ICHI_SENKOU_120};
|
|
|
|
|
ichiSenkou = senkouChoices[MathRand() % ArraySize(senkouChoices)];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
refactor(ExpertSignalAIBase): extract AutoTune param state into CADIndicatorTuner
CExpertSignalAIBase (4,326 lines, one class) carried 5 struct
definitions, 10 member fields, and 3 methods (Flatten/Unflatten/
PerturbRandom) purely for the AutoTuneIndicators search-space state -
entirely self-contained (never touches Net, Train()'s resumable state
machine, or anything else in the class). Extracted into a new
Expert/ADIndicatorTuner.mqh (CADIndicatorTuner), held as a single
m_indicatorTuner member.
TuneIndicatorsAndTrain() itself - the outer loop that actually
orchestrates Train()/Net/checkpointing around this tuner - turned out
to be exactly as tightly coupled to Train()'s resumable state machine
as Train() itself, so per the same caution already applied to Train()
in this refactor pass, it stays in CExpertSignalAIBase rather than
being pulled into the collaborator; it now calls the tuner's public
Flatten()/Unflatten()/PerturbRandom()/SaveAsBest()/RestoreBest()
instead of manipulating the structs inline.
All internal field-access renames (m_adCumDeltaParams.lookback ->
m_indicatorTuner.adCumDelta.lookback, etc., ~40 sites across the 5
InitAD*() indicator-setup methods) verified against a full grep sweep
- no leftover references to the old field/method names. Compiled
clean (MetaEditor, 0 errors/0 warnings).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:22:09 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CADIndicatorTuner::SaveAsBest(void)
|
|
|
|
|
{
|
|
|
|
|
bestAdCumDelta = adCumDelta;
|
|
|
|
|
bestAdSOT = adSOT;
|
|
|
|
|
bestAdWES = adWES;
|
|
|
|
|
bestAdWFS = adWFS;
|
|
|
|
|
bestAdWSBI = adWSBI;
|
2026-07-22 22:51:04 -04:00
|
|
|
bestMaPeriod = maPeriod;
|
feat: add unified MA type support to indicator tuner
Add `MA_TYPE_PRESETS` enum covering advanced (ALMA, DEMA, ZLEMA, T3, Kalman) and standard (SMA, EMA, SMMA, LWMA) moving averages. Integrate `maType` and `bestMaType` into `CADIndicatorTuner` struct, update flatten/unflatten routines, and bump `AD_TUNE_PARAM_COUNT` to 33. This allows the auto-tuner to search over MA type alongside period, improving feature discovery.
2026-07-23 15:02:09 -04:00
|
|
|
bestMaType = maType;
|
2026-07-22 22:51:04 -04:00
|
|
|
bestRsiPeriod = rsiPeriod;
|
2026-07-26 18:33:12 -04:00
|
|
|
bestMacdFast = macdFast;
|
|
|
|
|
bestMacdSlow = macdSlow;
|
|
|
|
|
bestMacdSignal = macdSignal;
|
|
|
|
|
bestIchiTenkan = ichiTenkan;
|
|
|
|
|
bestIchiKijun = ichiKijun;
|
|
|
|
|
bestIchiSenkou = ichiSenkou;
|
refactor(ExpertSignalAIBase): extract AutoTune param state into CADIndicatorTuner
CExpertSignalAIBase (4,326 lines, one class) carried 5 struct
definitions, 10 member fields, and 3 methods (Flatten/Unflatten/
PerturbRandom) purely for the AutoTuneIndicators search-space state -
entirely self-contained (never touches Net, Train()'s resumable state
machine, or anything else in the class). Extracted into a new
Expert/ADIndicatorTuner.mqh (CADIndicatorTuner), held as a single
m_indicatorTuner member.
TuneIndicatorsAndTrain() itself - the outer loop that actually
orchestrates Train()/Net/checkpointing around this tuner - turned out
to be exactly as tightly coupled to Train()'s resumable state machine
as Train() itself, so per the same caution already applied to Train()
in this refactor pass, it stays in CExpertSignalAIBase rather than
being pulled into the collaborator; it now calls the tuner's public
Flatten()/Unflatten()/PerturbRandom()/SaveAsBest()/RestoreBest()
instead of manipulating the structs inline.
All internal field-access renames (m_adCumDeltaParams.lookback ->
m_indicatorTuner.adCumDelta.lookback, etc., ~40 sites across the 5
InitAD*() indicator-setup methods) verified against a full grep sweep
- no leftover references to the old field/method names. Compiled
clean (MetaEditor, 0 errors/0 warnings).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:22:09 -04:00
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CADIndicatorTuner::RestoreBest(void)
|
|
|
|
|
{
|
|
|
|
|
adCumDelta = bestAdCumDelta;
|
|
|
|
|
adSOT = bestAdSOT;
|
|
|
|
|
adWES = bestAdWES;
|
|
|
|
|
adWFS = bestAdWFS;
|
|
|
|
|
adWSBI = bestAdWSBI;
|
2026-07-22 22:51:04 -04:00
|
|
|
maPeriod = bestMaPeriod;
|
feat: add unified MA type support to indicator tuner
Add `MA_TYPE_PRESETS` enum covering advanced (ALMA, DEMA, ZLEMA, T3, Kalman) and standard (SMA, EMA, SMMA, LWMA) moving averages. Integrate `maType` and `bestMaType` into `CADIndicatorTuner` struct, update flatten/unflatten routines, and bump `AD_TUNE_PARAM_COUNT` to 33. This allows the auto-tuner to search over MA type alongside period, improving feature discovery.
2026-07-23 15:02:09 -04:00
|
|
|
maType = bestMaType;
|
2026-07-22 22:51:04 -04:00
|
|
|
rsiPeriod = bestRsiPeriod;
|
2026-07-26 18:33:12 -04:00
|
|
|
macdFast = bestMacdFast;
|
|
|
|
|
macdSlow = bestMacdSlow;
|
|
|
|
|
macdSignal = bestMacdSignal;
|
|
|
|
|
ichiTenkan = bestIchiTenkan;
|
|
|
|
|
ichiKijun = bestIchiKijun;
|
|
|
|
|
ichiSenkou = bestIchiSenkou;
|
refactor(ExpertSignalAIBase): extract AutoTune param state into CADIndicatorTuner
CExpertSignalAIBase (4,326 lines, one class) carried 5 struct
definitions, 10 member fields, and 3 methods (Flatten/Unflatten/
PerturbRandom) purely for the AutoTuneIndicators search-space state -
entirely self-contained (never touches Net, Train()'s resumable state
machine, or anything else in the class). Extracted into a new
Expert/ADIndicatorTuner.mqh (CADIndicatorTuner), held as a single
m_indicatorTuner member.
TuneIndicatorsAndTrain() itself - the outer loop that actually
orchestrates Train()/Net/checkpointing around this tuner - turned out
to be exactly as tightly coupled to Train()'s resumable state machine
as Train() itself, so per the same caution already applied to Train()
in this refactor pass, it stays in CExpertSignalAIBase rather than
being pulled into the collaborator; it now calls the tuner's public
Flatten()/Unflatten()/PerturbRandom()/SaveAsBest()/RestoreBest()
instead of manipulating the structs inline.
All internal field-access renames (m_adCumDeltaParams.lookback ->
m_indicatorTuner.adCumDelta.lookback, etc., ~40 sites across the 5
InitAD*() indicator-setup methods) verified against a full grep sweep
- no leftover references to the old field/method names. Compiled
clean (MetaEditor, 0 errors/0 warnings).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:22:09 -04:00
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|