Warrior_EA/Variables/TunedPeriods.mqh
AnimateDread 73b6ab9724 refactor(system): TunedPeriods reuses AltDataFileSymbol instead of re-implementing it
TunedPeriodsFileName() inlined the same 9-line StringReplace sanitizer
AltData.mqh already defines once as AltDataFileSymbol(), whose own
comment said it was meant for exactly this. Gave AltData.mqh a proper
include guard (it had none) and included it directly from
TunedPeriods.mqh so the call is safe regardless of include order.

Compile-verified 0 errors/0 warnings.
2026-08-24 01:31:14 -04:00

103 lines
5.6 KiB
MQL5

//+------------------------------------------------------------------+
//| TunedPeriods.mqh |
//| AnimateDread |
//| every consumer of "what period does this indicator run at". |
//+------------------------------------------------------------------+
#ifndef WARRIOR_TUNED_PERIODS_MQH
#define WARRIOR_TUNED_PERIODS_MQH
//--- AltDataFileSymbol() is the one shared broker-symbol -> safe-file-name-token sanitizer.
#include "..\System\AltData.mqh"
//--- Record format version, written as the 10th field. Bumped whenever a field's MEANING changes
//--- rather than its value; "2" marks MA type as ENUM_MA_METHOD codes. A file without it is v1.
#define TUNED_PERIODS_VERSION "2"
//--- 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)
{
//--- broker symbols can carry path-hostile characters ("EUR/USD"); writing through
//--- them fails or lands in an unintended subfolder - AltDataFileSymbol() (System\AltData.mqh)
//--- is the one shared sanitizer for every consumer that builds a path from a broker symbol.
string sym = AltDataFileSymbol(_Symbol);
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[];
int fields = StringSplit(line, ';', f);
if(fields < 9)
{
Print("TunedPeriods: " + name + " is malformed ('" + line + "') - keeping the seed defaults.");
return;
}
//--- Field 9 is the format version, absent in files written before the ADMovingAverage removal. Those
//--- store MA type in the retired 0..8 scheme, where the four surviving types sat at 5..8 - see
//--- SanitizeMaType(). Everything else in the record is unaffected and carries over.
bool legacy = (fields < 10 || f[9] != TUNED_PERIODS_VERSION);
g_TunedMaPeriod = (int)StringToInteger(f[0]);
g_TunedMaType = SanitizeMaType((int)StringToInteger(f[1]), legacy);
if(legacy)
PrintFormat("TunedPeriods: %s predates the built-in-MA switch - MA type %d remapped to %d. "
"The five advanced types (ALMA/DEMA/ZLEMA/T3/Kalman) no longer exist; a file that "
"stored one falls back to SMA.", name, (int)StringToInteger(f[1]), g_TunedMaType);
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;%s\n",
maPeriod, maType, rsiPeriod, macdFast, macdSlow, macdSignal,
ichiTenkan, ichiKijun, ichiSenkou, TUNED_PERIODS_VERSION));
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