Vigiar
1
0
Derivar
Você já tinha feito uma derivação do repositório Warrior_EA, anteriormente
0
Warrior_EA/Variables/TunedPeriods.mqh

122 linhas
6,5 KiB
MQL5

//+------------------------------------------------------------------+
//| TunedPeriods.mqh |
//| AnimateDread |
//+------------------------------------------------------------------+
//| Chart-level tuned indicator periods - ONE source of truth for |
//| every consumer of "what period does this indicator run at". |
//| |
//| The 2026-08-16 menu pruning made ALL indicator parameters |
//| tuner-owned (see Inputs.mqh). That leaves two consumers that must |
//| agree: the AI features (whose per-model tuned values persist in |
//| the .nnw) and the classic votes + signal-DB key (chart-level, |
//| configured once at OnInit). This file is the bridge: a gated |
//| tuner INSTALL writes the winning periods here; the next attach |
//| reads them BEFORE the classic signals are configured and BEFORE |
//| the DB fingerprint is computed, so votes, DB key and tuner seeds |
//| all describe the same indicators. |
//| |
//| ADOPTION IS RESTART-GRAINED BY DESIGN: an install mid-run changes |
//| the AI features immediately (fresh topology) but classic votes |
//| and the DB key keep their init-time values until the next attach. |
//| Re-configuring framework signal indicators mid-run would need the |
//| ReInitADIndicators treatment (handle release, cache invalidation) |
//| for machinery that changes at most once per tuning install - |
//| restart-grained is simpler and cannot leak handles. |
//| |
//| The DB SEMANTICS consequence is intended: the DB fingerprint |
//| hashes these adopted values, so new periods = new database = the |
//| per-pattern win-rate history never blends rows from two different |
//| indicator definitions (the January-August 2026 blending trap). |
//+------------------------------------------------------------------+
#ifndef WARRIOR_TUNED_PERIODS_MQH
#define WARRIOR_TUNED_PERIODS_MQH
//--- Defaults are the seed constants; LoadTunedPeriods() overwrites from the chart's file if present.
int g_TunedMaPeriod = (int)PeriodMA;
int g_TunedMaType = (int)MA_Type;
int g_TunedRsiPeriod = (int)PeriodRSI;
int g_TunedMacdFast = (int)MACD_PeriodFast;
int g_TunedMacdSlow = (int)MACD_PeriodSlow;
int g_TunedMacdSignal = (int)MACD_PeriodSignal;
int g_TunedIchiTenkan = (int)Ichimoku_PeriodTenkan;
int g_TunedIchiKijun = (int)Ichimoku_PeriodKijun;
int g_TunedIchiSenkou = (int)Ichimoku_PeriodSenkou;
string TunedPeriodsFileName(void)
{
fix(altdata): robustness pass for arbitrary symbol/timeframe - validation + error handling Systematic audit of the alt-data stack against "any symbol, any timeframe", prompted by the H4 surprise. Findings, each fixed: CAPACITY: ALTDATA_MAX_FEATURES was 16 with FX symbols already at 15 - the next added column would have been silently truncated by a MathMin. Raised to 32, pin-chars 512 -> 1024. SYMBOL NAMES: the panel reload path re-derived symbol/timeframe by splitting the file path on its FIRST underscore - mis-parsing every symbol containing one (OANDA-style EUR_USD and US_500 are in our own alias lists) and knowing only three timeframes. It now stores the (symbol, period) Load() was called with and reuses them verbatim. Path-hostile characters in broker symbols ("EUR/USD") are sanitized by a shared AltDataFileSymbol() used by the panel, the fetcher and TunedPeriods, so a slash cannot route a write into an unintended subfolder. DOWNLOAD VALIDATION: every FRED-family fetch now enforces a per-series plausibility band (VIX 1-200, yields -5..30, CPI index 20-1000, ...) - StringToDouble on transport garbage returns 0.0, and one absurd value poisons every change/percentile feature computed across it (the BatchNorm NaN-latch incident came from exactly one huge-but-finite input). Rejected rows are counted and reported, never dropped silently. LOUD EMPTINESS: a successful response with zero observations on an empty cache now says so - naming the series (wrong id / format drift) or the COT predicate (the unverified like-clauses) instead of leaving 0-filled features unexplained. GEX gains a truncation guard: a day-over-day contract-count collapse >50% is the fingerprint of a partial 13 MB download, not of markets, and is skipped rather than recorded as a plausible-but-wrong number. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 17:59:10 -04:00
//--- broker symbols can carry path-hostile characters ("EUR/USD"); writing through
//--- them fails or lands in an unintended subfolder (same rule as AltDataFileSymbol)
string sym = _Symbol;
StringReplace(sym, "/", "-");
StringReplace(sym, "\\", "-");
StringReplace(sym, ":", "-");
StringReplace(sym, "*", "-");
StringReplace(sym, "?", "-");
StringReplace(sym, "\"", "-");
StringReplace(sym, "<", "-");
StringReplace(sym, ">", "-");
StringReplace(sym, "|", "-");
return "Warrior_EA\\TunedPeriods_" + sym + "_" +
StringSubstr(EnumToString((ENUM_TIMEFRAMES)_Period), 7) + ".cfg";
}
//+------------------------------------------------------------------+
//| Read the chart's adopted periods, if any. Call at the TOP of |
//| OnInit - before ComputeDbConfigFingerprint() and before the |
//| classic signals are configured. Missing file = seeds stand. |
//+------------------------------------------------------------------+
void LoadTunedPeriods(void)
{
string name = TunedPeriodsFileName();
if(!FileIsExist(name, FILE_COMMON))
return;
int h = FileOpen(name, FILE_READ | FILE_TXT | FILE_ANSI | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_COMMON);
if(h == INVALID_HANDLE)
return;
string line = FileReadString(h);
FileClose(h);
string f[];
if(StringSplit(line, ';', f) < 9)
{
Print("TunedPeriods: " + name + " is malformed ('" + line + "') - keeping the seed defaults.");
return;
}
g_TunedMaPeriod = (int)StringToInteger(f[0]);
g_TunedMaType = (int)StringToInteger(f[1]);
g_TunedRsiPeriod = (int)StringToInteger(f[2]);
g_TunedMacdFast = (int)StringToInteger(f[3]);
g_TunedMacdSlow = (int)StringToInteger(f[4]);
g_TunedMacdSignal = (int)StringToInteger(f[5]);
g_TunedIchiTenkan = (int)StringToInteger(f[6]);
g_TunedIchiKijun = (int)StringToInteger(f[7]);
g_TunedIchiSenkou = (int)StringToInteger(f[8]);
PrintFormat("TunedPeriods: adopted from %s - MA %d/type %d, RSI %d, MACD %d/%d/%d, Ichimoku %d/%d/%d "
"(classic votes, DB key and tuner seeds all use these).",
name, g_TunedMaPeriod, g_TunedMaType, g_TunedRsiPeriod,
g_TunedMacdFast, g_TunedMacdSlow, g_TunedMacdSignal,
g_TunedIchiTenkan, g_TunedIchiKijun, g_TunedIchiSenkou);
}
//+------------------------------------------------------------------+
//| Persist a gated tuner install's winning periods. Called from |
//| TuneIndicatorsByFilter on INSTALL only - never for a rejected |
//| winner, never per trial. Last install wins across ensemble |
//| members; the values take chart-wide effect on the next attach. |
//+------------------------------------------------------------------+
void SaveTunedPeriods(int maPeriod, int maType, int rsiPeriod,
int macdFast, int macdSlow, int macdSignal,
int ichiTenkan, int ichiKijun, int ichiSenkou)
{
string name = TunedPeriodsFileName();
int h = FileOpen(name, FILE_WRITE | FILE_TXT | FILE_ANSI | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_COMMON);
if(h == INVALID_HANDLE)
{
PrintFormat("TunedPeriods: cannot write %s (%d) - install still applies to this model's "
"features; classic votes keep their current periods.", name, GetLastError());
return;
}
FileWriteString(h, StringFormat("%d;%d;%d;%d;%d;%d;%d;%d;%d\n",
maPeriod, maType, rsiPeriod, macdFast, macdSlow, macdSignal,
ichiTenkan, ichiKijun, ichiSenkou));
FileClose(h);
PrintFormat("TunedPeriods: install persisted to %s - classic votes and the signal-DB key adopt "
"these on the next attach (restart-grained by design).", name);
}
#endif // WARRIOR_TUNED_PERIODS_MQH