The declustering the charts needed already existed - NmsLiveAccept, per-direction run-collapse plus cross-direction resolution plus strict alternation - and it was already set to 10 bars. It could not be TUNED: SignalClusterWindow was a compile- time const, so finding the right value needed a rebuild. That is the actual gap. Now three inputs, as enum dropdowns: Signal_CooldownScope per-direction, or a hard any-direction gate on top Signal_CooldownBars SCB_OFF..SCB_50, default 10 Signal_CooldownMinutes SCM_OFF..SCM_1440, overrides bars when set Minutes resolve against the CHART period and round UP, so a cooldown asked for in wall-clock is never silently shorter than requested and survives a timeframe change. SCB_/SCM_ prefixes are deliberately unique. M15/M30/M60 are ALREADY members of NF_LOOKBACK_PRESETS, and MQL5 binds a duplicated enum member to the first-declared enum silently - the obvious names would have compiled straight into the news filter's values. THE ANY-DIRECTION GATE IS ADDITIVE, NOT A REPLACEMENT, and the first cut of this had it backwards. Measured on the live log: the current rules draw 222 arrows over 4999 bars, while a BARE 10-bar cooldown permits up to 454 - because ALTERNATION is what declutters today, not the window. Swapping the rules out would have roughly doubled the clutter it was asked to remove. Layered, it can only ever suppress more. Suppressed bars still advance the per-direction last-SEEN cursors, so a run straddling the boundary does not restart as if it were fresh. Applied at all THREE sites that must agree - live inference, OOS pass-3 scoring and the chart renderer. Their own comments say why: an arrow set that does not obey the same rule as the traded set shows calls the EA would never take. Also corrects a stale comment that called this window "display only". It is not: when it suppresses, the live path zeroes the signal outright - no arrow, no vote, no position. Training never sees it, so these cost no retrain and are correctly absent from the fingerprint. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
575 行
28 KiB
MQL5
575 行
28 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| CustomEnums.mqh |
|
|
//| AnimateDread |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "AnimateDread"
|
|
#property link "https://www.mql5.com"
|
|
//--- Weight-update optimizer. This is really an AI\Network.mqh library type; a guarded duplicate is
|
|
//--- kept here so Variables\Inputs.mqh (which uses it for the TrainingOptimizer input) can be included
|
|
//--- before the AI headers - putting the EA's own inputs at the top of the Inputs tab. Keep in sync
|
|
//--- with AI\Network.mqh's copy; the shared WARRIOR_ENUM_OPTIMIZATION_DEFINED guard prevents a
|
|
//--- duplicate definition whichever header is parsed first.
|
|
#ifndef WARRIOR_ENUM_OPTIMIZATION_DEFINED
|
|
#define WARRIOR_ENUM_OPTIMIZATION_DEFINED
|
|
//--- A third DFA entry was removed 2026-07-28 - see AI\Network.mqh's copy for the full rationale (it was
|
|
//--- a deterministic index-parity sign flip on the gradient, i.e. ascent on half of every weight tensor,
|
|
//--- not Direct Feedback Alignment). SGD/ADAM keep ordinals 0/1: they feed the weights-filename
|
|
//--- fingerprint and must never be renumbered.
|
|
enum ENUM_OPTIMIZATION
|
|
{
|
|
SGD, // SGD + Momentum (heavy-ball, simpler, needs more eras)
|
|
ADAM // Adam (adaptive step, faster convergence, can overfit)
|
|
};
|
|
#endif
|
|
//--- Logical, commonly-used Moving Average / RSI periods only - keeps the Classic Signals inputs (and
|
|
//--- the AutoTuneIndicators search space over them, see ADIndicatorTuner.mqh) from being set/perturbed
|
|
//--- to an arbitrary, non-standard period.
|
|
enum MA_PERIOD_PRESETS
|
|
{
|
|
MA_PERIOD_5 = 5, // 5
|
|
MA_PERIOD_8 = 8, // 8
|
|
MA_PERIOD_9 = 9, // 9
|
|
MA_PERIOD_10 = 10, // 10
|
|
MA_PERIOD_13 = 13, // 13
|
|
MA_PERIOD_20 = 20, // 20
|
|
MA_PERIOD_21 = 21, // 21
|
|
MA_PERIOD_50 = 50, // 50
|
|
MA_PERIOD_100 = 100, // 100
|
|
MA_PERIOD_200 = 200, // 200
|
|
};
|
|
//--- Moving-average TYPE. VALUES ARE ENUM_MA_METHOD's own codes and MUST stay in sync with it - both the
|
|
//--- classic MA vote (Signals\SignalMA.mqh) and the NN MA input feature now run the BUILT-IN iMA via
|
|
//--- CiMA, so a value here is passed straight through as the ma_method argument. Auto-tuner-searchable.
|
|
//---
|
|
//--- 2026-08-19: replaced CustomIndicators\ADMovingAverage. That indicator offered five extra types
|
|
//--- (ALMA/DEMA/ZLEMA/T3/Kalman) on codes 0..4 with SMA/EMA/SMMA/LWMA on 5..8; those five have no iMA
|
|
//--- equivalent and are GONE, and the four survivors renumbered to match ENUM_MA_METHOD. Anything that
|
|
//--- persists a type code across that boundary must migrate - see LoadTunedPeriods().
|
|
enum MA_TYPE_PRESETS
|
|
{
|
|
MA_TYPE_SMA = MODE_SMA, // SMA (simple)
|
|
MA_TYPE_EMA = MODE_EMA, // EMA (exponential)
|
|
MA_TYPE_SMMA = MODE_SMMA, // SMMA (smoothed)
|
|
MA_TYPE_LWMA = MODE_LWMA, // LWMA (linear weighted)
|
|
};
|
|
//--- The ONE validity rule for a persisted MA type code. iMA rejects anything outside ENUM_MA_METHOD,
|
|
//--- and a stored code can predate the ADMovingAverage removal, so every load path runs it through
|
|
//--- here. Old codes 5..8 were SMA/EMA/SMMA/LWMA and map cleanly; old 0..4 were the five advanced
|
|
//--- types that no longer exist and are indistinguishable from valid new codes, so they cannot be
|
|
//--- rescued - callers that know they are reading a pre-migration file pass legacy=true to convert.
|
|
int SanitizeMaType(const int stored, const bool legacy)
|
|
{
|
|
if(legacy)
|
|
return (stored >= 5 && stored <= 8) ? stored - 5 : (int)MA_TYPE_SMA;
|
|
return (stored >= MODE_SMA && stored <= MODE_LWMA) ? stored : (int)MA_TYPE_SMA;
|
|
}
|
|
enum RSI_PERIOD_PRESETS
|
|
{
|
|
RSI_PERIOD_2 = 2, // 2
|
|
RSI_PERIOD_5 = 5, // 5
|
|
RSI_PERIOD_7 = 7, // 7
|
|
RSI_PERIOD_9 = 9, // 9
|
|
RSI_PERIOD_14 = 14, // 14 (classic)
|
|
RSI_PERIOD_21 = 21, // 21
|
|
RSI_PERIOD_25 = 25, // 25
|
|
};
|
|
//--- MACD periods (Signals\SignalMACD.mqh classic vote + the MACD input feature). The preset SETS are
|
|
//--- deliberately chosen so that EVERY fast/slow combination satisfies CSignalMACD::ValidationSettings()'s
|
|
//--- "slow must exceed fast" rule - the fast list tops out at 15, the slow list starts at 17. A trader
|
|
//--- picking two legal-looking values from the dropdowns can therefore never produce a combination that
|
|
//--- fails init, and the auto-tuner (ADIndicatorTuner::PerturbRandom) can perturb either one in isolation
|
|
//--- without having to know the other's current value.
|
|
enum MACD_FAST_PRESETS
|
|
{
|
|
MACD_FAST_5 = 5, // 5
|
|
MACD_FAST_8 = 8, // 8
|
|
MACD_FAST_12 = 12, // 12 (classic)
|
|
MACD_FAST_15 = 15, // 15
|
|
};
|
|
enum MACD_SLOW_PRESETS
|
|
{
|
|
MACD_SLOW_17 = 17, // 17
|
|
MACD_SLOW_21 = 21, // 21
|
|
MACD_SLOW_26 = 26, // 26 (classic)
|
|
MACD_SLOW_34 = 34, // 34
|
|
MACD_SLOW_50 = 50, // 50
|
|
};
|
|
enum MACD_SIGNAL_PRESETS
|
|
{
|
|
MACD_SIGNAL_5 = 5, // 5
|
|
MACD_SIGNAL_7 = 7, // 7
|
|
MACD_SIGNAL_9 = 9, // 9 (classic)
|
|
MACD_SIGNAL_12 = 12, // 12
|
|
};
|
|
//--- Ichimoku periods (Signals\SignalIchimoku.mqh classic vote + the Ichimoku input feature). Same
|
|
//--- all-combinations-are-legal design as the MACD presets above, against
|
|
//--- CSignalIchimoku::ValidationSettings()'s "Tenkan < Kijun < Senkou B" rule: Tenkan tops out at 20,
|
|
//--- Kijun spans 22-40, Senkou B starts at 44. The classic 9/26/52 triple is in the middle of each.
|
|
enum ICHIMOKU_TENKAN_PRESETS
|
|
{
|
|
ICHI_TENKAN_7 = 7, // 7
|
|
ICHI_TENKAN_9 = 9, // 9 (classic)
|
|
ICHI_TENKAN_12 = 12, // 12
|
|
ICHI_TENKAN_20 = 20, // 20
|
|
};
|
|
enum ICHIMOKU_KIJUN_PRESETS
|
|
{
|
|
ICHI_KIJUN_22 = 22, // 22
|
|
ICHI_KIJUN_26 = 26, // 26 (classic)
|
|
ICHI_KIJUN_30 = 30, // 30
|
|
ICHI_KIJUN_40 = 40, // 40
|
|
};
|
|
enum ICHIMOKU_SENKOU_PRESETS
|
|
{
|
|
ICHI_SENKOU_44 = 44, // 44
|
|
ICHI_SENKOU_52 = 52, // 52 (classic)
|
|
ICHI_SENKOU_60 = 60, // 60
|
|
ICHI_SENKOU_120 = 120, // 120
|
|
};
|
|
//--- custom enumerations for certain settings, minimizes overfitting
|
|
enum IND_PERIODS_PRESETS
|
|
{
|
|
PERIOD_5 = 5, // 5 Periods
|
|
PERIOD_10 = 10, // 10 Periods
|
|
PERIOD_14 = 14, // 14 Periods (classic)
|
|
PERIOD_20 = 20, // 20 Periods
|
|
PERIOD_30 = 30, // 30 Periods
|
|
PERIOD_50 = 50, // 50 Periods
|
|
PERIOD_100 = 100, // 100 Periods
|
|
PERIOD_200 = 200, // 200 Periods
|
|
};
|
|
enum TRAINING_YEARS_PRESET
|
|
{
|
|
YEARS_1 = 1, // 1 year
|
|
YEARS_2 = 2, // 2 years
|
|
YEARS_5 = 5, // 5 years
|
|
YEARS_10 = 10, // 10 years
|
|
YEARS_20 = 20, // 20 years
|
|
};
|
|
//--- Stop-loss sizing mode. The ATR_* presets place the SL a fixed multiple of ATR FROM THE ENTRY
|
|
//--- PRICE.
|
|
//--- SL_INTELLIGENT (-1) WAS REMOVED 2026-08-25 with the rest of the confidence-scaled trade
|
|
//--- management: it multiplied the base ATR distance by (1 - 0.3 * confidence), i.e. it staked real
|
|
//--- risk on a number the project has measured as MISCALIBRATED (the model over-calls by roughly 10x
|
|
//--- against the label prior - see the calibration verdict). Nothing ever demonstrated that a
|
|
//--- high-confidence bar deserves a tighter stop; the confidence-vs-outcome buckets in
|
|
//--- Database\TradeJournalReport.mqh are still recorded, so the claim remains testable, but it does
|
|
//--- not get to move a stop until it is.
|
|
//--- SWING-ANCHORED STOPS WERE REMOVED 2026-07-31. Both the ATR presets ("N ATR beyond the swing") and
|
|
//--- SL_PREV_SWING ("exactly at the swing") keyed the stop to the recent swing high/low, which makes
|
|
//--- the risk on a trade a function of how far away the last swing happens to sit rather than of
|
|
//--- current volatility: a shallow pullback produced a stop tight enough to be taken out by noise on a
|
|
//--- setup that then ran to target. Anchoring to the entry makes risk exactly N*ATR by construction,
|
|
//--- which is also what kept the old minimum-reward:risk rejection satisfiable without depending on
|
|
//--- swing geometry. That filter is gone (2026-08-09); the coupling is still the right shape.
|
|
//--- SL_Mode and TP_Mode NO LONGER DEFINE THE TRAINING LABELS. That was true from the 2026-08-01
|
|
//--- triple-barrier relabel until the swing-pivot target replaced it: the label is now geometry-free
|
|
//--- (which way the next confirmed pivot lies), neither mode appears in BuildModelFingerprint() or
|
|
//--- ComputeDbConfigFingerprint(), and both are free for the tester GA to sweep without a retrain.
|
|
enum STOP_LOSS_MODE
|
|
{
|
|
SL_ATR_x1 = 1, // ATR * 1 from entry
|
|
SL_ATR_x2 = 2, // ATR * 2 from entry
|
|
SL_ATR_x3 = 3, // ATR * 3 from entry
|
|
};
|
|
//--- Take-profit sizing mode. The ATR_* presets set the TP a fixed multiple of ATR FROM THE ENTRY
|
|
//--- PRICE (no longer derived from the reward:risk ratio - that ratio was a pure
|
|
//--- rejection filter).
|
|
//--- TP_INTELLIGENT (-1) WAS REMOVED 2026-08-25 for the same reason as SL_INTELLIGENT above - it
|
|
//--- widened the target to 2.5R * (1 + confidence), so an over-confident model quietly set itself a
|
|
//--- target it then had to reach.
|
|
//--- TP_PREV_SWING REMOVED 2026-07-31 alongside the swing-anchored stops: targeting the opposite swing
|
|
//--- caps the reward at whatever structure happens to be overhead, which on a trending signal exits
|
|
//--- well before the move is done and, paired with a swing-anchored stop, made the realised
|
|
//--- reward:risk a property of the chart's geometry rather than of the setup.
|
|
enum TAKE_PROFIT_MODE
|
|
{
|
|
TP_ATR_x1 = 1, // ATR * 1 from entry
|
|
TP_ATR_x2 = 2, // ATR * 2 from entry
|
|
TP_ATR_x3 = 3, // ATR * 3 from entry
|
|
TP_ATR_x4 = 4, // ATR * 4 from entry
|
|
TP_ATR_x6 = 6, // ATR * 6 from entry
|
|
TP_ATR_x8 = 8, // ATR * 8 from entry
|
|
TP_ATR_x10 = 10, // ATR * 10 from entry
|
|
};
|
|
//--- RISK_REWARD_RATIO removed 2026-08-09 along with its only consumer, the Min_Risk_Reward_Ratio
|
|
//--- input. Deleted rather than left dangling: a live enum with no input behind it is exactly the shape
|
|
//--- of the 2026-07 incident where a saved .set kept feeding a deleted option's ordinal back in and
|
|
//--- trained ~250 eras on the wrong target (MT5 does not validate saved enum inputs). See
|
|
//--- Variables\Inputs.mqh for why the ratio itself had to go.
|
|
enum MONEY_RISK_PERCENT_PRESET
|
|
{
|
|
RISK_PCT_1 = 1, // 1
|
|
RISK_PCT_2 = 2, // 2
|
|
RISK_PCT_3 = 3, // 3
|
|
RISK_PCT_4 = 4, // 4
|
|
RISK_PCT_5 = 5, // 5
|
|
};
|
|
enum BARS_EXPIRATION
|
|
{
|
|
BARS_X1 = 1, // 1 Candle
|
|
BARS_X2 = 2, // 2 Candles
|
|
BARS_X3 = 3, // 3 Candles
|
|
BARS_X5 = 5, // 5 Candles
|
|
BARS_X10 = 10, // 10 Candles
|
|
BARS_X20 = 20, // 20 Candles
|
|
};
|
|
//--- Entry order placement. All ATR offsets are measured from the CURRENT price (bid/ask), NOT the
|
|
//--- swing - this is the deliberate change for stability. Sign picks the side, magnitude is the ATR
|
|
//--- multiple:
|
|
//--- MARKET - fill immediately at market.
|
|
//--- LIMIT_*xATR - pending LIMIT that many ATR on the favorable side of bid/ask (buy below /
|
|
//--- sell above): wait for a pullback into a better price.
|
|
//--- STOP_*xATR - pending STOP that many ATR on the breakout side of bid/ask (buy above /
|
|
//--- sell below): enter on continuation.
|
|
//--- ENTRY_PREV_SWING - pending order anchored at the recent swing (buy at the lookback swing low /
|
|
//--- sell at the swing high) - the one swing-anchored option kept as a choice.
|
|
//--- ENTRY_INTELLIGENT (-100) WAS REMOVED 2026-08-25 with the other confidence-scaled trade
|
|
//--- management. It priced the ENTRY off confidence (deep pullback when unsure, market fill when
|
|
//--- sure), which is the worst of the three places to spend an uncalibrated number: a limit that
|
|
//--- never fills is not a smaller loss, it is a missed trade, and the misses are selected by exactly
|
|
//--- the signal the model is least sure about - so the mode silently reshaped which setups the
|
|
//--- strategy ever traded, not just how they were sized.
|
|
//--- Non-MARKET results that clear the broker's stop-level distance become a pending order that
|
|
//--- auto-expires after Signal_Expiration bars; anything closer just fills at market
|
|
//--- (CExpertTrade::Buy/Sell handle the market-vs-limit-vs-stop routing off this price natively).
|
|
enum ENTRY_MULTIPLIER
|
|
{
|
|
MARKET = 0, // Market order
|
|
//ENTRY_PREV_SWING = -101, // Pending at previous swing low (buy) / swing high (sell)
|
|
LIMIT_3xATR = -3, // Limit 3x ATR from bid/ask
|
|
LIMIT_2xATR = -2, // Limit 2x ATR from bid/ask
|
|
LIMIT_1xATR = -1, // Limit 1x ATR from bid/ask
|
|
STOP_1xATR = 1, // Stop 1x ATR from bid/ask
|
|
STOP_2xATR = 2, // Stop 2x ATR from bid/ask
|
|
STOP_3xATR = 3, // Stop 3x ATR from bid/ask
|
|
};
|
|
//--- THE ORDINALS BELOW ARE PINNED, AND MUST STAY PINNED. TRAILING_STRATEGY_INTELLIGENT held value 1
|
|
//--- until it was removed 2026-08-25; MetaTrader does not validate an enum input read back from a
|
|
//--- saved .set or a tester optimization cache, so had the remaining members been left implicit they
|
|
//--- would each have shifted down by one and every stored "3" would have quietly become ATR_x2
|
|
//--- instead of ATR_x3. Explicit values keep every saved selection meaning what it meant, and leave
|
|
//--- 1 as a hole that ValidateTradeManagementInputs() in Warrior_EA.mq5 rejects by name.
|
|
enum TRAILING_STRATEGY
|
|
{
|
|
TRAILING_STRATEGY_NONE = 0, // No Trailing Stop Strategy
|
|
TRAILING_STRATEGY_ATR_x1 = 2, // ATR * 1 Trailing Strategy
|
|
TRAILING_STRATEGY_ATR_x2 = 3, // ATR * 2 Trailing Strategy
|
|
TRAILING_STRATEGY_ATR_x3 = 4, // ATR * 3 Trailing Strategy
|
|
};
|
|
//--- Same pinning rule as TRAILING_STRATEGY above: INTELLIGENT held value 1 (Kelly-criterion risk%
|
|
//--- scaling off AI/DB confidence) and was removed 2026-08-25, so FIXED_LOT keeps its 2 rather than
|
|
//--- inheriting the vacated 1 and turning every saved "fixed lot" chart into a risk-percent one.
|
|
enum MONEY_MANAGEMENT_STRATEGY
|
|
{
|
|
FIXED_RISK = 0, // Fixed risk Percent of Account
|
|
FIXED_LOT = 2, // Fixed lot size
|
|
};
|
|
|
|
enum CLOSE_HOUR_OF_DAY
|
|
{
|
|
CLOSE_HOUR_DISABLED = -1, // Disabled
|
|
CH_0 = 0, // 00Hxx
|
|
CH_1 = 1, // 1Hxx
|
|
CH_2 = 2, // 2Hxx
|
|
CH_3 = 3, // 3Hxx
|
|
CH_4 = 4, // 4Hxx
|
|
CH_5 = 5, // 5Hxx
|
|
CH_6 = 6, // 6Hxx
|
|
CH_7 = 7, // 7Hxx
|
|
CH_8 = 8, // 8Hxx
|
|
CH_9 = 9, // 9Hxx
|
|
CH_10 = 10, // 10Hxx
|
|
CH_11 = 11, // 11Hxx
|
|
CH_12 = 12, // 12Hxx
|
|
CH_13 = 13, // 13Hxx
|
|
CH_14 = 14, // 14Hxx
|
|
CH_15 = 15, // 15Hxx
|
|
CH_16 = 16, // 16Hxx
|
|
CH_17 = 17, // 17Hxx
|
|
CH_18 = 18, // 18Hxx
|
|
CH_19 = 19, // 19Hxx
|
|
CH_20 = 20, // 20Hxx
|
|
CH_21 = 21, // 21Hxx
|
|
CH_22 = 22, // 22Hxx
|
|
CH_23 = 23, // 23Hxx
|
|
//--- Resolves per day from the SYMBOL'S OWN trading-session table (SymbolInfoSessionTrade),
|
|
//--- so it follows the broker through DST and per-symbol schedules with nothing to retune:
|
|
//--- the close-all fires "Close-all minute" minutes BEFORE that day's last session close
|
|
//--- (e.g. minute = xxH05 -> 5 minutes before the close). The label walk resolves the same
|
|
//--- value (Expert\AIBase\Labels.mqh), so training and the live book share one definition of
|
|
//--- "the day ends". Explicit 24: impossible as a literal hour, appended (values are saved,
|
|
//--- never validated - members are only ever added at the end).
|
|
CH_MARKET_CLOSE = 24, // Market close (minus Close-all minute)
|
|
};
|
|
enum CLOSE_MINUTE_OF_HOUR
|
|
{
|
|
CLOSE_MINUTE_DISABLED = -1,// Disabled
|
|
CM_0 = 0, // xxH00
|
|
CM_5 = 5, // xxH05
|
|
CM_10 = 10, // xxH10
|
|
CM_15 = 15, // xxH15
|
|
CM_20 = 20, // xxH20
|
|
CM_25 = 25, // xxH25
|
|
CM_30 = 30, // xxH30
|
|
CM_35 = 35, // xxH35
|
|
CM_40 = 40, // xxH40
|
|
CM_45 = 45, // xxH45
|
|
CM_50 = 50, // xxH50
|
|
CM_55 = 55, // xxH55
|
|
CM_60 = 60, // xxH60
|
|
};
|
|
//--- WHAT A KEPT SIGNAL BLOCKS. Member names are deliberately long and unique: MQL5 resolves a name
|
|
//--- duplicated across two enums to the FIRST-DECLARED one, silently, and this project has already
|
|
//--- shipped a wrong target that way.
|
|
//--- Dropdown presets for the cooldown. Prefixes SCB_/SCM_ are deliberately unique: MQL5 resolves a
|
|
//--- duplicated enum member to the FIRST-DECLARED enum, silently - and M15/M30/M60 are ALREADY taken
|
|
//--- by NF_LOOKBACK_PRESETS below, so the obvious names would have bound to the news filter's values.
|
|
enum SIGNAL_COOLDOWN_BARS
|
|
{
|
|
SCB_OFF = 0, // Off (no cooldown)
|
|
SCB_2 = 2, // 2 bars
|
|
SCB_3 = 3, // 3 bars
|
|
SCB_5 = 5, // 5 bars
|
|
SCB_8 = 8, // 8 bars
|
|
SCB_10 = 10, // 10 bars
|
|
SCB_15 = 15, // 15 bars
|
|
SCB_20 = 20, // 20 bars
|
|
SCB_30 = 30, // 30 bars
|
|
SCB_50 = 50, // 50 bars
|
|
};
|
|
enum SIGNAL_COOLDOWN_MINUTES
|
|
{
|
|
SCM_OFF = 0, // Use the bar count instead
|
|
SCM_15 = 15, // 15 minutes
|
|
SCM_30 = 30, // 30 minutes
|
|
SCM_60 = 60, // 1 hour
|
|
SCM_120 = 120, // 2 hours
|
|
SCM_240 = 240, // 4 hours
|
|
SCM_480 = 480, // 8 hours
|
|
SCM_720 = 720, // 12 hours
|
|
SCM_1440 = 1440, // 1 day
|
|
};
|
|
enum SIGNAL_COOLDOWN_SCOPE
|
|
{
|
|
//--- A kept Buy silences nearby Buys only, plus cross-direction flicker resolution and strict
|
|
//--- Buy/Sell alternation. Thins RUNS but still permits a fresh alternating pair every window.
|
|
SIGNAL_COOLDOWN_PER_DIRECTION = 0, // Per direction (collapse runs + alternate)
|
|
//--- ADDS a hard any-direction cooldown ON TOP of the three rules above. Deliberately additive and
|
|
//--- not a replacement: measured on the live log, ALTERNATION is what declutters today (222 arrows
|
|
//--- over 4999 bars), while a BARE 10-bar cooldown permits up to 454 - so swapping the rules out
|
|
//--- would have roughly DOUBLED the clutter it was asked to remove. Layered, it can only ever
|
|
//--- suppress more, never less.
|
|
SIGNAL_COOLDOWN_ANY_SIGNAL = 1, // Any signal, on top of per-direction (fewest signals)
|
|
};
|
|
enum CLOSE_DAY_OF_WEEK
|
|
{
|
|
CLOSE_DAY_DISABLED = -1, // Disabled
|
|
CLOSE_MONDAY = 1, // Monday
|
|
CLOSE_TUESDAY = 2, // Tuesday
|
|
CLOSE_WEDNESDAY = 3, // Wednesday
|
|
CLOSE_THURSDAY = 4, // Thursday
|
|
CLOSE_FRIDAY = 5, // Friday
|
|
CLOSE_EVERYDAY, // Every Day
|
|
};
|
|
enum NF_LOOKBACK_PRESETS
|
|
{
|
|
NF_DISABLED = -1, // Disabled
|
|
M5 = 5, // 5 Minutes
|
|
M15 = 15, // 15 Minutes
|
|
M30 = 30, // 30 Minutes
|
|
M45 = 45, // 45 Minutes
|
|
M60 = 60, // 1 Hour
|
|
M120 = 120, // 2 Hours
|
|
M240 = 240, // 4 Hours
|
|
};
|
|
enum NF_IMPACT_PRESETS
|
|
{
|
|
HOLIDAYS = 0, //Holidays
|
|
LOW = 1, // Low Impact News
|
|
MEDIUM = 2, // Medium Impact News
|
|
HIGH = 3, // High Impact News
|
|
};
|
|
//--- INTELLIGENT added 2026-08-19 (user request, SQX EdgeFinder precedent: "adjust for the drift
|
|
//--- to increase success rate"). It resolves to LONG_ONLY / SHORT_ONLY / BOTH at runtime from the
|
|
//--- The Intelligent member (value 3, the measured drift verdict) went with the barrier stack
|
|
//--- 2026-08-24: its data source was the per-side win caches. A saved .set holding 3 falls outside
|
|
//--- the enum and MT5 clamps it, which is the visible failure a silent re-map would not be.
|
|
enum TRADING_DIRECTION
|
|
{
|
|
BOTH, // Allow both long and short trades
|
|
LONG_ONLY, // Allow only long (buy) trades
|
|
SHORT_ONLY, // Allow only short (sell) trades
|
|
};
|
|
|
|
//--- 5-POINT STEPS BELOW 50, 10-POINT ABOVE (2026-08-19). This is Signal_ThresholdOpen's scale, and under
|
|
//--- CONSENSUS arithmetic the votes it must separate are quantized by AGREEMENT: with four members
|
|
//--- whose tiers self-rank to pooled win rates ~29, unanimity reads ~29, 3-of-4 ~22, 2-of-4 ~14.5.
|
|
//--- The old 10-point grid straddled every rung the ensemble can express - 20 admitted 3-of-4 and
|
|
//--- 30 admitted nothing - so the thresholds an operator actually wants, which sit BETWEEN rungs,
|
|
//--- did not exist on the dropdown. Steps stay coarse above 50 because nothing reachable lives up
|
|
//--- there until pooled skill does. Members are ADDED, never removed or renumbered: MT5 saves the
|
|
//--- VALUE and does not validate it against the current enum (see the RISK_LIMIT_PCT_PRESET
|
|
//--- removal note at the bottom of this file), so adding explicit-valued members is .set-safe
|
|
//--- while deleting one is the trained-250-eras-on-the-wrong-target failure.
|
|
enum PERCENTAGE_PRESETS
|
|
{
|
|
PCT_5 = 5, // 5%
|
|
PCT_10 = 10, // 10%
|
|
PCT_15 = 15, // 15%
|
|
PCT_20 = 20, // 20%
|
|
PCT_25 = 25, // 25%
|
|
PCT_30 = 30, // 30%
|
|
PCT_35 = 35, // 35%
|
|
PCT_40 = 40, // 40%
|
|
PCT_45 = 45, // 45%
|
|
PCT_50 = 50, // 50%
|
|
PCT_60 = 60, // 60%
|
|
PCT_70 = 70, // 70%
|
|
PCT_80 = 80, // 80%
|
|
PCT_90 = 90, // 90%
|
|
PCT_100 = 100, // 100%
|
|
};
|
|
//--- SIGNAL_CLOSE_PRESETS WAS REMOVED 2026-08-26 with the Signal_ThresholdClose input it existed for.
|
|
//--- The vote exit is gone rather than disabled-by-default: a vote-driven early close trades a horizon
|
|
//--- the deploy gate never certified, and acting on a reversal is Allow_Hedging's job now (it opens
|
|
//--- the other book instead of closing this one). The disabling value survives as
|
|
//--- VOTE_EXIT_DISABLED_THRESHOLD in Variables\Inputs.mqh, which is what the signal is pinned to.
|
|
//--- Nothing else referenced the enum, so no ordinal moved - see the flat-namespace warning above,
|
|
//--- which is why the members were prefixed in the first place.
|
|
//--- FIRST_LAYER_NEURONS removed 2026-07-29. The first dense layer dominates the parameter count -
|
|
//--- it is (inputWidth+1) x width - so its only defensible value is a function of the input width and
|
|
//--- the amount of in-sample data, neither of which the user can see when picking from a dropdown. It
|
|
//--- is now derived: see CExpertSignalAIBase::ComputeFirstLayerWidth().
|
|
//--- Architecture-aware dense-topology presets were then folded into the (since-removed) AI_CHOICE
|
|
//--- selector; today the front-end choice is the per-NN Use_* toggles and the dense taper is fully
|
|
//--- derived - see ComputeHiddenLayerCount.
|
|
//--- LSTM's own recurrent hidden-unit count - previously silently piggybacked on HiddenLayersCount
|
|
//--- (an unrelated dense-taper-depth setting), which meant it could never be tuned independently and
|
|
//--- defaulted to a value (4) nobody actually chose on purpose. Decoupled into its own input.
|
|
enum LSTM_HIDDEN_SIZE_PRESET
|
|
{
|
|
LSTM_HIDDEN_8 = 8, // 8 Units
|
|
LSTM_HIDDEN_16 = 16, // 16 Units
|
|
LSTM_HIDDEN_32 = 32, // 32 Units
|
|
LSTM_HIDDEN_64 = 64, // 64 Units
|
|
LSTM_HIDDEN_128 = 128, // 128 Units
|
|
};
|
|
//--- CONV's own output-filter count for its convolutional layer - previously silently piggybacked on
|
|
//--- HiddenLayersCount too (same bug class as LstmHiddenSize above), defaulting to a bottleneck of 4
|
|
//--- filters/bar. Decoupled into its own input.
|
|
enum CONV_FILTER_COUNT_PRESET
|
|
{
|
|
CONV_FILTERS_8 = 8, // 8 Filters
|
|
CONV_FILTERS_16 = 16, // 16 Filters
|
|
CONV_FILTERS_32 = 32, // 32 Filters
|
|
CONV_FILTERS_64 = 64, // 64 Filters
|
|
CONV_FILTERS_128 = 128, // 128 Filters
|
|
};
|
|
//--- Shared pooling shape for the Conv front-end used by both CONV and HYBRID. Keeping this
|
|
//--- separate from ConvFilterCount lets the filter-bank width and the downsampling span be tuned
|
|
//--- independently, instead of smuggling one into the other.
|
|
//--- CONV_POOL_WINDOW_PRESET / CONV_POOL_STEP_PRESET removed 2026-07-29 along with the pooling
|
|
//--- stage itself - their "N Bars" labels described time-axis pooling the implementation could
|
|
//--- never perform. See AddConvStage() in Expert\ExpertSignalAIBase.mqh.
|
|
|
|
enum MIN_NEURONS_COUNT
|
|
{
|
|
MIN_NEURONS_10 = 10, // Min. 10 Neurons per layer
|
|
MIN_NEURONS_20 = 20, // Min. 20 Neurons per layer
|
|
MIN_NEURONS_30 = 30, // Min. 30 Neurons per layer
|
|
MIN_NEURONS_40 = 40, // Min. 40 Neurons per layer
|
|
MIN_NEURONS_50 = 50, // Min. 50 Neurons per layer
|
|
};
|
|
// Value IS the reduction percentage applied per hidden layer (retention = 100-value), consumed
|
|
// via BuildFreshTopology()'s n = n*((100-value)*0.01) taper - e.g. RF_70 keeps 30% of the previous
|
|
// layer's neurons, i.e. a genuine 70% reduction per layer, matching the label at face value.
|
|
enum NEURONS_REDUCTION_FACTOR
|
|
{
|
|
RF_10 = 10, // 10 % Neurons Reduction Per Layer
|
|
RF_20 = 20, // 20 % Neurons Reduction Per Layer
|
|
RF_30 = 30, // 30 % Neurons Reduction Per Layer
|
|
RF_40 = 40, // 40 % Neurons Reduction Per Layer
|
|
RF_50 = 50, // 50 % Neurons Reduction Per Layer
|
|
RF_60 = 60, // 60 % Neurons Reduction Per Layer
|
|
RF_70 = 70, // 70 % Neurons Reduction Per Layer
|
|
RF_80 = 80, // 80 % Neurons Reduction Per Layer
|
|
RF_90 = 90, // 90 % Neurons Reduction Per Layer
|
|
};
|
|
enum OUTPUT_NEURONS_COUNT
|
|
{
|
|
OUTPUT_REGRESSION = 1, // Regression Algorithm
|
|
OUTPUT_CLASSIFICATION = 3, // Classification Algorithm
|
|
};
|
|
//--- AI_CHOICE REMOVED 2026-08-19 (user request: "remove the enum menu that selects neural networks,
|
|
//--- add individual inputs for every NN just like classic signals"). The preset selector could only
|
|
//--- express solo-or-all (no 2-3 member subsets) and made the META head mutually exclusive with the
|
|
//--- direction NNs. Replaced by the per-NN bools in Variables\Inputs.mqh (Use_MLP/Use_CONV/Use_LSTM/
|
|
//--- Use_CONVLSTM); the ensemble machinery keys off "two or more direction NNs
|
|
//--- enabled" (ConfigureAISignal), which reproduces the old AI_HYBRID fingerprints exactly, and the
|
|
//--- pattern-DB filename keeps its first slot via DbLegacyAiSlot() (Warrior_EA.mq5) so no existing
|
|
//--- database re-keys. Deleted rather than left dangling, same doctrine as RISK_LIMIT_PCT_PRESET at
|
|
//--- the bottom of this file: a live enum with no input behind it is exactly the stale-.set trap
|
|
//--- shape. Stale "AIType=..." lines in saved .set files are ignored by name, harmlessly.
|
|
//--- (Historical: value 4 was renamed AI_CONVLSTM 2026-08-15; State\HYBRID\ folder names were kept
|
|
//--- across that rename and remain the CONVLSTM instance's identity - see CSignalHYBRID.)
|
|
//--- CONFIDENCE_SOURCE REMOVED 2026-08-25, along with the Confidence_Source input it backed and every
|
|
//--- consumer of it. It chose which number the confidence-scaled SL/TP/entry/trail/lot modes read -
|
|
//--- and with all five of those gone it had nothing left to steer. Two independent reasons it should
|
|
//--- not come back in this shape:
|
|
//--- * THE DB ARM COULD NOT SURVIVE A BACKTEST. CONF_DB / CONF_BLENDED read the signal database's
|
|
//--- pattern win rates, and the tester DB guard (SignalDatabaseActive(), 2026-08-25) leaves that
|
|
//--- database closed in tester and optimizer. A backtest would therefore have read 0 for a
|
|
//--- quantity that is non-zero live - the one failure mode a backtest must not have.
|
|
//--- * THE DB IS A WEIGHTING MECHANISM, NOT A CONFIDENCE ESTIMATE. What it produces is an average
|
|
//--- pattern win rate used to rank filters against each other; reading it as "probability this
|
|
//--- trade wins" was a category error that no measurement ever supported.
|
|
//--- Both confidence numbers are still RECORDED per trade (aiConfidence / dbConfidence in
|
|
//--- Database\TradeJournalManager.mqh, bucketed against outcome in TradeJournalReport.mqh). Recording
|
|
//--- is how the question stays answerable; acting on it was the part that had no evidence behind it.
|
|
// How many bars to wait, after a candidate ZigZag reversal bar, before trusting the real ZigZag
|
|
// indicator's verdict on it as a training label - see CExpertSignalAIBase's m_swingConfirmationBars
|
|
// declaration comment. A ZigZag's most recent 1-3 legs can still repaint as new bars arrive, so this
|
|
// must be generous enough to let a leg fully settle (bumped from the old fractal-based system's
|
|
// default of 20 to 100 for exactly that reason). A value of 0 is clamped up to a 1-bar minimum
|
|
// internally, never used to mean "no delay".
|
|
enum SWING_CONFIRMATION_PRESET
|
|
{
|
|
SC_10 = 10, // 10 Bars
|
|
SC_20 = 20, // 20 Bars
|
|
SC_30 = 30, // 30 Bars
|
|
SC_50 = 50, // 50 Bars
|
|
SC_100 = 100, // 100 Bars
|
|
SC_200 = 200, // 200 Bars
|
|
};
|
|
enum MAX_ERAS_PRESET
|
|
{
|
|
ME_100 = 100, // 100 Eras
|
|
ME_200 = 200, // 200 Eras
|
|
ME_300 = 300, // 300 Eras
|
|
ME_500 = 500, // 500 Eras
|
|
ME_1000 = 1000, // 1000 Eras
|
|
ME_2000 = 2000, // 2000 Eras
|
|
ME_3000 = 3000, // 3000 Eras
|
|
ME_5000 = 5000, // 5000 Eras
|
|
ME_10000 = 10000, // 10000 Eras
|
|
};
|
|
//--- percentage of the study period held back as out-of-sample data never trained on;
|
|
//--- value is the OOS share, in-sample share is the remainder (e.g. OOS_30 -> 70% IS / 30% OOS)
|
|
enum OOS_SPLIT_PRESET
|
|
{
|
|
OOS_10 = 10, // 90% IS / 10% OOS
|
|
OOS_20 = 20, // 80% IS / 20% OOS
|
|
OOS_30 = 30, // 70% IS / 30% OOS
|
|
OOS_40 = 40, // 60% IS / 40% OOS
|
|
OOS_50 = 50, // 50% IS / 50% OOS
|
|
};
|
|
//--- RISK_LIMIT_PCT_PRESET REMOVED 2026-08-02. It backed MaxDailyLossPct/MaxDrawdownPct as a dropdown
|
|
//--- of eight fixed percentages, which no funded-account programme is obliged to match - 4.5% or 3.75%
|
|
//--- were unreachable. Both inputs are now free-entry doubles (Variables\Inputs.mqh) validated at init.
|
|
//--- Note for anyone reinstating an enum input here: MT5 does NOT validate a saved enum value against
|
|
//--- the current enum, so a .set file holding a deleted member loads as a silent out-of-range int - the
|
|
//--- failure mode that trained four topologies on the wrong barrier (project memory: stale enum wrong
|
|
//--- target). Changing these two to doubles removes that exposure rather than renaming it.
|
|
//+------------------------------------------------------------------+
|