//+------------------------------------------------------------------+ //| TunedPeriods.mqh | //| AnimateDread | //| every consumer of "what period does this indicator run at". | //+------------------------------------------------------------------+ #ifndef WARRIOR_TUNED_PERIODS_MQH #define WARRIOR_TUNED_PERIODS_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 (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[]; 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